refactor: rewrite integration for git branch command

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2025-07-07 17:25:48 +08:00
parent b2aac68600
commit f7b2063e8d
8 changed files with 83 additions and 55 deletions

View File

@@ -3,9 +3,15 @@ using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class Branch
public class Branch : Command
{
public static async Task<bool> CreateAsync(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
public Branch(string repo)
{
WorkingDirectory = repo;
Context = repo;
}
public async Task<bool> CreateAsync(string name, string basedOn, bool force)
{
var builder = new StringBuilder();
builder.Append("branch ");
@@ -15,61 +21,36 @@ namespace SourceGit.Commands
builder.Append(" ");
builder.Append(basedOn);
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = builder.ToString();
cmd.Log = log;
return await cmd.ExecAsync().ConfigureAwait(false);
Args = builder.ToString();
return await ExecAsync().ConfigureAwait(false);
}
public static async Task<bool> RenameAsync(string repo, string name, string to, Models.ICommandLog log)
public async Task<bool> RenameAsync(string name, string to)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -M {name} {to}";
cmd.Log = log;
return await cmd.ExecAsync().ConfigureAwait(false);
Args = $"branch -M {name} {to}";
return await ExecAsync().ConfigureAwait(false);
}
public static async Task<bool> SetUpstreamAsync(string repo, string name, string upstream, Models.ICommandLog log)
public async Task<bool> SetUpstreamAsync(string name, string upstream)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Log = log;
if (string.IsNullOrEmpty(upstream))
cmd.Args = $"branch {name} --unset-upstream";
Args = $"branch {name} --unset-upstream";
else
cmd.Args = $"branch {name} -u {upstream}";
Args = $"branch {name} -u {upstream}";
return await cmd.ExecAsync().ConfigureAwait(false);
return await ExecAsync().ConfigureAwait(false);
}
public static async Task<bool> DeleteLocalAsync(string repo, string name, Models.ICommandLog log)
public async Task<bool> DeleteLocalAsync(string name)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D {name}";
cmd.Log = log;
return await cmd.ExecAsync().ConfigureAwait(false);
Args = $"branch -D {name}";
return await ExecAsync().ConfigureAwait(false);
}
public static async Task<bool> DeleteRemoteAsync(string repo, string remote, string name, Models.ICommandLog log)
public async Task<bool> DeleteRemoteAsync(string remote, string name)
{
bool exists = await new Remote(repo).HasBranchAsync(remote, name).ConfigureAwait(false);
if (exists)
return await new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.RunAsync().ConfigureAwait(false);
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D -r {remote}/{name}";
cmd.Log = log;
return await cmd.ExecAsync().ConfigureAwait(false);
Args = $"branch -D -r {remote}/{name}";
return await ExecAsync().ConfigureAwait(false);
}
}
}

View File

@@ -187,7 +187,9 @@ namespace SourceGit.ViewModels
}
else
{
succ = await Commands.Branch.CreateAsync(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.CreateAsync(fixedName, _baseOnRevision, _allowOverwrite);
}
log.Complete();

View File

@@ -49,22 +49,42 @@ namespace SourceGit.ViewModels
if (Target.IsLocal)
{
await Commands.Branch.DeleteLocalAsync(_repo.FullPath, Target.Name, log);
await new Commands.Branch(_repo.FullPath)
.Use(log)
.DeleteLocalAsync(Target.Name);
if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
await DeleteRemoteBranchAsync(TrackingRemoteBranch, log);
}
else
{
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, Target.Remote, Target.Name, log);
await DeleteRemoteBranchAsync(Target, log);
}
log.Complete();
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
return true;
}
private async Task DeleteRemoteBranchAsync(Models.Branch branch, CommandLog log)
{
var exists = await new Commands.Remote(_repo.FullPath)
.HasBranchAsync(branch.Remote, branch.Name)
.ConfigureAwait(false);
if (exists)
await new Commands.Push(_repo.FullPath, branch.Remote, $"refs/heads/{branch.Name}", true)
.Use(log)
.RunAsync()
.ConfigureAwait(false);
else
await new Commands.Branch(_repo.FullPath)
.Use(log)
.DeleteRemoteAsync(branch.Remote, branch.Name)
.ConfigureAwait(false);
}
private readonly Repository _repo = null;
private bool _alsoDeleteTrackingRemote = false;
}

View File

@@ -28,12 +28,24 @@ namespace SourceGit.ViewModels
if (_isLocal)
{
foreach (var target in Targets)
await Commands.Branch.DeleteLocalAsync(_repo.FullPath, target.Name, log);
await new Commands.Branch(_repo.FullPath)
.Use(log)
.DeleteLocalAsync(target.Name);
}
else
{
foreach (var target in Targets)
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, target.Remote, target.Name, log);
{
var exists = await new Commands.Remote(_repo.FullPath).HasBranchAsync(target.Remote, target.Name);
if (exists)
await new Commands.Push(_repo.FullPath, target.Remote, $"refs/heads/{target.Name}", true)
.Use(log)
.RunAsync();
else
await new Commands.Branch(_repo.FullPath)
.Use(log)
.DeleteRemoteAsync(target.Remote, target.Name);
}
}
log.Complete();

View File

@@ -114,7 +114,9 @@ namespace SourceGit.ViewModels
var masterBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_master, StringComparison.Ordinal));
if (masterBranch == null)
{
succ = await Commands.Branch.CreateAsync(_repo.FullPath, _master, current.Head, true, log);
succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.CreateAsync(_master, current.Head, true);
if (!succ)
{
log.Complete();
@@ -126,7 +128,9 @@ namespace SourceGit.ViewModels
var developBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_develop, StringComparison.Ordinal));
if (developBranch == null)
{
succ = await Commands.Branch.CreateAsync(_repo.FullPath, _develop, current.Head, true, log);
succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.CreateAsync(_develop, current.Head, true);
if (!succ)
{
log.Complete();

View File

@@ -57,7 +57,10 @@ namespace SourceGit.ViewModels
var isCurrent = Target.IsCurrent;
var oldName = Target.FullName;
var succ = await Commands.Branch.RenameAsync(_repo.FullPath, Target.Name, fixedName, log);
var succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.RenameAsync(Target.Name, fixedName);
if (succ)
{
foreach (var filter in _repo.Settings.HistoriesFilters)

View File

@@ -38,8 +38,12 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Reset '{Target.Name}' to '{_revision}'");
Use(log);
var succ = await Commands.Branch.CreateAsync(_repo.FullPath, Target.Name, _revision, true, log);
var succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.CreateAsync(Target.Name, _revision, true);
log.Complete();
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
return succ;
}

View File

@@ -61,9 +61,11 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Set Upstream");
Use(log);
var succ = await Commands.Branch.SetUpstreamAsync(_repo.FullPath, Local.Name, upstream.Replace("refs/remotes/", ""), log);
log.Complete();
var succ = await new Commands.Branch(_repo.FullPath)
.Use(log)
.SetUpstreamAsync(Local.Name, upstream.Replace("refs/remotes/", ""));
log.Complete();
if (succ)
_repo.MarkBranchesDirtyManually();
return true;