enhance: ensure sourcegit_rebase_jobs.json only being used when orig-head and onto are both matched

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-04-18 12:49:19 +08:00
parent 75b4a4b294
commit 413669741d
No known key found for this signature in database
4 changed files with 35 additions and 36 deletions

View file

@ -6,6 +6,7 @@ using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -431,21 +432,37 @@ namespace SourceGit
return true; return true;
var gitDir = Path.GetDirectoryName(file)!; var gitDir = Path.GetDirectoryName(file)!;
var jobsFile = Path.Combine(gitDir, "sourcegit_rebase_jobs.json"); var origHeadFile = Path.Combine(gitDir, "rebase-merge", "orig-head");
if (!File.Exists(jobsFile)) var ontoFile = Path.Combine(gitDir, "rebase-merge", "onto");
return true;
var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection);
var doneFile = Path.Combine(gitDir, "rebase-merge", "done"); 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; return true;
var done = File.ReadAllText(doneFile).Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); var origHead = File.ReadAllText(origHeadFile).Trim();
if (done.Length > collection.Jobs.Count) 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; return true;
var job = collection.Jobs[done.Length - 1]; 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); File.WriteAllText(file, job.Message);
break;
}
}
return true; return true;
} }
@ -621,6 +638,9 @@ namespace SourceGit
return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; 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 Models.IpcChannel _ipcChannel = null;
private ViewModels.Launcher _launcher = null; private ViewModels.Launcher _launcher = null;
private ResourceDictionary _activeLocale = null; private ResourceDictionary _activeLocale = null;

View file

@ -27,6 +27,8 @@ namespace SourceGit.Models
public class InteractiveRebaseJobCollection public class InteractiveRebaseJobCollection
{ {
public string OrigHead { get; set; } = string.Empty;
public string Onto { get; set; } = string.Empty;
public List<InteractiveRebaseJob> Jobs { get; set; } = new List<InteractiveRebaseJob>(); public List<InteractiveRebaseJob> Jobs { get; set; } = new List<InteractiveRebaseJob>();
} }
} }

View file

@ -105,8 +105,6 @@ namespace SourceGit.ViewModels
public RebaseInProgress(Repository repo) : base(repo.FullPath, "rebase") public RebaseInProgress(Repository repo) : base(repo.FullPath, "rebase")
{ {
_gitDir = repo.GitDir;
HeadName = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "head-name")).Trim(); HeadName = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "head-name")).Trim();
if (HeadName.StartsWith("refs/heads/")) if (HeadName.StartsWith("refs/heads/"))
HeadName = HeadName.Substring(11); HeadName = HeadName.Substring(11);
@ -129,34 +127,14 @@ namespace SourceGit.ViewModels
public override bool Continue() public override bool Continue()
{ {
var succ = new Commands.Command() return new Commands.Command()
{ {
WorkingDirectory = _repo, WorkingDirectory = _repo,
Context = _repo, Context = _repo,
Editor = Commands.Command.EditorType.RebaseEditor, Editor = Commands.Command.EditorType.RebaseEditor,
Args = $"rebase --continue", Args = $"rebase --continue",
}.Exec(); }.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 public class RevertInProgress : InProgressContext

View file

@ -162,6 +162,8 @@ namespace SourceGit.ViewModels
var saveFile = Path.Combine(_repo.GitDir, "sourcegit_rebase_jobs.json"); var saveFile = Path.Combine(_repo.GitDir, "sourcegit_rebase_jobs.json");
var collection = new Models.InteractiveRebaseJobCollection(); var collection = new Models.InteractiveRebaseJobCollection();
collection.OrigHead = _repo.CurrentBranch.Head;
collection.Onto = On.SHA;
for (int i = Items.Count - 1; i >= 0; i--) for (int i = Items.Count - 1; i >= 0; i--)
{ {
var item = Items[i]; var item = Items[i];
@ -178,9 +180,6 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).Exec(); var succ = new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).Exec();
if (succ)
File.Delete(saveFile);
log.Complete(); log.Complete();
Dispatcher.UIThread.Invoke(() => _repo.SetWatcherEnabled(true)); Dispatcher.UIThread.Invoke(() => _repo.SetWatcherEnabled(true));
return succ; return succ;