From 413669741ddcf402c886d4f6af6a82c17292c691 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 18 Apr 2025 12:49:19 +0800 Subject: [PATCH] enhance: ensure `sourcegit_rebase_jobs.json` only being used when `orig-head` and `onto` are both matched Signed-off-by: leo --- src/App.axaml.cs | 40 +++++++++++++++++++++------- src/Models/InteractiveRebase.cs | 2 ++ src/ViewModels/InProgressContexts.cs | 24 +---------------- src/ViewModels/InteractiveRebase.cs | 5 ++-- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index ef9398d9..c659388a 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Reflection; using System.Text; using System.Text.Json; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -431,21 +432,37 @@ namespace SourceGit return true; var gitDir = Path.GetDirectoryName(file)!; - var jobsFile = Path.Combine(gitDir, "sourcegit_rebase_jobs.json"); - if (!File.Exists(jobsFile)) - return true; - - var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection); + var origHeadFile = Path.Combine(gitDir, "rebase-merge", "orig-head"); + var ontoFile = Path.Combine(gitDir, "rebase-merge", "onto"); var doneFile = Path.Combine(gitDir, "rebase-merge", "done"); - if (!File.Exists(doneFile)) + var jobsFile = Path.Combine(gitDir, "sourcegit_rebase_jobs.json"); + if (!File.Exists(ontoFile) || !File.Exists(origHeadFile) || !File.Exists(doneFile) || !File.Exists(jobsFile)) return true; - var done = File.ReadAllText(doneFile).Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); - if (done.Length > collection.Jobs.Count) + var origHead = File.ReadAllText(origHeadFile).Trim(); + var onto = File.ReadAllText(ontoFile).Trim(); + var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection); + if (!collection.Onto.Equals(onto) || !collection.OrigHead.Equals(origHead)) return true; - var job = collection.Jobs[done.Length - 1]; - File.WriteAllText(file, job.Message); + var done = File.ReadAllText(doneFile).Trim().Split([ '\r', '\n' ], StringSplitOptions.RemoveEmptyEntries); + if (done.Length == 0) + return true; + + var current = done[^1].Trim(); + var match = REG_REBASE_TODO().Match(current); + if (!match.Success) + return true; + + var sha = match.Groups[1].Value; + foreach (var job in collection.Jobs) + { + if (job.SHA.StartsWith(sha)) + { + File.WriteAllText(file, job.Message); + break; + } + } return true; } @@ -621,6 +638,9 @@ namespace SourceGit return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; } + [GeneratedRegex(@"^[a-z]+\s+([a-fA-F0-9]{4,40})(\s+.*)?$")] + private static partial Regex REG_REBASE_TODO(); + private Models.IpcChannel _ipcChannel = null; private ViewModels.Launcher _launcher = null; private ResourceDictionary _activeLocale = null; diff --git a/src/Models/InteractiveRebase.cs b/src/Models/InteractiveRebase.cs index 691aadeb..d1710d4a 100644 --- a/src/Models/InteractiveRebase.cs +++ b/src/Models/InteractiveRebase.cs @@ -27,6 +27,8 @@ namespace SourceGit.Models public class InteractiveRebaseJobCollection { + public string OrigHead { get; set; } = string.Empty; + public string Onto { get; set; } = string.Empty; public List Jobs { get; set; } = new List(); } } diff --git a/src/ViewModels/InProgressContexts.cs b/src/ViewModels/InProgressContexts.cs index 24b07332..593b2a72 100644 --- a/src/ViewModels/InProgressContexts.cs +++ b/src/ViewModels/InProgressContexts.cs @@ -105,8 +105,6 @@ namespace SourceGit.ViewModels public RebaseInProgress(Repository repo) : base(repo.FullPath, "rebase") { - _gitDir = repo.GitDir; - HeadName = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "head-name")).Trim(); if (HeadName.StartsWith("refs/heads/")) HeadName = HeadName.Substring(11); @@ -129,34 +127,14 @@ namespace SourceGit.ViewModels public override bool Continue() { - var succ = new Commands.Command() + return new Commands.Command() { WorkingDirectory = _repo, Context = _repo, Editor = Commands.Command.EditorType.RebaseEditor, Args = $"rebase --continue", }.Exec(); - - if (succ) - { - var jobsFile = Path.Combine(_gitDir, "sourcegit_rebase_jobs.json"); - var rebaseMergeHead = Path.Combine(_gitDir, "REBASE_HEAD"); - var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); - var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply"); - if (File.Exists(jobsFile)) - File.Delete(jobsFile); - if (File.Exists(rebaseMergeHead)) - File.Delete(rebaseMergeHead); - if (Directory.Exists(rebaseMergeFolder)) - Directory.Delete(rebaseMergeFolder); - if (Directory.Exists(rebaseApplyFolder)) - Directory.Delete(rebaseApplyFolder); - } - - return succ; } - - private string _gitDir; } public class RevertInProgress : InProgressContext diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index f9ae06b5..0e77eecf 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -162,6 +162,8 @@ namespace SourceGit.ViewModels var saveFile = Path.Combine(_repo.GitDir, "sourcegit_rebase_jobs.json"); var collection = new Models.InteractiveRebaseJobCollection(); + collection.OrigHead = _repo.CurrentBranch.Head; + collection.Onto = On.SHA; for (int i = Items.Count - 1; i >= 0; i--) { var item = Items[i]; @@ -178,9 +180,6 @@ namespace SourceGit.ViewModels return Task.Run(() => { var succ = new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).Exec(); - if (succ) - File.Delete(saveFile); - log.Complete(); Dispatcher.UIThread.Invoke(() => _repo.SetWatcherEnabled(true)); return succ;