refactor: rewrite checkout/create branch with submodules

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-05-09 17:51:46 +08:00
parent e446e97f28
commit 0f6c8976af
No known key found for this signature in database
8 changed files with 136 additions and 65 deletions

View file

@ -11,18 +11,27 @@ namespace SourceGit.Commands
Context = repo;
}
public bool Branch(string branch)
public bool Branch(string branch, bool force)
{
Args = $"checkout --progress {branch}";
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --progress {branch}";
return Exec();
}
public bool Branch(string branch, string basedOn)
public bool Branch(string branch, string basedOn, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout --progress -b {branch} {basedOn}";
return Exec();
}
public bool Commit(string commitId, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --detach --progress {commitId}";
return Exec();
}
public bool UseTheirs(List<string> files)
{
var builder = new StringBuilder();
@ -56,11 +65,5 @@ namespace SourceGit.Commands
Args = $"checkout --no-overlay {revision} -- \"{file}\"";
return Exec();
}
public bool Commit(string commitId)
{
Args = $"checkout --detach --progress {commitId}";
return Exec();
}
}
}

View file

@ -1,4 +1,7 @@
namespace SourceGit.Commands
using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands
{
public class Submodule : Command
{
@ -42,6 +45,28 @@
return Exec();
}
public bool Update(List<Models.Submodule> modules, bool init, bool recursive, bool useRemote)
{
var builder = new StringBuilder();
builder.Append("submodule update");
if (init)
builder.Append(" --init");
if (recursive)
builder.Append(" --recursive");
if (useRemote)
builder.Append(" --remote");
if (modules.Count > 0)
{
builder.Append(" --");
foreach (var module in modules)
builder.Append($" \"{module.Path}\"");
}
Args = builder.ToString();
return Exec();
}
public bool Delete(string relativePath)
{
Args = $"submodule deinit -f \"{relativePath}\"";

View file

@ -46,17 +46,19 @@ namespace SourceGit.ViewModels
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var succ = false;
var needPopStash = false;
if (changes > 0)
if (DiscardLocalChanges)
{
if (DiscardLocalChanges)
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
@ -66,18 +68,22 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, false);
}
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch);
if (rs && updateSubmodules)
if (succ)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
foreach (var submodule in submodules)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodule.Path, true, true, false);
}
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (rs && needPopStash)
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete();
@ -94,7 +100,7 @@ namespace SourceGit.ViewModels
});
Task.Delay(400).Wait();
return rs;
return succ;
});
}

View file

@ -15,11 +15,24 @@ namespace SourceGit.ViewModels
set;
}
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public CheckoutCommit(Repository repo, Models.Commit commit)
{
_repo = repo;
Commit = commit;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public override Task<bool> Sure()
@ -30,19 +43,22 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Checkout Commit");
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false;
if (changes > 0)
var succ = false;
var needPop = false;
if (DiscardLocalChanges)
{
if (DiscardLocalChanges)
succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
@ -50,17 +66,28 @@ namespace SourceGit.ViewModels
return false;
}
needPopStash = true;
needPop = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, false);
}
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA);
if (needPopStash)
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (needPop)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return rs;
return succ;
});
}

View file

@ -141,8 +141,8 @@ namespace SourceGit.ViewModels
if (InitAndUpdateSubmodules)
{
var submodules = new Commands.QuerySubmodules(path).Result();
foreach (var submodule in submodules)
new Commands.Submodule(path).Use(log).Update(submodule.Path, true, true, false);
if (submodules.Count > 0)
new Commands.Submodule(path).Use(log).Update(submodules, true, true, false);
}
log.Complete();

View file

@ -864,7 +864,7 @@ namespace SourceGit.ViewModels
{
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(path, $"{_commit.SHA}");
log.Complete();
});
});
}
private Task ResetToParentRevision(Models.Change change)

View file

@ -117,18 +117,18 @@ namespace SourceGit.ViewModels
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
bool succ;
bool succ = false;
if (CheckoutAfterCreated && !_repo.IsBare)
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false;
if (changes > 0)
if (DiscardLocalChanges)
{
if (DiscardLocalChanges)
{
Commands.Discard.All(_repo.FullPath, false, log);
}
else
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
if (!succ)
@ -140,18 +140,22 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false);
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision);
if (succ && updateSubmodules)
if (succ)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
foreach (var submodule in submodules)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodule.Path, true, true, false);
}
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (succ && needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
}
else
{
@ -174,6 +178,8 @@ namespace SourceGit.ViewModels
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
ProgressDescription = "Waiting for branch updated...";
}
_repo.MarkBranchesDirtyManually();
@ -181,10 +187,7 @@ namespace SourceGit.ViewModels
});
if (CheckoutAfterCreated)
{
CallUIThread(() => ProgressDescription = "Waiting for branch updated...");
Task.Delay(400).Wait();
}
return true;
});

View file

@ -12,7 +12,7 @@
Classes="bold"
Text="{DynamicResource Text.Checkout.Commit}" />
<Grid Margin="0,16,0,0" RowDefinitions="32,Auto,Auto" ColumnDefinitions="Auto,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,Auto,Auto,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -36,7 +36,14 @@
GroupName="LocalChanges"/>
</StackPanel>
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="Auto,*" Margin="0,6,0,0">
<CheckBox Grid.Row="2" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsRecurseSubmoduleVisible}"
ToolTip.Tip="--recurse-submodules"/>
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="Auto,*" Margin="0,6,0,0">
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.Error}"