feature: git command logs

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-04-17 12:30:20 +08:00
parent 928a0ad3c5
commit 8b39df32cc
No known key found for this signature in database
101 changed files with 1040 additions and 573 deletions

View file

@ -93,15 +93,19 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding remote ...";
var log = _repo.CreateLog("Add Remote");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Remote(_repo.FullPath).Add(_name, _url);
var succ = new Commands.Remote(_repo.FullPath).Use(log).Add(_name, _url);
if (succ)
{
SetProgressDescription("Fetching from added remote ...");
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
new Commands.Fetch(_repo.FullPath, _name, false, false, SetProgressDescription).Exec();
new Commands.Config(_repo.FullPath).Use(log).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
new Commands.Fetch(_repo.FullPath, _name, false, false).Use(log).Exec();
}
log.Complete();
CallUIThread(() =>
{
_repo.MarkFetched();

View file

@ -61,9 +61,14 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding submodule...";
var log = _repo.CreateLog("Add Submodule");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Add(_url, _relativePath, Recursive, SetProgressDescription);
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Add(_url, _relativePath, Recursive);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -114,10 +114,15 @@ namespace SourceGit.ViewModels
var branchName = _selectedBranch;
var tracking = _setTrackingBranch ? SelectedTrackingBranch : string.Empty;
var log = _repo.CreateLog("Add Worktree");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Worktree(_repo.FullPath).Add(_path, branchName, _createNewBranch, tracking, SetProgressDescription);
var succ = new Commands.Worktree(_repo.FullPath).Use(log).Add(_path, branchName, _createNewBranch, tracking);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -47,9 +47,12 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Apply patch...";
var log = _repo.CreateLog("Apply Patch");
return Task.Run(() =>
{
var succ = new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Exec();
var succ = new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -22,7 +22,7 @@ namespace SourceGit.ViewModels
set;
} = false;
public ApplyStash(string repo, Models.Stash stash)
public ApplyStash(Repository repo, Models.Stash stash)
{
_repo = repo;
Stash = stash;
@ -33,16 +33,18 @@ namespace SourceGit.ViewModels
{
ProgressDescription = $"Applying stash: {Stash.Name}";
var log = _repo.CreateLog("Apply Stash");
return Task.Run(() =>
{
var succ = new Commands.Stash(_repo).Apply(Stash.Name, RestoreIndex);
var succ = new Commands.Stash(_repo.FullPath).Use(log).Apply(Stash.Name, RestoreIndex);
if (succ && DropAfterApply)
new Commands.Stash(_repo).Drop(Stash.Name);
new Commands.Stash(_repo.FullPath).Use(log).Drop(Stash.Name);
log.Complete();
return true;
});
}
private readonly string _repo;
private readonly Repository _repo;
}
}

View file

@ -51,9 +51,14 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Archiving ...";
var log = _repo.CreateLog("Archive");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Archive(_repo.FullPath, _revision, _saveFile, SetProgressDescription).Exec();
var succ = new Commands.Archive(_repo.FullPath, _revision, _saveFile).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.SetWatcherEnabled(true);

View file

@ -16,11 +16,8 @@ namespace SourceGit.ViewModels
Task.Run(() =>
{
var collect = new Commands.AssumeUnchanged(_repo).View();
Dispatcher.UIThread.Invoke(() =>
{
Files.AddRange(collect);
});
var collect = new Commands.QueryAssumeUnchangedFiles(_repo).Result();
Dispatcher.UIThread.Invoke(() => Files.AddRange(collect));
});
}
@ -28,7 +25,7 @@ namespace SourceGit.ViewModels
{
if (!string.IsNullOrEmpty(file))
{
new Commands.AssumeUnchanged(_repo).Remove(file);
new Commands.AssumeUnchanged(_repo, file, false).Exec();
Files.Remove(file);
}
}

View file

@ -28,6 +28,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout '{Branch}' ...";
var log = _repo.CreateLog($"Checkout '{Branch}'");
Use(log);
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
@ -36,15 +39,14 @@ namespace SourceGit.ViewModels
{
if (DiscardLocalChanges)
{
SetProgressDescription("Discard local changes ...");
Commands.Discard.All(_repo.FullPath, false);
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
SetProgressDescription("Stash local changes ...");
var succ = new Commands.Stash(_repo.FullPath).Push("CHECKOUT_AUTO_STASH");
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -53,14 +55,11 @@ namespace SourceGit.ViewModels
}
}
SetProgressDescription("Checkout branch ...");
var rs = new Commands.Checkout(_repo.FullPath).Branch(Branch, SetProgressDescription);
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch);
if (needPopStash)
{
SetProgressDescription("Re-apply local changes...");
rs = new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
}
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
log.Complete();
CallUIThread(() =>
{

View file

@ -28,6 +28,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout Commit '{Commit.SHA}' ...";
var log = _repo.CreateLog("Checkout Commit");
Use(log);
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
@ -36,15 +39,14 @@ namespace SourceGit.ViewModels
{
if (DiscardLocalChanges)
{
SetProgressDescription("Discard local changes ...");
Commands.Discard.All(_repo.FullPath, false);
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
SetProgressDescription("Stash local changes ...");
var succ = new Commands.Stash(_repo.FullPath).Push("CHECKOUT_AUTO_STASH");
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -53,15 +55,11 @@ namespace SourceGit.ViewModels
}
}
SetProgressDescription("Checkout commit ...");
var rs = new Commands.Checkout(_repo.FullPath).Commit(Commit.SHA, SetProgressDescription);
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA);
if (needPopStash)
{
SetProgressDescription("Re-apply local changes...");
rs = new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
}
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return rs;
});

View file

@ -70,6 +70,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Cherry-Pick commit(s) ...";
var log = _repo.CreateLog("Cherry-Pick");
Use(log);
return Task.Run(() =>
{
if (IsMergeCommit)
@ -79,7 +82,7 @@ namespace SourceGit.ViewModels
Targets[0].SHA,
!AutoCommit,
AppendSourceToMessage,
$"-m {MainlineForMergeCommit + 1}").Exec();
$"-m {MainlineForMergeCommit + 1}").Use(log).Exec();
}
else
{
@ -88,9 +91,10 @@ namespace SourceGit.ViewModels
string.Join(' ', Targets.ConvertAll(c => c.SHA)),
!AutoCommit,
AppendSourceToMessage,
string.Empty).Exec();
string.Empty).Use(log).Exec();
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -15,9 +15,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Cleanup (GC & prune) ...";
var log = _repo.CreateLog("Cleanup (GC & prune)");
Use(log);
return Task.Run(() =>
{
new Commands.GC(_repo.FullPath, SetProgressDescription).Exec();
new Commands.GC(_repo.FullPath).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -15,9 +15,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Clear all stashes...";
var log = _repo.CreateLog("Clear Stashes");
Use(log);
return Task.Run(() =>
{
new Commands.Stash(_repo.FullPath).Clear();
new Commands.Stash(_repo.FullPath).Use(log).Clear();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -103,9 +103,13 @@ namespace SourceGit.ViewModels
{
ProgressDescription = "Clone ...";
// Create a temp log.
var log = new CommandLog("Clone");
Use(log);
return Task.Run(() =>
{
var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs, SetProgressDescription);
var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs).Use(log);
if (!cmd.Exec())
return false;
@ -142,12 +146,11 @@ namespace SourceGit.ViewModels
{
var submoduleList = new Commands.QuerySubmodules(path).Result();
foreach (var submodule in submoduleList)
{
var update = new Commands.Submodule(path);
update.Update(submodule.Path, true, true, false, SetProgressDescription);
}
new Commands.Submodule(path).Use(log).Update(submodule.Path, true, true, false);
}
log.Complete();
CallUIThread(() =>
{
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);

View file

@ -0,0 +1,87 @@
using System;
using System.Text;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class CommandLog : ObservableObject, Models.ICommandLog
{
public string Name
{
get;
private set;
} = string.Empty;
public DateTime Time
{
get;
} = DateTime.Now;
public string TimeStr
{
get => Time.ToString("T");
}
public bool IsComplete
{
get;
private set;
} = false;
public string Content
{
get
{
return IsComplete ? _content : _builder.ToString();
}
}
public CommandLog(string name)
{
Name = name;
}
public void Register(Action<string> handler)
{
if (!IsComplete)
_onNewLineReceived += handler;
}
public void AppendLine(string line = null)
{
var newline = line ?? string.Empty;
Dispatcher.UIThread.Invoke(() =>
{
_builder.AppendLine(newline);
_onNewLineReceived?.Invoke(newline);
});
}
public void Complete()
{
IsComplete = true;
Dispatcher.UIThread.Invoke(() =>
{
_content = _builder.ToString();
_builder.Clear();
_builder = null;
OnPropertyChanged(nameof(IsComplete));
if (_onNewLineReceived != null)
{
var dumpHandlers = _onNewLineReceived.GetInvocationList();
foreach (var d in dumpHandlers)
_onNewLineReceived -= (Action<string>)d;
}
});
}
private string _content = string.Empty;
private StringBuilder _builder = new StringBuilder();
private event Action<string> _onNewLineReceived;
}
}

View file

@ -46,7 +46,7 @@
_wc = wc;
_change = change;
IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).ReadToEnd().IsSuccess;
IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).Result();
var context = wc.InProgressContext;
if (context is CherryPickInProgress cherryPick)

View file

@ -92,6 +92,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
var fixedName = FixName(_name);
var log = _repo.CreateLog($"Create Branch '{fixedName}'");
Use(log);
return Task.Run(() =>
{
var succ = false;
@ -103,15 +106,14 @@ namespace SourceGit.ViewModels
{
if (DiscardLocalChanges)
{
SetProgressDescription("Discard local changes...");
Commands.Discard.All(_repo.FullPath, false);
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
SetProgressDescription("Stash local changes");
succ = new Commands.Stash(_repo.FullPath).Push("CREATE_BRANCH_AUTO_STASH");
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -120,21 +122,17 @@ namespace SourceGit.ViewModels
}
}
SetProgressDescription($"Create new branch '{fixedName}'");
succ = new Commands.Checkout(_repo.FullPath).Branch(fixedName, _baseOnRevision, SetProgressDescription);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision);
if (needPopStash)
{
SetProgressDescription("Re-apply local changes...");
new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
}
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
else
{
SetProgressDescription($"Create new branch '{fixedName}'");
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision);
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, log);
}
log.Complete();
CallUIThread(() =>
{
if (succ && CheckoutAfterCreated)

View file

@ -83,23 +83,24 @@ namespace SourceGit.ViewModels
ProgressDescription = "Create tag...";
var remotes = PushToRemotes ? _repo.Remotes : null;
var log = _repo.CreateLog("Create Tag");
Use(log);
return Task.Run(() =>
{
bool succ;
if (_annotated)
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, Message, SignTag);
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log);
else
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn);
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, log);
if (succ && remotes != null)
{
foreach (var remote in remotes)
{
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Exec();
}
new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Use(log).Exec();
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -48,23 +48,25 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting branch...";
var log = _repo.CreateLog("Delete Branch");
Use(log);
return Task.Run(() =>
{
if (Target.IsLocal)
{
Commands.Branch.DeleteLocal(_repo.FullPath, Target.Name);
Commands.Branch.DeleteLocal(_repo.FullPath, Target.Name, log);
if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
{
SetProgressDescription("Deleting remote-tracking branch...");
Commands.Branch.DeleteRemote(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name);
}
Commands.Branch.DeleteRemote(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
}
else
{
Commands.Branch.DeleteRemote(_repo.FullPath, Target.Remote, Target.Name);
Commands.Branch.DeleteRemote(_repo.FullPath, Target.Remote, Target.Name, log);
}
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();

View file

@ -23,25 +23,24 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting multiple branches...";
var log = _repo.CreateLog("Delete Multiple Branches");
Use(log);
return Task.Run(() =>
{
if (_isLocal)
{
foreach (var target in Targets)
{
SetProgressDescription($"Deleting local branch : {target.Name}");
Commands.Branch.DeleteLocal(_repo.FullPath, target.Name);
}
Commands.Branch.DeleteLocal(_repo.FullPath, target.Name, log);
}
else
{
foreach (var target in Targets)
{
SetProgressDescription($"Deleting remote branch : {target.FriendlyName}");
Commands.Branch.DeleteRemote(_repo.FullPath, target.Remote, target.Name);
}
Commands.Branch.DeleteRemote(_repo.FullPath, target.Remote, target.Name, log);
}
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();

View file

@ -22,9 +22,14 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting remote ...";
var log = _repo.CreateLog("Delete Remote");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Remote(_repo.FullPath).Delete(Remote.Name);
var succ = new Commands.Remote(_repo.FullPath).Use(log).Delete(Remote.Name);
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();

View file

@ -23,9 +23,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting submodule ...";
var log = _repo.CreateLog("Delete Submodule");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Delete(Submodule);
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Delete(Submodule);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -28,10 +28,21 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Deleting tag '{Target.Name}' ...";
var remotes = PushToRemotes ? _repo.Remotes : null;
var remotes = PushToRemotes ? _repo.Remotes : [];
var log = _repo.CreateLog("Delete Tag");
Use(log);
return Task.Run(() =>
{
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes);
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, log);
if (succ)
{
foreach (var r in remotes)
new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true).Use(log).Exec();
}
log.Complete();
CallUIThread(() =>
{
_repo.MarkTagsDirtyManually();

View file

@ -65,12 +65,17 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = _changes == null ? "Discard all local changes ..." : $"Discard total {_changes.Count} changes ...";
var log = _repo.CreateLog("Discard all");
Use(log);
return Task.Run(() =>
{
if (Mode is DiscardAllMode all)
Commands.Discard.All(_repo.FullPath, all.IncludeIgnored);
Commands.Discard.All(_repo.FullPath, all.IncludeIgnored, log);
else
Commands.Discard.Changes(_repo.FullPath, _changes);
Commands.Discard.Changes(_repo.FullPath, _changes, log);
log.Complete();
CallUIThread(() =>
{

View file

@ -6,7 +6,7 @@ namespace SourceGit.ViewModels
{
public Models.Stash Stash { get; private set; }
public DropStash(string repo, Models.Stash stash)
public DropStash(Repository repo, Models.Stash stash)
{
_repo = repo;
Stash = stash;
@ -17,13 +17,17 @@ namespace SourceGit.ViewModels
{
ProgressDescription = $"Dropping stash: {Stash.Name}";
var log = _repo.CreateLog("Drop Stash");
Use(log);
return Task.Run(() =>
{
new Commands.Stash(_repo).Drop(Stash.Name);
new Commands.Stash(_repo.FullPath).Use(log).Drop(Stash.Name);
log.Complete();
return true;
});
}
private readonly string _repo;
private readonly Repository _repo;
}
}

View file

@ -127,7 +127,6 @@ namespace SourceGit.ViewModels
if (pushURL != _url)
new Commands.Remote(_repo.FullPath).SetURL(_name, _url, true);
SetProgressDescription("Post processing ...");
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
CallUIThread(() => _repo.SetWatcherEnabled(true));

View file

@ -43,7 +43,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
if (CustomAction.WaitForExit)
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription);
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, output => CallUIThread(() => ProgressDescription = output));
else
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args);

View file

@ -29,9 +29,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fast-Forward ...";
var log = _repo.CreateLog("Fast-Forward (No checkout)");
Use(log);
return Task.Run(() =>
{
new Commands.UpdateRef(_repo.FullPath, Local.FullName, To.FullName, SetProgressDescription).Exec();
new Commands.UpdateRef(_repo.FullPath, Local.FullName, To.FullName).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToCommit(To.Head);

View file

@ -65,22 +65,23 @@ namespace SourceGit.ViewModels
var notags = _repo.Settings.FetchWithoutTags;
var force = _repo.Settings.EnableForceOnFetch;
var log = _repo.CreateLog("Fetch");
Use(log);
return Task.Run(() =>
{
if (FetchAllRemotes)
{
foreach (var remote in _repo.Remotes)
{
SetProgressDescription($"Fetching remote: {remote.Name}");
new Commands.Fetch(_repo.FullPath, remote.Name, notags, force, SetProgressDescription).Exec();
}
new Commands.Fetch(_repo.FullPath, remote.Name, notags, force).Use(log).Exec();
}
else
{
SetProgressDescription($"Fetching remote: {SelectedRemote.Name}");
new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force, SetProgressDescription).Exec();
new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force).Use(log).Exec();
}
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.Upstream);

View file

@ -29,9 +29,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fast-Forward ...";
var log = _repo.CreateLog($"Fetch Into '{Local.FriendlyName}'");
Use(log);
return Task.Run(() =>
{
new Commands.Fetch(_repo.FullPath, Local, Upstream, SetProgressDescription).Exec();
new Commands.Fetch(_repo.FullPath, Local, Upstream).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(Upstream.FullName);

View file

@ -33,11 +33,17 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
var name = Branch.Name.StartsWith(_prefix) ? Branch.Name.Substring(_prefix.Length) : Branch.Name;
ProgressDescription = $"Git Flow - finishing {_type} {name} ...";
var log = _repo.CreateLog("Gitflow - Finish");
Use(log);
return Task.Run(() =>
{
var name = Branch.Name.StartsWith(_prefix) ? Branch.Name.Substring(_prefix.Length) : Branch.Name;
SetProgressDescription($"Git Flow - finishing {_type} {name} ...");
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, KeepBranch);
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, KeepBranch, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -50,10 +50,15 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Git Flow - starting {_type} {_name} ...";
var log = _repo.CreateLog("Gitflow - Start");
Use(log);
return Task.Run(() =>
{
SetProgressDescription($"Git Flow - starting {_type} {_name} ...");
var succ = Commands.GitFlow.Start(_repo.FullPath, _type, _name);
var succ = Commands.GitFlow.Start(_repo.FullPath, _type, _name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -302,17 +302,20 @@ namespace SourceGit.ViewModels
var picker = await storageProvider.OpenFolderPickerAsync(options);
if (picker.Count == 1)
{
var log = _repo.CreateLog("Save as Patch");
var succ = false;
for (var i = 0; i < selected.Count; i++)
{
var saveTo = GetPatchFileName(picker[0].Path.LocalPath, selected[i], i);
succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, selected[i].SHA, saveTo).Exec());
succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, selected[i].SHA, saveTo).Use(log).Exec());
if (!succ)
break;
}
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
log.Complete();
}
}
catch (Exception exception)

View file

@ -30,19 +30,24 @@ namespace SourceGit.ViewModels
{
ProgressDescription = $"Initialize git repository at: '{_targetPath}'";
var log = new CommandLog("Initialize");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Init(_pageId, _targetPath).Exec();
if (!succ)
return false;
var succ = new Commands.Init(_pageId, _targetPath).Use(log).Exec();
log.Complete();
CallUIThread(() =>
if (succ)
{
Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true);
Welcome.Instance.Refresh();
});
CallUIThread(() =>
{
Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true);
Welcome.Instance.Refresh();
});
}
return true;
return succ;
});
}

View file

@ -106,9 +106,23 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Init git-flow ...";
var log = _repo.CreateLog("Gitflow - Init");
Use(log);
return Task.Run(() =>
{
var succ = Commands.GitFlow.Init(_repo.FullPath, _repo.Branches, _master, _develop, _featurePrefix, _releasePrefix, _hotfixPrefix, _tagPrefix);
var succ = Commands.GitFlow.Init(
_repo.FullPath,
_repo.Branches,
_master,
_develop,
_featurePrefix,
_releasePrefix,
_hotfixPrefix,
_tagPrefix,
log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -24,9 +24,14 @@ namespace SourceGit.ViewModels
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Fetching LFS objects from remote ...";
var log = _repo.CreateLog("LFS Fetch");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Fetch(SelectedRemote.Name, SetProgressDescription);
new Commands.LFS(_repo.FullPath).Fetch(SelectedRemote.Name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -15,9 +15,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "LFS prune ...";
var log = _repo.CreateLog("LFS Prune");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Prune(SetProgressDescription);
new Commands.LFS(_repo.FullPath).Prune(log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -24,9 +24,14 @@ namespace SourceGit.ViewModels
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Pull LFS objects from remote ...";
var log = _repo.CreateLog("LFS Pull");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Pull(SelectedRemote.Name, SetProgressDescription);
new Commands.LFS(_repo.FullPath).Pull(SelectedRemote.Name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -24,9 +24,14 @@ namespace SourceGit.ViewModels
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Push LFS objects to remote ...";
var log = _repo.CreateLog("LFS Push");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Push(SelectedRemote.Name, SetProgressDescription);
new Commands.LFS(_repo.FullPath).Push(SelectedRemote.Name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -29,9 +29,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding custom LFS tracking pattern ...";
var log = _repo.CreateLog("LFS Add Custom Pattern");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.LFS(_repo.FullPath).Track(_pattern, IsFilename);
var succ = new Commands.LFS(_repo.FullPath).Track(_pattern, IsFilename, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -59,9 +59,14 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Merging '{_sourceName}' into '{Into}' ...";
var log = _repo.CreateLog($"Merging '{_sourceName}' into '{Into}'");
Use(log);
return Task.Run(() =>
{
new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, SetProgressDescription).Exec();
new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.FullName);

View file

@ -46,15 +46,18 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Merge head(s) ...";
var log = _repo.CreateLog("Merge Multiple Heads");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Merge(
_repo.FullPath,
ConvertTargetToMergeSources(),
AutoCommit,
Strategy.Arg,
SetProgressDescription).Exec();
Strategy.Arg).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -52,9 +52,9 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(action);
}
protected void SetProgressDescription(string description)
protected void Use(CommandLog log)
{
CallUIThread(() => ProgressDescription = description);
log.Register(newline => ProgressDescription = newline.Trim());
}
private bool _inProgress = false;

View file

@ -22,9 +22,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Run `prune` on remote ...";
var log = _repo.CreateLog($"Prune Remote '{Remote.Name}'");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Remote(_repo.FullPath).Prune(Remote.Name);
var succ = new Commands.Remote(_repo.FullPath).Use(log).Prune(Remote.Name);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -15,9 +15,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Prune worktrees ...";
var log = _repo.CreateLog("Prune Worktrees");
Use(log);
return Task.Run(() =>
{
new Commands.Worktree(_repo.FullPath).Prune(SetProgressDescription);
new Commands.Worktree(_repo.FullPath).Use(log).Prune();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -118,6 +118,9 @@ namespace SourceGit.ViewModels
{
_repo.SetWatcherEnabled(false);
var log = _repo.CreateLog("Pull");
Use(log);
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
@ -126,15 +129,14 @@ namespace SourceGit.ViewModels
{
if (DiscardLocalChanges)
{
SetProgressDescription("Discard local changes ...");
Commands.Discard.All(_repo.FullPath, false);
Commands.Discard.All(_repo.FullPath, false, log);
}
else
{
SetProgressDescription("Stash local changes...");
var succ = new Commands.Stash(_repo.FullPath).Push("PULL_AUTO_STASH");
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("PULL_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -146,16 +148,14 @@ namespace SourceGit.ViewModels
bool rs;
if (FetchAllBranches)
{
SetProgressDescription($"Fetching remote: {_selectedRemote.Name}...");
rs = new Commands.Fetch(
_repo.FullPath,
_selectedRemote.Name,
NoTags,
false,
SetProgressDescription).Exec();
false).Use(log).Exec();
if (!rs)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -164,39 +164,31 @@ namespace SourceGit.ViewModels
// Use merge/rebase instead of pull as fetch is done manually.
if (UseRebase)
{
SetProgressDescription($"Rebase {_current.Name} on {_selectedBranch.FriendlyName} ...");
rs = new Commands.Rebase(_repo.FullPath, _selectedBranch.FriendlyName, false).Exec();
}
rs = new Commands.Rebase(_repo.FullPath, _selectedBranch.FriendlyName, false).Use(log).Exec();
else
{
SetProgressDescription($"Merge {_selectedBranch.FriendlyName} into {_current.Name} ...");
rs = new Commands.Merge(_repo.FullPath, _selectedBranch.FriendlyName, "", SetProgressDescription).Exec();
}
rs = new Commands.Merge(_repo.FullPath, _selectedBranch.FriendlyName, "").Use(log).Exec();
}
else
{
SetProgressDescription($"Pull {_selectedRemote.Name}/{_selectedBranch.Name}...");
rs = new Commands.Pull(
_repo.FullPath,
_selectedRemote.Name,
_selectedBranch.Name,
UseRebase,
NoTags,
SetProgressDescription).Exec();
NoTags).Use(log).Exec();
}
if (rs && needPopStash)
{
SetProgressDescription("Re-apply local changes...");
rs = new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
}
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.FullName);
_repo.SetWatcherEnabled(true);
});
return rs;
});
}

View file

@ -164,6 +164,9 @@ namespace SourceGit.ViewModels
var remoteBranchName = _selectedRemoteBranch.Name;
ProgressDescription = $"Push {_selectedLocalBranch.Name} -> {_selectedRemote.Name}/{remoteBranchName} ...";
var log = _repo.CreateLog("Push");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Push(
@ -174,8 +177,9 @@ namespace SourceGit.ViewModels
PushAllTags,
_repo.Submodules.Count > 0 && CheckSubmodules,
_isSetTrackOptionVisible && Tracking,
ForcePush,
SetProgressDescription).Exec();
ForcePush).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -41,6 +41,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Pushing tag ...";
var log = _repo.CreateLog("Push Tag");
Use(log);
return Task.Run(() =>
{
var succ = true;
@ -49,18 +52,17 @@ namespace SourceGit.ViewModels
{
foreach (var remote in _repo.Remotes)
{
SetProgressDescription($"Pushing tag to remote {remote.Name} ...");
succ = new Commands.Push(_repo.FullPath, remote.Name, tag, false).Exec();
succ = new Commands.Push(_repo.FullPath, remote.Name, tag, false).Use(log).Exec();
if (!succ)
break;
}
}
else
{
SetProgressDescription($"Pushing tag to remote {SelectedRemote.Name} ...");
succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, tag, false).Exec();
succ = new Commands.Push(_repo.FullPath, SelectedRemote.Name, tag, false).Use(log).Exec();
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -47,9 +47,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Rebasing ...";
var log = _repo.CreateLog("Rebase");
Use(log);
return Task.Run(() =>
{
new Commands.Rebase(_repo.FullPath, _revision, AutoStash).Exec();
new Commands.Rebase(_repo.FullPath, _revision, AutoStash).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -26,11 +26,15 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Remove worktrees ...";
ProgressDescription = "Remove worktree ...";
var log = _repo.CreateLog("Remove worktree");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Worktree(_repo.FullPath).Remove(Target.FullPath, Force, SetProgressDescription);
var succ = new Commands.Worktree(_repo.FullPath).Use(log).Remove(Target.FullPath, Force);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -54,10 +54,15 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Rename '{Target.Name}'";
var log = _repo.CreateLog($"Rename Branch '{Target.Name}'");
Use(log);
return Task.Run(() =>
{
var oldName = Target.FullName;
var succ = Commands.Branch.Rename(_repo.FullPath, Target.Name, fixedName);
var succ = Commands.Branch.Rename(_repo.FullPath, Target.Name, fixedName, log);
log.Complete();
CallUIThread(() =>
{
if (succ)

View file

@ -6,6 +6,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.Imaging;
@ -409,6 +410,12 @@ namespace SourceGit.ViewModels
set;
} = 0;
public AvaloniaList<CommandLog> Logs
{
get;
private set;
} = new AvaloniaList<CommandLog>();
public Repository(bool isBare, string path, string gitDir)
{
IsBare = isBare;
@ -472,6 +479,8 @@ namespace SourceGit.ViewModels
public void Close()
{
SelectedView = null; // Do NOT modify. Used to remove exists widgets for GC.Collect
Logs.Clear();
_settings.LastCommitMessage = _workingCopy.CommitMessage;
var settingsSerialized = JsonSerializer.Serialize(_settings, JsonCodeGen.Default.RepositorySettings);
@ -538,6 +547,13 @@ namespace SourceGit.ViewModels
GetOwnerPage()?.StartPopup(popup);
}
public CommandLog CreateLog(string name)
{
var log = new CommandLog(name);
Logs.Insert(0, log);
return log;
}
public void RefreshAll()
{
Task.Run(() =>
@ -2560,7 +2576,7 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => IsAutoFetching = true);
foreach (var remote in remotes)
new Commands.Fetch(_fullpath, remote, false, false, null) { RaiseError = false }.Exec();
new Commands.Fetch(_fullpath, remote, false, false) { RaiseError = false }.Exec();
_lastFetchTime = DateTime.Now;
Dispatcher.UIThread.Invoke(() => IsAutoFetching = false);
}

View file

@ -36,9 +36,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Reset current branch to {To.SHA} ...";
var log = _repo.CreateLog($"Reset HEAD to '{To.SHA}'");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Reset(_repo.FullPath, To.SHA, SelectedMode.Arg).Exec();
var succ = new Commands.Reset(_repo.FullPath, To.SHA, SelectedMode.Arg).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -29,9 +29,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Revert commit '{Target.SHA}' ...";
var log = _repo.CreateLog($"Revert '{Target.SHA}'");
Use(log);
return Task.Run(() =>
{
new Commands.Revert(_repo.FullPath, Target.SHA, AutoCommit).Exec();
new Commands.Revert(_repo.FullPath, Target.SHA, AutoCommit).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -37,9 +37,13 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Editing head commit message ...";
var log = _repo.CreateLog("Reword HEAD");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Commit(_repo.FullPath, _message, true, _repo.Settings.EnableSignOffForCommit).Run();
var succ = new Commands.Commit(_repo.FullPath, _message, true, _repo.Settings.EnableSignOffForCommit).Use(log).Run();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -97,7 +97,7 @@ namespace SourceGit.ViewModels
subdir.Name.Equals(".idea", StringComparison.Ordinal))
continue;
SetProgressDescription($"Scanning {subdir.FullName}...");
CallUIThread(() => ProgressDescription = $"Scanning {subdir.FullName}...");
var normalizedSelf = subdir.FullName.Replace("\\", "/");
if (_managed.Contains(normalizedSelf))

View file

@ -55,17 +55,22 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
SetProgressDescription("Setting upstream...");
ProgressDescription = "Setting upstream...";
var upstream = (_unset || SelectedRemoteBranch == null) ? string.Empty : SelectedRemoteBranch.FullName;
if (upstream == Local.Upstream)
return null;
var log = _repo.CreateLog("Set Upstream");
Use(log);
return Task.Run(() =>
{
var succ = Commands.Branch.SetUpstream(_repo.FullPath, Local.Name, upstream.Replace("refs/remotes/", ""));
var succ = Commands.Branch.SetUpstream(_repo.FullPath, Local.Name, upstream.Replace("refs/remotes/", ""), log);
if (succ)
_repo.RefreshBranches();
log.Complete();
return true;
});
}

View file

@ -31,6 +31,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Squashing ...";
var log = _repo.CreateLog("Squash");
Use(log);
return Task.Run(() =>
{
var autoStashed = false;
@ -38,9 +41,10 @@ namespace SourceGit.ViewModels
if (_repo.LocalChangesCount > 0)
{
succ = new Commands.Stash(_repo.FullPath).Push("SQUASH_AUTO_STASH");
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("SQUASH_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
@ -48,13 +52,14 @@ namespace SourceGit.ViewModels
autoStashed = true;
}
succ = new Commands.Reset(_repo.FullPath, Target.SHA, "--soft").Exec();
succ = new Commands.Reset(_repo.FullPath, Target.SHA, "--soft").Use(log).Exec();
if (succ)
succ = new Commands.Commit(_repo.FullPath, _message, true, _repo.Settings.EnableSignOffForCommit).Run();
succ = new Commands.Commit(_repo.FullPath, _message, true, _repo.Settings.EnableSignOffForCommit).Use(log).Run();
if (succ && autoStashed)
new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});

View file

@ -56,6 +56,9 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Stash changes ...";
var log = _repo.CreateLog("Stash Local Changes");
Use(log);
return Task.Run(() =>
{
var succ = false;
@ -66,7 +69,7 @@ namespace SourceGit.ViewModels
{
if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_ONLY_STAGED)
{
succ = new Commands.Stash(_repo.FullPath).PushOnlyStaged(Message, KeepIndex);
succ = new Commands.Stash(_repo.FullPath).Use(log).PushOnlyStaged(Message, KeepIndex);
}
else
{
@ -77,22 +80,23 @@ namespace SourceGit.ViewModels
staged.Add(c);
}
succ = StashWithChanges(staged);
succ = StashWithChanges(staged, log);
}
}
else
{
succ = new Commands.Stash(_repo.FullPath).Push(Message, IncludeUntracked, KeepIndex);
succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, IncludeUntracked, KeepIndex);
}
}
else
{
succ = StashWithChanges(_changes);
succ = StashWithChanges(_changes, log);
}
if (AutoRestore && succ)
succ = new Commands.Stash(_repo.FullPath).Apply("stash@{0}", true);
succ = new Commands.Stash(_repo.FullPath).Use(log).Apply("stash@{0}", true);
log.Complete();
CallUIThread(() =>
{
_repo.MarkWorkingCopyDirtyManually();
@ -103,7 +107,7 @@ namespace SourceGit.ViewModels
});
}
private bool StashWithChanges(List<Models.Change> changes)
private bool StashWithChanges(List<Models.Change> changes, CommandLog log)
{
if (changes.Count == 0)
return true;
@ -117,7 +121,7 @@ namespace SourceGit.ViewModels
var tmpFile = Path.GetTempFileName();
File.WriteAllLines(tmpFile, paths);
succ = new Commands.Stash(_repo.FullPath).Push(Message, tmpFile, KeepIndex);
succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, tmpFile, KeepIndex);
File.Delete(tmpFile);
}
else
@ -126,7 +130,7 @@ namespace SourceGit.ViewModels
{
var count = Math.Min(10, changes.Count - i);
var step = changes.GetRange(i, count);
succ = new Commands.Stash(_repo.FullPath).Push(Message, step, KeepIndex);
succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, step, KeepIndex);
if (!succ)
break;
}

View file

@ -147,7 +147,7 @@ namespace SourceGit.ViewModels
apply.Click += (_, ev) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new ApplyStash(_repo.FullPath, stash));
_repo.ShowPopup(new ApplyStash(_repo, stash));
ev.Handled = true;
};
@ -157,7 +157,7 @@ namespace SourceGit.ViewModels
drop.Click += (_, ev) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new DropStash(_repo.FullPath, stash));
_repo.ShowPopup(new DropStash(_repo, stash));
ev.Handled = true;
};

View file

@ -62,19 +62,21 @@ namespace SourceGit.ViewModels
else
targets = [SelectedSubmodule];
var log = _repo.CreateLog("Update Submodule");
Use(log);
return Task.Run(() =>
{
foreach (var submodule in targets)
{
ProgressDescription = $"Updating submodule {submodule} ...";
new Commands.Submodule(_repo.FullPath).Update(
new Commands.Submodule(_repo.FullPath).Use(log).Update(
submodule,
EnableInit,
EnableRecursive,
EnableRemote,
SetProgressDescription);
EnableRemote);
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -0,0 +1,27 @@
using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class ViewLogs : ObservableObject
{
public AvaloniaList<CommandLog> Logs
{
get => _repo.Logs;
}
public CommandLog SelectedLog
{
get => _selectedLog;
set => SetProperty(ref _selectedLog, value);
}
public ViewLogs(Repository repo)
{
_repo = repo;
}
private Repository _repo = null;
private CommandLog _selectedLog = null;
}
}

View file

@ -711,7 +711,9 @@ namespace SourceGit.ViewModels
assumeUnchanged.IsVisible = change.WorkTree != Models.ChangeState.Untracked;
assumeUnchanged.Click += (_, e) =>
{
new Commands.AssumeUnchanged(_repo.FullPath).Add(change.Path);
var log = _repo.CreateLog("Assume File Unchanged");
new Commands.AssumeUnchanged(_repo.FullPath, change.Path, true).Use(log).Exec();
log.Complete();
e.Handled = true;
};
@ -805,10 +807,12 @@ namespace SourceGit.ViewModels
lfsTrackThisFile.Header = App.Text("GitLFS.Track", filename);
lfsTrackThisFile.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track(filename, true));
var log = _repo.CreateLog("Track LFS");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track(filename, true, log));
if (succ)
App.SendNotification(_repo.FullPath, $"Tracking file named {filename} successfully!");
log.Complete();
e.Handled = true;
};
lfs.Items.Add(lfsTrackThisFile);
@ -819,10 +823,12 @@ namespace SourceGit.ViewModels
lfsTrackByExtension.Header = App.Text("GitLFS.TrackByExtension", extension);
lfsTrackByExtension.Click += async (_, e) =>
{
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track("*" + extension));
var log = _repo.CreateLog("Track LFS");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Track("*" + extension, false, log));
if (succ)
App.SendNotification(_repo.FullPath, $"Tracking all *{extension} files successfully!");
log.Complete();
e.Handled = true;
};
lfs.Items.Add(lfsTrackByExtension);
@ -1581,9 +1587,11 @@ namespace SourceGit.ViewModels
IsStaging = true;
_repo.SetWatcherEnabled(false);
var log = _repo.CreateLog("Stage");
if (count == _unstaged.Count)
{
await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Exec());
await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).Exec());
}
else if (Native.OS.GitVersion >= Models.GitVersions.ADD_WITH_PATHSPECFILE)
{
@ -1593,7 +1601,7 @@ namespace SourceGit.ViewModels
var tmpFile = Path.GetTempFileName();
File.WriteAllLines(tmpFile, paths);
await Task.Run(() => new Commands.Add(_repo.FullPath, tmpFile).Exec());
await Task.Run(() => new Commands.Add(_repo.FullPath, tmpFile).Use(log).Exec());
File.Delete(tmpFile);
}
else
@ -1605,9 +1613,10 @@ namespace SourceGit.ViewModels
for (int i = 0; i < count; i += 10)
{
var step = paths.GetRange(i, Math.Min(10, count - i));
await Task.Run(() => new Commands.Add(_repo.FullPath, step).Exec());
await Task.Run(() => new Commands.Add(_repo.FullPath, step).Use(log).Exec());
}
}
log.Complete();
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
IsStaging = false;
@ -1624,22 +1633,26 @@ namespace SourceGit.ViewModels
IsUnstaging = true;
_repo.SetWatcherEnabled(false);
var log = _repo.CreateLog("Unstage");
if (_useAmend)
{
log.AppendLine("$ git update-index --index-info ");
await Task.Run(() => new Commands.UnstageChangesForAmend(_repo.FullPath, changes).Exec());
}
else if (count == _staged.Count)
{
await Task.Run(() => new Commands.Reset(_repo.FullPath).Exec());
await Task.Run(() => new Commands.Reset(_repo.FullPath).Use(log).Exec());
}
else
{
for (int i = 0; i < count; i += 10)
{
var step = changes.GetRange(i, Math.Min(10, count - i));
await Task.Run(() => new Commands.Reset(_repo.FullPath, step).Exec());
await Task.Run(() => new Commands.Reset(_repo.FullPath, step).Use(log).Exec());
}
}
log.Complete();
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
IsUnstaging = false;
@ -1703,14 +1716,17 @@ namespace SourceGit.ViewModels
_repo.Settings.PushCommitMessage(_commitMessage);
_repo.SetWatcherEnabled(false);
var log = _repo.CreateLog("Commit");
Task.Run(() =>
{
var succ = true;
if (autoStage && _unstaged.Count > 0)
succ = new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Exec();
succ = new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).Exec();
if (succ)
succ = new Commands.Commit(_repo.FullPath, _commitMessage, _useAmend, _repo.Settings.EnableSignOffForCommit).Run();
succ = new Commands.Commit(_repo.FullPath, _commitMessage, _useAmend, _repo.Settings.EnableSignOffForCommit).Use(log).Run();
log.Complete();
Dispatcher.UIThread.Post(() =>
{