diff --git a/README.md b/README.md
index 2d222996..8c12c646 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ You can find the current translation status in [TRANSLATION.md](https://github.c
## How to Use
-**To use this tool, you need to install Git(>=2.23.0) first.**
+**To use this tool, you need to install Git(>=2.25.1) first.**
You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [Github Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
diff --git a/TRANSLATION.md b/TRANSLATION.md
index 08594b66..94ff684b 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -6,7 +6,7 @@ This document shows the translation status of each locale file in the repository
### 
-### 
+### 
Missing keys in de_DE.axaml
@@ -26,6 +26,7 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Pull.RecurseSubmodules
+- Text.Repository.ClearStashes
- Text.Repository.ShowSubmodulesAsTree
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
@@ -37,19 +38,13 @@ This document shows the translation status of each locale file in the repository
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
- Text.Submodule.URL
+- Text.WorkingCopy.ResetAuthor
-### 
+### 
-
-Missing keys in es_ES.axaml
-
-- Text.CreateBranch.OverwriteExisting
-
-
-
-### 
+### 
Missing keys in fr_FR.axaml
@@ -90,6 +85,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
- Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
@@ -113,10 +109,11 @@ This document shows the translation status of each locale file in the repository
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
-### 
+### 
Missing keys in it_IT.axaml
@@ -133,14 +130,16 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Pull.RecurseSubmodules
+- Text.Repository.ClearStashes
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
+- Text.WorkingCopy.ResetAuthor
-### 
+### 
Missing keys in ja_JP.axaml
@@ -152,6 +151,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
+- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
@@ -181,6 +181,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
- Text.Repository.FilterCommits
- Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree
@@ -206,10 +207,11 @@ This document shows the translation status of each locale file in the repository
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
-### 
+### 
Missing keys in pt_BR.axaml
@@ -294,6 +296,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
- Text.Repository.FilterCommits
- Text.Repository.HistoriesLayout
- Text.Repository.HistoriesLayout.Horizontal
@@ -339,13 +342,23 @@ This document shows the translation status of each locale file in the repository
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
- Text.WorkingCopy.SignOff
-### 
+### 
-### 
+
+Missing keys in ru_RU.axaml
+
+- Text.BranchCM.CompareWithCurrent
+- Text.Repository.ClearStashes
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
Missing keys in ta_IN.axaml
@@ -357,6 +370,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
+- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
@@ -386,6 +400,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
- Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
@@ -409,10 +424,11 @@ This document shows the translation status of each locale file in the repository
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
-### 
+### 
Missing keys in uk_UA.axaml
@@ -449,6 +465,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
- Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
@@ -467,6 +484,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.ResetAuthor
diff --git a/VERSION b/VERSION
index ac98de3d..67a3d7e0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2025.19
\ No newline at end of file
+2025.20
\ No newline at end of file
diff --git a/src/App.axaml.cs b/src/App.axaml.cs
index 0664ee25..411f5cfb 100644
--- a/src/App.axaml.cs
+++ b/src/App.axaml.cs
@@ -393,7 +393,17 @@ namespace SourceGit
_ipcChannel = new Models.IpcChannel();
if (!_ipcChannel.IsFirstInstance)
{
- _ipcChannel.SendToFirstInstance(desktop.Args is { Length: 1 } ? desktop.Args[0] : string.Empty);
+ var arg = desktop.Args is { Length: > 0 } ? desktop.Args[0].Trim() : string.Empty;
+ if (!string.IsNullOrEmpty(arg))
+ {
+ if (arg.StartsWith('"') && arg.EndsWith('"'))
+ arg = arg.Substring(1, arg.Length - 2).Trim();
+
+ if (arg.Length > 0 && !Path.IsPathFullyQualified(arg))
+ arg = Path.GetFullPath(arg);
+ }
+
+ _ipcChannel.SendToFirstInstance(arg);
Environment.Exit(0);
}
else
diff --git a/src/Commands/Add.cs b/src/Commands/Add.cs
index b2aa803d..210eb4b2 100644
--- a/src/Commands/Add.cs
+++ b/src/Commands/Add.cs
@@ -1,7 +1,4 @@
-using System.Collections.Generic;
-using System.Text;
-
-namespace SourceGit.Commands
+namespace SourceGit.Commands
{
public class Add : Command
{
@@ -12,20 +9,11 @@ namespace SourceGit.Commands
Args = includeUntracked ? "add ." : "add -u .";
}
- public Add(string repo, List changes)
+ public Add(string repo, Models.Change change)
{
WorkingDirectory = repo;
Context = repo;
-
- var builder = new StringBuilder();
- builder.Append("add --");
- foreach (var c in changes)
- {
- builder.Append(" \"");
- builder.Append(c);
- builder.Append("\"");
- }
- Args = builder.ToString();
+ Args = $"add -- \"{change.Path}\"";
}
public Add(string repo, string pathspecFromFile)
diff --git a/src/Commands/Checkout.cs b/src/Commands/Checkout.cs
index aa386c2f..d2876740 100644
--- a/src/Commands/Checkout.cs
+++ b/src/Commands/Checkout.cs
@@ -27,9 +27,9 @@ namespace SourceGit.Commands
{
var builder = new StringBuilder();
builder.Append("checkout --progress ");
- builder.Append(allowOverwrite ? "-B " : "-b ");
if (force)
builder.Append("--force ");
+ builder.Append(allowOverwrite ? "-B " : "-b ");
builder.Append(branch);
builder.Append(" ");
builder.Append(basedOn);
diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs
index 5be08cef..17410bc9 100644
--- a/src/Commands/Commit.cs
+++ b/src/Commands/Commit.cs
@@ -4,7 +4,7 @@ namespace SourceGit.Commands
{
public class Commit : Command
{
- public Commit(string repo, string message, bool amend, bool signOff)
+ public Commit(string repo, string message, bool signOff, bool amend, bool resetAuthor)
{
_tmpFile = Path.GetTempFileName();
File.WriteAllText(_tmpFile, message);
@@ -12,10 +12,10 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
Args = $"commit --allow-empty --file=\"{_tmpFile}\"";
- if (amend)
- Args += " --amend --no-edit";
if (signOff)
Args += " --signoff";
+ if (amend)
+ Args += resetAuthor ? " --amend --reset-author --no-edit" : " --amend --no-edit";
}
public bool Run()
diff --git a/src/Commands/Discard.cs b/src/Commands/Discard.cs
index e61fe1e6..f36ca6c9 100644
--- a/src/Commands/Discard.cs
+++ b/src/Commands/Discard.cs
@@ -8,6 +8,12 @@ namespace SourceGit.Commands
{
public static class Discard
{
+ ///
+ /// Discard all local changes (unstaged & staged)
+ ///
+ ///
+ ///
+ ///
public static void All(string repo, bool includeIgnored, Models.ICommandLog log)
{
var changes = new QueryLocalChanges(repo).Result();
@@ -36,11 +42,18 @@ namespace SourceGit.Commands
});
}
- new Restore(repo) { Log = log }.Exec();
+ new Reset(repo, "HEAD", "--hard") { Log = log }.Exec();
+
if (includeIgnored)
new Clean(repo) { Log = log }.Exec();
}
+ ///
+ /// Discard selected changes (only unstaged).
+ ///
+ ///
+ ///
+ ///
public static void Changes(string repo, List changes, Models.ICommandLog log)
{
var restores = new List();
@@ -71,10 +84,12 @@ namespace SourceGit.Commands
});
}
- for (int i = 0; i < restores.Count; i += 10)
+ if (restores.Count > 0)
{
- var count = Math.Min(10, restores.Count - i);
- new Restore(repo, restores.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
+ var pathSpecFile = Path.GetTempFileName();
+ File.WriteAllLines(pathSpecFile, restores);
+ new Restore(repo, pathSpecFile, false) { Log = log }.Exec();
+ File.Delete(pathSpecFile);
}
}
}
diff --git a/src/Commands/FormatPatch.cs b/src/Commands/FormatPatch.cs
index b3ec2e4a..bf850d60 100644
--- a/src/Commands/FormatPatch.cs
+++ b/src/Commands/FormatPatch.cs
@@ -6,6 +6,7 @@
{
WorkingDirectory = repo;
Context = repo;
+ Editor = EditorType.None;
Args = $"format-patch {commit} -1 --output=\"{saveTo}\"";
}
}
diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs
index 910e5fd2..d0ecd322 100644
--- a/src/Commands/QueryBranches.cs
+++ b/src/Commands/QueryBranches.cs
@@ -58,7 +58,7 @@ namespace SourceGit.Commands
if (b.TrackStatus == null)
b.TrackStatus = new Models.BranchTrackStatus();
- }
+ }
}
}
diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs
index 9abf433e..788ed617 100644
--- a/src/Commands/QueryLocalChanges.cs
+++ b/src/Commands/QueryLocalChanges.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+
using Avalonia.Threading;
namespace SourceGit.Commands
@@ -121,19 +122,32 @@ namespace SourceGit.Commands
case "CD":
change.Set(Models.ChangeState.Copied, Models.ChangeState.Deleted);
break;
- case "DR":
- change.Set(Models.ChangeState.Deleted, Models.ChangeState.Renamed);
- break;
- case "DC":
- change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied);
- break;
case "DD":
+ change.ConflictReason = Models.ConflictReason.BothDeleted;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "AU":
+ change.ConflictReason = Models.ConflictReason.AddedByUs;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "UD":
+ change.ConflictReason = Models.ConflictReason.DeletedByThem;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "UA":
+ change.ConflictReason = Models.ConflictReason.AddedByThem;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "DU":
+ change.ConflictReason = Models.ConflictReason.DeletedByUs;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "AA":
+ change.ConflictReason = Models.ConflictReason.BothAdded;
+ change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
+ break;
case "UU":
+ change.ConflictReason = Models.ConflictReason.BothModified;
change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
break;
case "??":
diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs
index b20c20dc..78980401 100644
--- a/src/Commands/QueryStagedChangesWithAmend.cs
+++ b/src/Commands/QueryStagedChangesWithAmend.cs
@@ -24,7 +24,7 @@ namespace SourceGit.Commands
var rs = ReadToEnd();
if (!rs.IsSuccess)
return [];
-
+
var changes = new List();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
diff --git a/src/Commands/QueryStashChanges.cs b/src/Commands/QueryStashChanges.cs
deleted file mode 100644
index 1f6c5b4f..00000000
--- a/src/Commands/QueryStashChanges.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-
-namespace SourceGit.Commands
-{
- ///
- /// Query stash changes. Requires git >= 2.32.0
- ///
- public partial class QueryStashChanges : Command
- {
- [GeneratedRegex(@"^([MADC])\s+(.+)$")]
- private static partial Regex REG_FORMAT();
- [GeneratedRegex(@"^R[0-9]{0,4}\s+(.+)$")]
- private static partial Regex REG_RENAME_FORMAT();
-
- public QueryStashChanges(string repo, string stash)
- {
- WorkingDirectory = repo;
- Context = repo;
- Args = $"stash show -u --name-status \"{stash}\"";
- }
-
- public List Result()
- {
- var rs = ReadToEnd();
- if (!rs.IsSuccess)
- return [];
-
- var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
- var outs = new List();
- foreach (var line in lines)
- {
- var match = REG_FORMAT().Match(line);
- if (!match.Success)
- {
- match = REG_RENAME_FORMAT().Match(line);
- if (match.Success)
- {
- var renamed = new Models.Change() { Path = match.Groups[1].Value };
- renamed.Set(Models.ChangeState.Renamed);
- outs.Add(renamed);
- }
-
- continue;
- }
-
- var change = new Models.Change() { Path = match.Groups[2].Value };
- var status = match.Groups[1].Value;
-
- switch (status[0])
- {
- case 'M':
- change.Set(Models.ChangeState.Modified);
- outs.Add(change);
- break;
- case 'A':
- change.Set(Models.ChangeState.Added);
- outs.Add(change);
- break;
- case 'D':
- change.Set(Models.ChangeState.Deleted);
- outs.Add(change);
- break;
- case 'C':
- change.Set(Models.ChangeState.Copied);
- outs.Add(change);
- break;
- }
- }
-
- outs.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
- return outs;
- }
- }
-}
diff --git a/src/Commands/Reset.cs b/src/Commands/Reset.cs
index da272135..6a54533b 100644
--- a/src/Commands/Reset.cs
+++ b/src/Commands/Reset.cs
@@ -1,33 +1,7 @@
-using System.Collections.Generic;
-using System.Text;
-
-namespace SourceGit.Commands
+namespace SourceGit.Commands
{
public class Reset : Command
{
- public Reset(string repo)
- {
- WorkingDirectory = repo;
- Context = repo;
- Args = "reset";
- }
-
- public Reset(string repo, List changes)
- {
- WorkingDirectory = repo;
- Context = repo;
-
- var builder = new StringBuilder();
- builder.Append("reset --");
- foreach (var c in changes)
- {
- builder.Append(" \"");
- builder.Append(c.Path);
- builder.Append("\"");
- }
- Args = builder.ToString();
- }
-
public Reset(string repo, string revision, string mode)
{
WorkingDirectory = repo;
diff --git a/src/Commands/Restore.cs b/src/Commands/Restore.cs
index 7a363543..663ea975 100644
--- a/src/Commands/Restore.cs
+++ b/src/Commands/Restore.cs
@@ -1,29 +1,52 @@
-using System.Collections.Generic;
-using System.Text;
+using System.Text;
namespace SourceGit.Commands
{
public class Restore : Command
{
- public Restore(string repo)
+ ///
+ /// Only used for single staged change.
+ ///
+ ///
+ ///
+ public Restore(string repo, Models.Change stagedChange)
{
WorkingDirectory = repo;
Context = repo;
- Args = "restore . --source=HEAD --staged --worktree --recurse-submodules";
+
+ var builder = new StringBuilder();
+ builder.Append("restore --staged -- \"");
+ builder.Append(stagedChange.Path);
+ builder.Append('"');
+
+ if (stagedChange.Index == Models.ChangeState.Renamed)
+ {
+ builder.Append(" \"");
+ builder.Append(stagedChange.OriginalPath);
+ builder.Append('"');
+ }
+
+ Args = builder.ToString();
}
- public Restore(string repo, List files, string extra)
+ ///
+ /// Restore changes given in a path-spec file.
+ ///
+ ///
+ ///
+ ///
+ public Restore(string repo, string pathspecFile, bool isStaged)
{
WorkingDirectory = repo;
Context = repo;
- StringBuilder builder = new StringBuilder();
+ var builder = new StringBuilder();
builder.Append("restore ");
- if (!string.IsNullOrEmpty(extra))
- builder.Append(extra).Append(" ");
- builder.Append("--");
- foreach (var f in files)
- builder.Append(' ').Append('"').Append(f).Append('"');
+ builder.Append(isStaged ? "--staged " : "--worktree --recurse-submodules ");
+ builder.Append("--pathspec-from-file=\"");
+ builder.Append(pathspecFile);
+ builder.Append('"');
+
Args = builder.ToString();
}
}
diff --git a/src/Commands/Tag.cs b/src/Commands/Tag.cs
index 10a7ba87..017afea0 100644
--- a/src/Commands/Tag.cs
+++ b/src/Commands/Tag.cs
@@ -28,12 +28,13 @@ namespace SourceGit.Commands
string tmp = Path.GetTempFileName();
File.WriteAllText(tmp, message);
cmd.Args += $"-F \"{tmp}\"";
- }
- else
- {
- cmd.Args += $"-m {name}";
+
+ var succ = cmd.Exec();
+ File.Delete(tmp);
+ return succ;
}
+ cmd.Args += $"-m {name}";
return cmd.Exec();
}
diff --git a/src/Models/Change.cs b/src/Models/Change.cs
index 7d772d3e..129678be 100644
--- a/src/Models/Change.cs
+++ b/src/Models/Change.cs
@@ -22,6 +22,18 @@ namespace SourceGit.Models
Conflicted,
}
+ public enum ConflictReason
+ {
+ None,
+ BothDeleted,
+ AddedByUs,
+ DeletedByThem,
+ AddedByThem,
+ DeletedByUs,
+ BothAdded,
+ BothModified,
+ }
+
public class ChangeDataForAmend
{
public string FileMode { get; set; } = "";
@@ -36,7 +48,14 @@ namespace SourceGit.Models
public string Path { get; set; } = "";
public string OriginalPath { get; set; } = "";
public ChangeDataForAmend DataForAmend { get; set; } = null;
+ public ConflictReason ConflictReason { get; set; } = ConflictReason.None;
+
public bool IsConflicted => WorkTree == ChangeState.Conflicted;
+ public string ConflictMarker => CONFLICT_MARKERS[(int)ConflictReason];
+ public string ConflictDesc => CONFLICT_DESCS[(int)ConflictReason];
+
+ public string WorkTreeDesc => TYPE_DESCS[(int)WorkTree];
+ public string IndexDesc => TYPE_DESCS[(int)Index];
public void Set(ChangeState index, ChangeState workTree = ChangeState.None)
{
@@ -64,9 +83,44 @@ namespace SourceGit.Models
if (Path[0] == '"')
Path = Path.Substring(1, Path.Length - 2);
-
+
if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"')
OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2);
}
+
+ private static readonly string[] TYPE_DESCS =
+ [
+ "Unknown",
+ "Modified",
+ "Type Changed",
+ "Added",
+ "Deleted",
+ "Renamed",
+ "Copied",
+ "Untracked",
+ "Conflict"
+ ];
+ private static readonly string[] CONFLICT_MARKERS =
+ [
+ string.Empty,
+ "DD",
+ "AU",
+ "UD",
+ "UA",
+ "DU",
+ "AA",
+ "UU"
+ ];
+ private static readonly string[] CONFLICT_DESCS =
+ [
+ string.Empty,
+ "Both deleted",
+ "Added by us",
+ "Deleted by them",
+ "Added by them",
+ "Deleted by us",
+ "Both added",
+ "Both modified"
+ ];
}
}
diff --git a/src/Models/GitVersions.cs b/src/Models/GitVersions.cs
index 92fd8c59..8aae63a3 100644
--- a/src/Models/GitVersions.cs
+++ b/src/Models/GitVersions.cs
@@ -5,26 +5,16 @@
///
/// The minimal version of Git that required by this app.
///
- public static readonly System.Version MINIMAL = new System.Version(2, 23, 0);
-
- ///
- /// The minimal version of Git that supports the `add` command with the `--pathspec-from-file` option.
- ///
- public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0);
+ public static readonly System.Version MINIMAL = new(2, 25, 1);
///
/// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option.
///
- public static readonly System.Version STASH_PUSH_WITH_PATHSPECFILE = new System.Version(2, 26, 0);
+ public static readonly System.Version STASH_PUSH_WITH_PATHSPECFILE = new(2, 26, 0);
///
/// The minimal version of Git that supports the `stash push` command with the `--staged` option.
///
- public static readonly System.Version STASH_PUSH_ONLY_STAGED = new System.Version(2, 35, 0);
-
- ///
- /// The minimal version of Git that supports the `stash show` command with the `-u` option.
- ///
- public static readonly System.Version STASH_SHOW_WITH_UNTRACKED = new System.Version(2, 32, 0);
+ public static readonly System.Version STASH_PUSH_ONLY_STAGED = new(2, 35, 0);
}
}
diff --git a/src/Models/Statistics.cs b/src/Models/Statistics.cs
index d982a3ed..a86380c3 100644
--- a/src/Models/Statistics.cs
+++ b/src/Models/Statistics.cs
@@ -26,25 +26,23 @@ namespace SourceGit.Models
public class StatisticsReport
{
- public static readonly string[] WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
-
public int Total { get; set; } = 0;
- public List Authors { get; set; } = new List();
- public List Series { get; set; } = new List();
- public List XAxes { get; set; } = new List();
- public List YAxes { get; set; } = new List();
+ public List Authors { get; set; } = new();
+ public List Series { get; set; } = new();
+ public List XAxes { get; set; } = new();
+ public List YAxes { get; set; } = new();
public StatisticsAuthor SelectedAuthor { get => _selectedAuthor; set => ChangeAuthor(value); }
public StatisticsReport(StatisticsMode mode, DateTime start)
{
_mode = mode;
- YAxes = [new Axis()
+ YAxes.Add(new Axis()
{
TextSize = 10,
MinLimit = 0,
SeparatorsPaint = new SolidColorPaint(new SKColor(0x40808080)) { StrokeThickness = 1 }
- }];
+ });
if (mode == StatisticsMode.ThisWeek)
{
@@ -72,7 +70,7 @@ namespace SourceGit.Models
{
Total++;
- var normalized = DateTime.MinValue;
+ DateTime normalized;
if (_mode == StatisticsMode.ThisWeek || _mode == StatisticsMode.ThisMonth)
normalized = time.Date;
else
@@ -172,26 +170,27 @@ namespace SourceGit.Models
ChangeColor(_fillColor);
}
- private StatisticsMode _mode = StatisticsMode.All;
- private Dictionary _mapUsers = new Dictionary();
- private Dictionary _mapSamples = new Dictionary();
- private Dictionary> _mapUserSamples = new Dictionary>();
+ private static readonly string[] WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
+ private StatisticsMode _mode;
+ private Dictionary _mapUsers = new();
+ private Dictionary _mapSamples = new();
+ private Dictionary> _mapUserSamples = new();
private StatisticsAuthor _selectedAuthor = null;
private uint _fillColor = 255;
}
public class Statistics
{
- public StatisticsReport All { get; set; }
- public StatisticsReport Month { get; set; }
- public StatisticsReport Week { get; set; }
+ public StatisticsReport All { get; }
+ public StatisticsReport Month { get; }
+ public StatisticsReport Week { get; }
public Statistics()
{
- _today = DateTime.Now.ToLocalTime().Date;
- var weekOffset = (7 + (int)_today.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek) % 7;
- _thisWeekStart = _today.AddDays(-weekOffset);
- _thisMonthStart = _today.AddDays(1 - _today.Day);
+ var today = DateTime.Now.ToLocalTime().Date;
+ var weekOffset = (7 + (int)today.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek) % 7;
+ _thisWeekStart = today.AddDays(-weekOffset);
+ _thisMonthStart = today.AddDays(1 - today.Day);
All = new StatisticsReport(StatisticsMode.All, DateTime.MinValue);
Month = new StatisticsReport(StatisticsMode.ThisMonth, _thisMonthStart);
@@ -200,7 +199,13 @@ namespace SourceGit.Models
public void AddCommit(string author, double timestamp)
{
- var user = User.FindOrAdd(author);
+ var emailIdx = author.IndexOf('±', StringComparison.Ordinal);
+ var email = author.Substring(emailIdx + 1).ToLower(CultureInfo.CurrentCulture);
+ if (!_users.TryGetValue(email, out var user))
+ {
+ user = User.FindOrAdd(author);
+ _users.Add(email, user);
+ }
var time = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime();
if (time >= _thisWeekStart)
@@ -214,13 +219,15 @@ namespace SourceGit.Models
public void Complete()
{
+ _users.Clear();
+
All.Complete();
Month.Complete();
Week.Complete();
}
- private readonly DateTime _today;
private readonly DateTime _thisMonthStart;
private readonly DateTime _thisWeekStart;
+ private readonly Dictionary _users = new();
}
}
diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml
index 886a07cf..3c900d42 100644
--- a/src/Resources/Locales/de_DE.axaml
+++ b/src/Resources/Locales/de_DE.axaml
@@ -50,13 +50,12 @@
Blame
BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!
Auschecken von ${0}$...
- Mit HEAD vergleichen
+ Mit ${0}$ vergleichen
Mit Worktree vergleichen
Branch-Namen kopieren
Benutzerdefinierte Aktion
Lösche ${0}$...
Lösche alle ausgewählten {0} Branches
- Alle Änderungen verwerfen
Fast-Forward zu ${0}$
Fetche ${0}$ in ${1}$ hinein...
Git Flow - Abschließen ${0}$
@@ -502,7 +501,7 @@
Globale Git Benutzer Email
Aktivere --prune beim fetchen
Aktiviere --ignore-cr-at-eol beim Unterschied
- Diese App setzt Git (>= 2.23.0) voraus
+ Diese App setzt Git (>= 2.25.1) voraus
Installationspfad
Aktiviere HTTP SSL Verifizierung
Benutzername
@@ -583,6 +582,7 @@
WEITER
Benutzerdefinierte Aktionen
Keine benutzerdefinierten Aktionen
+ Alle Änderungen verwerfen
Aktiviere '--reflog' Option
Öffne im Datei-Browser
Suche Branches/Tags/Submodule
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index c12396ec..4834aef9 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -46,13 +46,12 @@
Blame
BLAME ON THIS FILE IS NOT SUPPORTED!!!
Checkout ${0}$...
- Compare with HEAD
+ Compare with ${0}$
Compare with Worktree
Copy Branch Name
Custom Action
Delete ${0}$...
Delete selected {0} branches
- Discard all changes
Fast-Forward to ${0}$
Fetch ${0}$ into ${1}$...
Git Flow - Finish ${0}$
@@ -512,7 +511,7 @@
Global git user email
Enable --prune on fetch
Enable --ignore-cr-at-eol in diff
- Git (>= 2.23.0) is required by this app
+ Git (>= 2.25.1) is required by this app
Install Path
Enable HTTP SSL Verify
User Name
@@ -590,10 +589,12 @@
Cleanup(GC & Prune)
Run `git gc` command for this repository.
Clear all
+ Clear
Configure this repository
CONTINUE
Custom Actions
No Custom Actions
+ Discard all changes
Enable '--reflog' Option
Open in File Browser
Search Branches/Tags/Submodules
@@ -781,6 +782,7 @@
INCLUDE UNTRACKED FILES
NO RECENT INPUT MESSAGES
NO COMMIT TEMPLATES
+ Reset Author
Right-click the selected file(s), and make your choice to resolve conflicts.
SignOff
STAGED
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index 513eeb06..36c60346 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -50,13 +50,12 @@
Blame
¡BLAME EN ESTE ARCHIVO NO SOPORTADO!
Checkout ${0}$...
- Comparar con HEAD
+ Comparar con ${0}$
Comparar con Worktree
Copiar Nombre de Rama
Acción personalizada
Eliminar ${0}$...
Eliminar {0} ramas seleccionadas
- Descartar todos los cambios
Fast-Forward a ${0}$
Fetch ${0}$ en ${1}$...
Git Flow - Finalizar ${0}$
@@ -221,6 +220,7 @@
Introduzca el nombre de la rama.
Los espacios serán reemplazados con guiones.
Crear Rama Local
+ Sobrescribir la rama existente
Crear Etiqueta...
Nueva Etiqueta En:
Firma GPG
@@ -515,7 +515,7 @@
Email global del usuario git
Habilitar --prune para fetch
Habilitar --ignore-cr-at-eol en diff
- Se requiere Git (>= 2.23.0) para esta aplicación
+ Se requiere Git (>= 2.25.1) para esta aplicación
Ruta de instalación
Habilitar verificación HTTP SSL
Nombre de usuario
@@ -593,10 +593,12 @@
Limpiar (GC & Prune)
Ejecutar comando `git gc` para este repositorio.
Limpiar todo
+ Limpiar
Configurar este repositorio
CONTINUAR
Acciones Personalizadas
No hay ninguna Acción Personalizada
+ Descartar todos los cambios
Habilitar Opción '--reflog'
Abrir en el Explorador
Buscar Ramas/Etiquetas/Submódulos
@@ -784,6 +786,7 @@
INCLUIR ARCHIVOS NO RASTREADOS
NO HAY MENSAJES DE ENTRADA RECIENTES
NO HAY PLANTILLAS DE COMMIT
+ Restablecer Autor
Haz clic derecho en el(los) archivo(s) seleccionado(s) y elige tu opción para resolver conflictos.
Firmar
STAGED
diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml
index 0c3ab91b..25e6ca3e 100644
--- a/src/Resources/Locales/fr_FR.axaml
+++ b/src/Resources/Locales/fr_FR.axaml
@@ -43,13 +43,12 @@
Blâme
LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!
Récupérer ${0}$...
- Comparer avec HEAD
+ Comparer avec ${0}$
Comparer avec le worktree
Copier le nom de la branche
Action personnalisée
Supprimer ${0}$...
Supprimer {0} branches sélectionnées
- Rejeter tous les changements
Fast-Forward vers ${0}$
Fetch ${0}$ vers ${1}$...
Git Flow - Terminer ${0}$
@@ -484,7 +483,7 @@
E-mail utilsateur
E-mail utilsateur global
Activer --prune pour fetch
- Cette application requière Git (>= 2.23.0)
+ Cette application requière Git (>= 2.25.1)
Chemin d'installation
Activer la vérification HTTP SSL
Nom d'utilisateur
@@ -562,6 +561,7 @@
CONTINUER
Actions personnalisées
Pas d'actions personnalisées
+ Rejeter tous les changements
Activer l'option '--reflog'
Ouvrir dans l'explorateur de fichiers
Rechercher Branches/Tags/Submodules
diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml
index 23c31c6e..22c4e8fe 100644
--- a/src/Resources/Locales/it_IT.axaml
+++ b/src/Resources/Locales/it_IT.axaml
@@ -50,13 +50,12 @@
Attribuisci
L'ATTRIBUZIONE SU QUESTO FILE NON È SUPPORTATA!!!
Checkout ${0}$...
- Confronta con HEAD
+ Confronta con ${0}$
Confronta con Worktree
Copia Nome Branch
Azione personalizzata
Elimina ${0}$...
Elimina i {0} branch selezionati
- Scarta tutte le modifiche
Avanzamento Veloce a ${0}$
Recupera ${0}$ in ${1}$...
Git Flow - Completa ${0}$
@@ -505,7 +504,7 @@
Email utente Git globale
Abilita --prune durante il fetch
Abilita --ignore-cr-at-eol nel diff
- Questa applicazione richiede Git (>= 2.23.0)
+ Questa applicazione richiede Git (>= 2.25.1)
Percorso Installazione
Abilita la verifica HTTP SSL
Nome Utente
@@ -586,6 +585,7 @@
CONTINUA
Azioni Personalizzate
Nessuna Azione Personalizzata
+ Scarta tutte le modifiche
Abilita opzione '--reflog'
Apri nell'Esplora File
Cerca Branch/Tag/Sottomodulo
diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml
index ca29b985..945cf2d9 100644
--- a/src/Resources/Locales/ja_JP.axaml
+++ b/src/Resources/Locales/ja_JP.axaml
@@ -43,13 +43,11 @@
Blame
BLAMEではこのファイルはサポートされていません!!!
${0}$ をチェックアウトする...
- HEADと比較
ワークツリーと比較
ブランチ名をコピー
カスタムアクション
${0}$を削除...
選択中の{0}個のブランチを削除
- すべての変更を破棄
${0}$ へ早送りする
${0}$ から ${1}$ へフェッチする
Git Flow - Finish ${0}$
@@ -484,7 +482,7 @@
ユーザー Eメールアドレス
グローバルgitのEメールアドレス
フェッチ時に--pruneを有効化
- Git (>= 2.23.0) はこのアプリで必要です
+ Git (>= 2.25.1) はこのアプリで必要です
インストール パス
HTTP SSL 検証を有効にする
ユーザー名
@@ -562,6 +560,7 @@
続ける
カスタムアクション
カスタムアクションがありません
+ すべての変更を破棄
`--reflog` オプションを有効化
ファイルブラウザーで開く
ブランチ/タグ/サブモジュールを検索
diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml
index 7ce861e9..a75d6777 100644
--- a/src/Resources/Locales/pt_BR.axaml
+++ b/src/Resources/Locales/pt_BR.axaml
@@ -37,12 +37,11 @@
Blame
BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!
Checkout ${0}$...
- Comparar com HEAD
+ Comparar com ${0}$
Comparar com Worktree
Copiar Nome do Branch
Excluir ${0}$...
Excluir {0} branches selecionados
- Descartar todas as alterações
Fast-Forward para ${0}$
Buscar ${0}$ em ${1}$...
Git Flow - Finalizar ${0}$
@@ -441,7 +440,7 @@
Email do Usuário
Email global do usuário git
Habilita --prune ao buscar
- Git (>= 2.23.0) é necessário para este aplicativo
+ Git (>= 2.25.1) é necessário para este aplicativo
Caminho de Instalação
Nome do Usuário
Nome global do usuário git
@@ -518,6 +517,7 @@
CONTINUAR
Ações customizada
Nenhuma ação customizada
+ Descartar todas as alterações
Habilitar opção '--reflog'
Abrir no Navegador de Arquivos
Pesquisar Branches/Tags/Submódulos
diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml
index bc72fd65..0a6ccba4 100644
--- a/src/Resources/Locales/ru_RU.axaml
+++ b/src/Resources/Locales/ru_RU.axaml
@@ -50,13 +50,11 @@
Расследование
РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!
Переключиться на ${0}$...
- Сравнить с ГОЛОВОЙ (HEAD)
Сравнить с рабочим каталогом
Копировать имя ветки
Изменить действие
Удалить ${0}$...
Удалить выбранные {0} ветки
- Отклонить все изменения.
Перемотать вперёд к ${0}$
Извлечь ${0}$ в ${1}$...
Git-процесс - Завершение ${0}$
@@ -516,7 +514,7 @@
Общая электроная почта пользователя git
Разрешить (--prune) при скачивании
Разрешить (--ignore-cr-at-eol) в сравнении
- Для работы программы требуется версия Git (>= 2.23.0)
+ Для работы программы требуется версия Git (>= 2.25.1)
Путь установки
Разрешить верификацию HTTP SSL
Имя пользователя
@@ -598,6 +596,7 @@
ПРОДОЛЖИТЬ
Изменить действия
Не изменять действия
+ Отклонить все изменения.
Разрешить опцию --reflog
Открыть в файловом менеджере
Поиск веток, меток и подмодулей
diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml
index 71df97c0..e66af3ff 100644
--- a/src/Resources/Locales/ta_IN.axaml
+++ b/src/Resources/Locales/ta_IN.axaml
@@ -43,13 +43,11 @@
குற்றச்சாட்டு
இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!
${0}$ சரிபார்...
- தலையுடன் ஒப்பிடுக
பணிமரத்துடன் ஒப்பிடுக
கிளை பெயரை நகலெடு
தனிப்பயன் செயல்
${0}$ ஐ நீக்கு...
தேர்ந்தெடுக்கப்பட்ட {0} கிளைகளை நீக்கு
- எல்லா மாற்றங்களையும் நிராகரி
${0}$ இதற்கு வேகமாக முன்னோக்கிச் செல்
${0}$ ஐ ${1}$இல் பெறு...
அறிவிலி ஓட்டம் - முடி ${0}$
@@ -484,7 +482,7 @@
பயனர் மின்னஞ்சல்
உலகளாவிய அறிவிலி பயனர் மின்னஞ்சல்
--prune எடுக்கும்போது இயக்கு
- அறிவிலி (>= 2.23.0) இந்த பயன்பாட்டிற்கு தேவைப்படுகிறது
+ அறிவிலி (>= 2.25.1) இந்த பயன்பாட்டிற்கு தேவைப்படுகிறது
நிறுவல் பாதை
உஉபநெ பாகுஅ சரிபார்ப்பை இயக்கு
பயனர் பெயர்
@@ -562,6 +560,7 @@
தொடர்க
தனிப்பயன் செயல்கள்
தனிப்பயன் செயல்கள் இல்லை
+ எல்லா மாற்றங்களையும் நிராகரி
'--குறிபதிவு' விருப்பத்தை இயக்கு
கோப்பு உலாவியில் திற
கிளைகள்/குறிச்சொற்கள்/துணைத் தொகுதிகளைத் தேடு
diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml
index 297878a6..2e7b399b 100644
--- a/src/Resources/Locales/uk_UA.axaml
+++ b/src/Resources/Locales/uk_UA.axaml
@@ -43,13 +43,12 @@
Автор рядка
ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!
Перейти на ${0}$...
- Порівняти з HEAD
+ Порівняти з ${0}$
Порівняти з робочим деревом
Копіювати назву гілки
Спеціальна дія
Видалити ${0}$...
Видалити вибрані {0} гілок
- Скасувати всі зміни
Перемотати до ${0}$
Отримати ${0}$ в ${1}$...
Git Flow - Завершити ${0}$
@@ -488,7 +487,7 @@
Email користувача
Глобальний email користувача git
Увімкнути --prune при fetch
- Git (>= 2.23.0) є обов'язковим для цієї програми
+ Git (>= 2.25.1) є обов'язковим для цієї програми
Шлях встановлення
Увімкнути перевірку HTTP SSL
Ім'я користувача
@@ -566,6 +565,7 @@
ПРОДОВЖИТИ
Спеціальні дії
Немає спеціальних дій
+ Скасувати всі зміни
Увімкнути опцію '--reflog'
Відкрити у файловому менеджері
Пошук гілок/тегів/підмодулів
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 00939656..77a55f75 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -50,13 +50,12 @@
逐行追溯(blame)
选中文件不支持该操作!!!
检出(checkout) ${0}$...
- 与当前HEAD比较
+ 与当前 ${0}$ 比较
与本地工作树比较
复制分支名
自定义操作
删除 ${0}$...
删除选中的 {0} 个分支
- 放弃所有更改
快进(fast-forward)到 ${0}$
拉取(fetch) ${0}$ 至 ${1}$...
GIT工作流 - 完成 ${0}$
@@ -516,7 +515,7 @@
默认GIT用户邮箱
拉取更新时启用修剪(--prune)
对比文件时,默认忽略换行符变更 (--ignore-cr-at-eol)
- 本软件要求GIT最低版本为2.23.0
+ 本软件要求GIT最低版本为2.25.1
安装路径
启用HTTP SSL验证
用户名
@@ -594,10 +593,12 @@
清理本仓库(GC)
本操作将执行`git gc`命令。
清空过滤规则
+ 清空
配置本仓库
下一步
自定义操作
自定义操作未设置
+ 放弃所有更改
启用 --reflog 选项
在文件浏览器中打开
快速查找分支/标签/子模块
@@ -785,6 +786,7 @@
显示未跟踪文件
没有提交信息记录
没有可应用的提交信息模板
+ 重置提交者
请选中冲突文件,打开右键菜单,选择合适的解决方式
署名
已暂存
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index 026a41ed..aef769de 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -50,13 +50,12 @@
逐行溯源 (blame)
所選擇的檔案不支援該操作!
簽出 (checkout) ${0}$...
- 與目前 HEAD 比較
+ 與目前 ${0}$ 比較
與本機工作區比較
複製分支名稱
自訂動作
刪除 ${0}$...
刪除所選的 {0} 個分支
- 捨棄所有變更
快轉 (fast-forward) 到 ${0}$
提取 (fetch) ${0}$ 到 ${1}$...
Git 工作流 - 完成 ${0}$
@@ -516,7 +515,7 @@
預設 Git 使用者電子郵件
拉取變更時進行清理 (--prune)
對比檔案時,預設忽略行尾的 CR 變更 (--ignore-cr-at-eol)
- 本軟體要求 Git 最低版本為 2.23.0
+ 本軟體要求 Git 最低版本為 2.25.1
安裝路徑
啟用 HTTP SSL 驗證
使用者名稱
@@ -594,10 +593,12 @@
清理本存放庫 (GC)
本操作將執行 `git gc` 命令。
清空篩選規則
+ 清空
設定本存放庫
下一步
自訂動作
沒有自訂的動作
+ 捨棄所有變更
啟用 [--reflog] 選項
在檔案瀏覽器中開啟
快速搜尋分支/標籤/子模組
@@ -785,6 +786,7 @@
顯示未追蹤檔案
沒有提交訊息記錄
沒有可套用的提交訊息範本
+ 重設作者
請選擇發生衝突的檔案,開啟右鍵選單,選擇合適的解決方式
署名
已暫存
diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj
index 5e617561..3fe21b1a 100644
--- a/src/SourceGit.csproj
+++ b/src/SourceGit.csproj
@@ -2,11 +2,9 @@
WinExe
net9.0
- true
App.manifest
App.ico
$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)\\..\\VERSION"))
- false
true
true
diff --git a/src/ViewModels/ChangeTreeNode.cs b/src/ViewModels/ChangeTreeNode.cs
index 245c1dfe..6c061f65 100644
--- a/src/ViewModels/ChangeTreeNode.cs
+++ b/src/ViewModels/ChangeTreeNode.cs
@@ -17,6 +17,16 @@ namespace SourceGit.ViewModels
get => Change == null;
}
+ public bool ShowConflictMarker
+ {
+ get => Change is { IsConflicted: true };
+ }
+
+ public string ConflictMarker
+ {
+ get => Change?.ConflictMarker ?? string.Empty;
+ }
+
public bool IsExpanded
{
get => _isExpanded;
diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs
index bd4f2284..959cc3fe 100644
--- a/src/ViewModels/CommitDetail.cs
+++ b/src/ViewModels/CommitDetail.cs
@@ -452,7 +452,9 @@ namespace SourceGit.ViewModels
var selected = await storageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
{
- var saveTo = Path.Combine(selected[0].Path.LocalPath, Path.GetFileName(file.Path));
+ var folder = selected[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
+ var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path));
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo);
}
}
diff --git a/src/ViewModels/Conflict.cs b/src/ViewModels/Conflict.cs
index add365a3..bf93b5bc 100644
--- a/src/ViewModels/Conflict.cs
+++ b/src/ViewModels/Conflict.cs
@@ -25,6 +25,16 @@ namespace SourceGit.ViewModels
public class Conflict
{
+ public string Marker
+ {
+ get => _change.ConflictMarker;
+ }
+
+ public string Description
+ {
+ get => _change.ConflictDesc;
+ }
+
public object Theirs
{
get;
@@ -41,7 +51,13 @@ namespace SourceGit.ViewModels
{
get;
private set;
- }
+ } = false;
+
+ public bool CanUseExternalMergeTool
+ {
+ get;
+ private set;
+ } = false;
public Conflict(Repository repo, WorkingCopy wc, Models.Change change)
{
@@ -49,7 +65,11 @@ namespace SourceGit.ViewModels
_change = change;
var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null;
- IsResolved = !isSubmodule && new Commands.IsConflictResolved(repo.FullPath, change).Result();
+ if (!isSubmodule && (_change.ConflictReason == Models.ConflictReason.BothAdded || _change.ConflictReason == Models.ConflictReason.BothModified))
+ {
+ CanUseExternalMergeTool = true;
+ IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).Result();
+ }
var context = wc.InProgressContext;
if (context is CherryPickInProgress cherryPick)
diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs
index 2057a13f..5ca1ba5d 100644
--- a/src/ViewModels/Histories.cs
+++ b/src/ViewModels/Histories.cs
@@ -333,10 +333,12 @@ namespace SourceGit.ViewModels
{
log = _repo.CreateLog("Save as Patch");
+ var folder = picker[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
var succ = false;
for (var i = 0; i < selected.Count; i++)
{
- var saveTo = GetPatchFileName(picker[0].Path.LocalPath, selected[i], i);
+ var saveTo = GetPatchFileName(folderPath, selected[i], i);
succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, selected[i].SHA, saveTo).Use(log).Exec());
if (!succ)
break;
@@ -691,8 +693,10 @@ namespace SourceGit.ViewModels
{
log = _repo.CreateLog("Save as Patch");
- var saveTo = GetPatchFileName(selected[0].Path.LocalPath, commit);
- var succ = new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).Exec();
+ var folder = selected[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
+ var saveTo = GetPatchFileName(folderPath, commit);
+ var succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).Exec());
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs
index 1c4d4480..7811014a 100644
--- a/src/ViewModels/InteractiveRebase.cs
+++ b/src/ViewModels/InteractiveRebase.cs
@@ -178,7 +178,7 @@ namespace SourceGit.ViewModels
if (action == Models.InteractiveRebaseAction.Squash || action == Models.InteractiveRebaseAction.Fixup)
return;
}
-
+
item.Action = action;
UpdateItems();
}
diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs
index b02cf36a..fcc4a853 100644
--- a/src/ViewModels/Repository.cs
+++ b/src/ViewModels/Repository.cs
@@ -639,7 +639,7 @@ namespace SourceGit.ViewModels
Task.Run(RefreshWorktrees);
Task.Run(RefreshWorkingCopyChanges);
Task.Run(RefreshStashes);
-
+
Task.Run(() =>
{
var config = new Commands.Config(_fullpath).ListAll();
@@ -1766,6 +1766,18 @@ namespace SourceGit.ViewModels
return menu;
}
+ public void DiscardAllChanges()
+ {
+ if (CanCreatePopup())
+ ShowPopup(new Discard(this));
+ }
+
+ public void ClearStashes()
+ {
+ if (CanCreatePopup())
+ ShowPopup(new ClearStashes(this));
+ }
+
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
{
var menu = new ContextMenu();
@@ -1785,19 +1797,6 @@ namespace SourceGit.ViewModels
{
if (!IsBare)
{
- var discard = new MenuItem();
- discard.Header = App.Text("BranchCM.DiscardAll");
- discard.Icon = App.CreateMenuIcon("Icons.Undo");
- discard.Click += (_, e) =>
- {
- if (CanCreatePopup())
- ShowPopup(new Discard(this));
- e.Handled = true;
- };
-
- menu.Items.Add(discard);
- menu.Items.Add(new MenuItem() { Header = "-" });
-
if (!string.IsNullOrEmpty(branch.Upstream))
{
var upstream = branch.Upstream.Substring(13);
@@ -1828,6 +1827,7 @@ namespace SourceGit.ViewModels
};
menu.Items.Add(fastForward);
+ menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(pull);
}
}
@@ -1866,21 +1866,6 @@ namespace SourceGit.ViewModels
};
menu.Items.Add(fastForward);
- var selectedCommit = (_histories?.DetailContext as CommitDetail)?.Commit;
- if (selectedCommit != null && !selectedCommit.SHA.Equals(branch.Head, StringComparison.Ordinal))
- {
- var move = new MenuItem();
- move.Header = App.Text("BranchCM.ResetToSelectedCommit", branch.Name, selectedCommit.SHA.Substring(0, 10));
- move.Icon = App.CreateMenuIcon("Icons.Reset");
- move.Click += (_, e) =>
- {
- if (CanCreatePopup())
- ShowPopup(new ResetWithoutCheckout(this, branch, selectedCommit));
- e.Handled = true;
- };
- menu.Items.Add(move);
- }
-
var fetchInto = new MenuItem();
fetchInto.Header = App.Text("BranchCM.FetchInto", upstream.FriendlyName, branch.Name);
fetchInto.Icon = App.CreateMenuIcon("Icons.Fetch");
@@ -1924,15 +1909,34 @@ namespace SourceGit.ViewModels
menu.Items.Add(rebase);
}
- var compareWithHead = new MenuItem();
- compareWithHead.Header = App.Text("BranchCM.CompareWithHead");
- compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
- compareWithHead.Click += (_, _) =>
+ if (worktree == null)
+ {
+ var selectedCommit = (_histories?.DetailContext as CommitDetail)?.Commit;
+ if (selectedCommit != null && !selectedCommit.SHA.Equals(branch.Head, StringComparison.Ordinal))
+ {
+ var move = new MenuItem();
+ move.Header = App.Text("BranchCM.ResetToSelectedCommit", branch.Name, selectedCommit.SHA.Substring(0, 10));
+ move.Icon = App.CreateMenuIcon("Icons.Reset");
+ move.Click += (_, e) =>
+ {
+ if (CanCreatePopup())
+ ShowPopup(new ResetWithoutCheckout(this, branch, selectedCommit));
+ e.Handled = true;
+ };
+ menu.Items.Add(new MenuItem() { Header = "-" });
+ menu.Items.Add(move);
+ }
+ }
+
+ var compareWithCurrent = new MenuItem();
+ compareWithCurrent.Header = App.Text("BranchCM.CompareWithCurrent", _currentBranch.Name);
+ compareWithCurrent.Icon = App.CreateMenuIcon("Icons.Compare");
+ compareWithCurrent.Click += (_, _) =>
{
App.ShowWindow(new BranchCompare(_fullpath, branch, _currentBranch), false);
};
menu.Items.Add(new MenuItem() { Header = "-" });
- menu.Items.Add(compareWithHead);
+ menu.Items.Add(compareWithCurrent);
if (_localChangesCount > 0)
{
diff --git a/src/ViewModels/Reword.cs b/src/ViewModels/Reword.cs
index 82fa3169..72dd9e58 100644
--- a/src/ViewModels/Reword.cs
+++ b/src/ViewModels/Reword.cs
@@ -37,9 +37,11 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Reword HEAD");
Use(log);
+ var signOff = _repo.Settings.EnableSignOffForCommit;
return Task.Run(() =>
{
- var succ = new Commands.Commit(_repo.FullPath, _message, true, _repo.Settings.EnableSignOffForCommit).Use(log).Run();
+ // For reword (only changes the commit message), disable `--reset-author`
+ var succ = new Commands.Commit(_repo.FullPath, _message, signOff, true, false).Use(log).Run();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
diff --git a/src/ViewModels/Squash.cs b/src/ViewModels/Squash.cs
index fa9d98e1..8e9bae8b 100644
--- a/src/ViewModels/Squash.cs
+++ b/src/ViewModels/Squash.cs
@@ -34,6 +34,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
+ var signOff = _repo.Settings.EnableSignOffForCommit;
var autoStashed = false;
var succ = false;
@@ -52,7 +53,7 @@ namespace SourceGit.ViewModels
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).Use(log).Run();
+ succ = new Commands.Commit(_repo.FullPath, _message, signOff, true, false).Use(log).Run();
if (succ && autoStashed)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
diff --git a/src/ViewModels/StashChanges.cs b/src/ViewModels/StashChanges.cs
index 0b4fa7db..11e449fb 100644
--- a/src/ViewModels/StashChanges.cs
+++ b/src/ViewModels/StashChanges.cs
@@ -117,16 +117,16 @@ namespace SourceGit.ViewModels
foreach (var c in changes)
paths.Add(c.Path);
- var tmpFile = Path.GetTempFileName();
- File.WriteAllLines(tmpFile, paths);
- succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, tmpFile, KeepIndex);
- File.Delete(tmpFile);
+ var pathSpecFile = Path.GetTempFileName();
+ File.WriteAllLines(pathSpecFile, paths);
+ succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, pathSpecFile, KeepIndex);
+ File.Delete(pathSpecFile);
}
else
{
- for (int i = 0; i < changes.Count; i += 10)
+ for (int i = 0; i < changes.Count; i += 32)
{
- var count = Math.Min(10, changes.Count - i);
+ var count = Math.Min(32, changes.Count - i);
var step = changes.GetRange(i, count);
succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, step, KeepIndex);
if (!succ)
diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs
index b974d427..5449e4c1 100644
--- a/src/ViewModels/StashesPage.cs
+++ b/src/ViewModels/StashesPage.cs
@@ -53,34 +53,32 @@ namespace SourceGit.ViewModels
if (value == null)
{
Changes = null;
+ _untracked.Clear();
}
else
{
Task.Run(() =>
{
- var changes = null as List;
+ var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
+ var untracked = new List();
- if (Native.OS.GitVersion >= Models.GitVersions.STASH_SHOW_WITH_UNTRACKED)
+ if (value.Parents.Count == 3)
{
- changes = new Commands.QueryStashChanges(_repo.FullPath, value.Name).Result();
- }
- else
- {
- changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
- if (value.Parents.Count == 3)
- {
- var untracked = new Commands.CompareRevisions(_repo.FullPath, Models.Commit.EmptyTreeSHA1, value.Parents[2]).Result();
- var needSort = changes.Count > 0;
+ untracked = new Commands.CompareRevisions(_repo.FullPath, Models.Commit.EmptyTreeSHA1, value.Parents[2]).Result();
+ var needSort = changes.Count > 0 && untracked.Count > 0;
- foreach (var c in untracked)
- changes.Add(c);
+ foreach (var c in untracked)
+ changes.Add(c);
- if (needSort)
- changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
- }
+ if (needSort)
+ changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
}
- Dispatcher.UIThread.Invoke(() => Changes = changes);
+ Dispatcher.UIThread.Invoke(() =>
+ {
+ _untracked = untracked;
+ Changes = changes;
+ });
});
}
}
@@ -106,7 +104,7 @@ namespace SourceGit.ViewModels
{
if (value == null)
DiffContext = null;
- else if (value.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
+ else if (_untracked.Contains(value))
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(Models.Commit.EmptyTreeSHA1, _selectedStash.Parents[2], value), _diffContext);
else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext);
@@ -129,6 +127,7 @@ namespace SourceGit.ViewModels
{
_stashes?.Clear();
_changes?.Clear();
+ _untracked.Clear();
_repo = null;
_selectedStash = null;
@@ -181,7 +180,7 @@ namespace SourceGit.ViewModels
var opts = new List();
foreach (var c in _changes)
{
- if (c.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
+ if (_untracked.Contains(c))
opts.Add(new Models.DiffOption(Models.Commit.EmptyTreeSHA1, _selectedStash.Parents[2], c));
else
opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c));
@@ -273,12 +272,6 @@ namespace SourceGit.ViewModels
return menu;
}
- public void Clear()
- {
- if (_repo.CanCreatePopup())
- _repo.ShowPopup(new ClearStashes(_repo));
- }
-
public void ClearSearchFilter()
{
SearchFilter = string.Empty;
@@ -304,11 +297,12 @@ namespace SourceGit.ViewModels
}
private Repository _repo = null;
- private List _stashes = new List();
- private List _visibleStashes = new List();
+ private List _stashes = [];
+ private List _visibleStashes = [];
private string _searchFilter = string.Empty;
private Models.Stash _selectedStash = null;
private List _changes = null;
+ private List _untracked = [];
private Models.Change _selectedChange = null;
private DiffContext _diffContext = null;
}
diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs
index 7c2d95f9..6469b564 100644
--- a/src/ViewModels/WorkingCopy.cs
+++ b/src/ViewModels/WorkingCopy.cs
@@ -91,6 +91,7 @@ namespace SourceGit.ViewModels
else
{
CommitMessage = string.Empty;
+ ResetAuthor = false;
}
Staged = GetStagedChanges();
@@ -100,6 +101,12 @@ namespace SourceGit.ViewModels
}
}
+ public bool ResetAuthor
+ {
+ get => _resetAuthor;
+ set => SetProperty(ref _resetAuthor, value);
+ }
+
public string Filter
{
get => _filter;
@@ -381,7 +388,9 @@ namespace SourceGit.ViewModels
if (!change.IsConflicted)
continue;
- if (change.WorkTree == Models.ChangeState.Deleted)
+ if (change.ConflictReason == Models.ConflictReason.BothDeleted ||
+ change.ConflictReason == Models.ConflictReason.DeletedByThem ||
+ change.ConflictReason == Models.ConflictReason.AddedByUs)
{
var fullpath = Path.Combine(_repo.FullPath, change.Path);
if (File.Exists(fullpath))
@@ -403,7 +412,12 @@ namespace SourceGit.ViewModels
}
if (needStage.Count > 0)
- await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Use(log).Exec());
+ {
+ var pathSpecFile = Path.GetTempFileName();
+ await File.WriteAllLinesAsync(pathSpecFile, needStage);
+ await Task.Run(() => new Commands.Add(_repo.FullPath, pathSpecFile).Use(log).Exec());
+ File.Delete(pathSpecFile);
+ }
log.Complete();
_repo.MarkWorkingCopyDirtyManually();
@@ -423,7 +437,9 @@ namespace SourceGit.ViewModels
if (!change.IsConflicted)
continue;
- if (change.Index == Models.ChangeState.Deleted)
+ if (change.ConflictReason == Models.ConflictReason.BothDeleted ||
+ change.ConflictReason == Models.ConflictReason.DeletedByUs ||
+ change.ConflictReason == Models.ConflictReason.AddedByThem)
{
var fullpath = Path.Combine(_repo.FullPath, change.Path);
if (File.Exists(fullpath))
@@ -445,7 +461,12 @@ namespace SourceGit.ViewModels
}
if (needStage.Count > 0)
- await Task.Run(() => new Commands.Add(_repo.FullPath, needStage).Use(log).Exec());
+ {
+ var pathSpecFile = Path.GetTempFileName();
+ await File.WriteAllLinesAsync(pathSpecFile, needStage);
+ await Task.Run(() => new Commands.Add(_repo.FullPath, pathSpecFile).Use(log).Exec());
+ File.Delete(pathSpecFile);
+ }
log.Complete();
_repo.MarkWorkingCopyDirtyManually();
@@ -456,7 +477,7 @@ namespace SourceGit.ViewModels
{
var toolType = Preferences.Instance.ExternalMergeToolType;
var toolPath = Preferences.Instance.ExternalMergeToolPath;
- var file = change?.Path; // NOTE: With no arg, mergetool runs on on every file with merge conflicts!
+ var file = change?.Path; // NOTE: With no arg, mergetool runs on every file with merge conflicts!
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, file));
}
@@ -759,7 +780,7 @@ namespace SourceGit.ViewModels
byParentFolder.IsVisible = !isRooted;
byParentFolder.Click += (_, e) =>
{
- var dir = Path.GetDirectoryName(change.Path).Replace("\\", "/");
+ var dir = Path.GetDirectoryName(change.Path)!.Replace("\\", "/");
Commands.GitIgnore.Add(_repo.FullPath, dir + "/");
e.Handled = true;
};
@@ -781,7 +802,7 @@ namespace SourceGit.ViewModels
byExtensionInSameFolder.IsVisible = !isRooted;
byExtensionInSameFolder.Click += (_, e) =>
{
- var dir = Path.GetDirectoryName(change.Path).Replace("\\", "/");
+ var dir = Path.GetDirectoryName(change.Path)!.Replace("\\", "/");
Commands.GitIgnore.Add(_repo.FullPath, $"{dir}/*{extension}");
e.Handled = true;
};
@@ -1608,30 +1629,19 @@ namespace SourceGit.ViewModels
{
await Task.Run(() => new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).Exec());
}
- else if (Native.OS.GitVersion >= Models.GitVersions.ADD_WITH_PATHSPECFILE)
- {
- var paths = new List();
- foreach (var c in changes)
- paths.Add(c.Path);
-
- var tmpFile = Path.GetTempFileName();
- File.WriteAllLines(tmpFile, paths);
- await Task.Run(() => new Commands.Add(_repo.FullPath, tmpFile).Use(log).Exec());
- File.Delete(tmpFile);
- }
else
{
var paths = new List();
foreach (var c in changes)
paths.Add(c.Path);
- 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).Use(log).Exec());
- }
+ var pathSpecFile = Path.GetTempFileName();
+ await File.WriteAllLinesAsync(pathSpecFile, paths);
+ await Task.Run(() => new Commands.Add(_repo.FullPath, pathSpecFile).Use(log).Exec());
+ File.Delete(pathSpecFile);
}
log.Complete();
+
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
IsStaging = false;
@@ -1655,19 +1665,23 @@ namespace SourceGit.ViewModels
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).Use(log).Exec());
- }
else
{
- for (int i = 0; i < count; i += 10)
+ var paths = new List();
+ foreach (var c in changes)
{
- var step = changes.GetRange(i, Math.Min(10, count - i));
- await Task.Run(() => new Commands.Reset(_repo.FullPath, step).Use(log).Exec());
+ paths.Add(c.Path);
+ if (c.Index == Models.ChangeState.Renamed)
+ paths.Add(c.OriginalPath);
}
+
+ var pathSpecFile = Path.GetTempFileName();
+ await File.WriteAllLinesAsync(pathSpecFile, paths);
+ await Task.Run(() => new Commands.Restore(_repo.FullPath, pathSpecFile, true).Use(log).Exec());
+ File.Delete(pathSpecFile);
}
log.Complete();
+
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
IsUnstaging = false;
@@ -1717,6 +1731,7 @@ namespace SourceGit.ViewModels
_repo.Settings.PushCommitMessage(_commitMessage);
_repo.SetWatcherEnabled(false);
+ var signOff = _repo.Settings.EnableSignOffForCommit;
var log = _repo.CreateLog("Commit");
Task.Run(() =>
{
@@ -1725,7 +1740,7 @@ namespace SourceGit.ViewModels
succ = new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).Exec();
if (succ)
- succ = new Commands.Commit(_repo.FullPath, _commitMessage, _useAmend, _repo.Settings.EnableSignOffForCommit).Use(log).Run();
+ succ = new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).Run();
log.Complete();
@@ -1762,7 +1777,7 @@ namespace SourceGit.ViewModels
{
if (old.Count != cur.Count)
return true;
-
+
var oldMap = new Dictionary();
foreach (var c in old)
oldMap.Add(c.Path, c);
@@ -1785,6 +1800,7 @@ namespace SourceGit.ViewModels
private bool _isUnstaging = false;
private bool _isCommitting = false;
private bool _useAmend = false;
+ private bool _resetAuthor = false;
private bool _hasRemotes = false;
private List _cached = [];
private List _unstaged = [];
diff --git a/src/Views/AddWorktree.axaml.cs b/src/Views/AddWorktree.axaml.cs
index 30369247..dad947de 100644
--- a/src/Views/AddWorktree.axaml.cs
+++ b/src/Views/AddWorktree.axaml.cs
@@ -23,7 +23,11 @@ namespace SourceGit.Views
{
var selected = await toplevel.StorageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
- TxtLocation.Text = selected[0].Path.LocalPath;
+ {
+ var folder = selected[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
+ TxtLocation.Text = folderPath;
+ }
}
catch (Exception exception)
{
diff --git a/src/Views/ChangeCollectionView.axaml b/src/Views/ChangeCollectionView.axaml
index 36de5685..43af3a9a 100644
--- a/src/Views/ChangeCollectionView.axaml
+++ b/src/Views/ChangeCollectionView.axaml
@@ -37,11 +37,11 @@
SelectionChanged="OnRowSelectionChanged">
-
+ DataContextChanged="OnRowDataContextChanged">
-
-
+
+
+
+
+
+
@@ -77,17 +85,17 @@
+ DataContextChanged="OnRowDataContextChanged">
-
+
+
+
+
+ DataContextChanged="OnRowDataContextChanged">
-
+
+
+
+
diff --git a/src/Views/ChangeCollectionView.axaml.cs b/src/Views/ChangeCollectionView.axaml.cs
index 00499fce..6623a60b 100644
--- a/src/Views/ChangeCollectionView.axaml.cs
+++ b/src/Views/ChangeCollectionView.axaml.cs
@@ -3,9 +3,11 @@ using System.Collections.Generic;
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Controls.Documents;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
+using Avalonia.Media;
using Avalonia.VisualTree;
namespace SourceGit.Views
@@ -86,7 +88,7 @@ namespace SourceGit.Views
}
public static readonly StyledProperty AutoSelectFirstChangeProperty =
- AvaloniaProperty.Register(nameof(AutoSelectFirstChange), false);
+ AvaloniaProperty.Register(nameof(AutoSelectFirstChange));
public bool AutoSelectFirstChange
{
@@ -229,6 +231,28 @@ namespace SourceGit.Views
UpdateSelection();
}
+ private void OnRowDataContextChanged(object sender, EventArgs e)
+ {
+ if (sender is not Control control)
+ return;
+
+ if (control.DataContext is ViewModels.ChangeTreeNode node)
+ {
+ if (node.Change is { } c)
+ UpdateRowTips(control, c);
+ else
+ ToolTip.SetTip(control, node.FullPath);
+ }
+ else if (control.DataContext is Models.Change change)
+ {
+ UpdateRowTips(control, change);
+ }
+ else
+ {
+ ToolTip.SetTip(control, null);
+ }
+ }
+
private void OnRowDoubleTapped(object sender, TappedEventArgs e)
{
var grid = sender as Grid;
@@ -466,6 +490,21 @@ namespace SourceGit.Views
}
}
+ private void UpdateRowTips(Control control, Models.Change change)
+ {
+ var tip = new TextBlock() { TextWrapping = TextWrapping.Wrap };
+ tip.Inlines!.Add(new Run(change.Path));
+ tip.Inlines!.Add(new Run(" • ") { Foreground = Brushes.Gray });
+ tip.Inlines!.Add(new Run(IsUnstagedChange ? change.WorkTreeDesc : change.IndexDesc) { Foreground = Brushes.Gray });
+ if (change.IsConflicted)
+ {
+ tip.Inlines!.Add(new Run(" • ") { Foreground = Brushes.Gray });
+ tip.Inlines!.Add(new Run(change.ConflictDesc) { Foreground = Brushes.Gray });
+ }
+
+ ToolTip.SetTip(control, tip);
+ }
+
private bool _disableSelectionChangingEvent = false;
}
}
diff --git a/src/Views/ChangeStatusIcon.cs b/src/Views/ChangeStatusIcon.cs
index c1185174..d66ac11d 100644
--- a/src/Views/ChangeStatusIcon.cs
+++ b/src/Views/ChangeStatusIcon.cs
@@ -9,6 +9,7 @@ namespace SourceGit.Views
{
public class ChangeStatusIcon : Control
{
+ private static readonly string[] INDICATOR = ["?", "±", "T", "+", "−", "➜", "❏", "★", "!"];
private static readonly IBrush[] BACKGROUNDS = [
Brushes.Transparent,
new LinearGradientBrush
@@ -56,9 +57,6 @@ namespace SourceGit.Views
Brushes.OrangeRed,
];
- private static readonly string[] INDICATOR = ["?", "±", "T", "+", "−", "➜", "❏", "★", "!"];
- private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Untracked", "Conflict"];
-
public static readonly StyledProperty IsUnstagedChangeProperty =
AvaloniaProperty.Register(nameof(IsUnstagedChange));
@@ -116,22 +114,7 @@ namespace SourceGit.Views
base.OnPropertyChanged(change);
if (change.Property == IsUnstagedChangeProperty || change.Property == ChangeProperty)
- {
- var isUnstaged = IsUnstagedChange;
- var c = Change;
- if (c == null)
- {
- ToolTip.SetTip(this, null);
- return;
- }
-
- if (isUnstaged)
- ToolTip.SetTip(this, TIPS[(int)c.WorkTree]);
- else
- ToolTip.SetTip(this, TIPS[(int)c.Index]);
-
InvalidateVisual();
- }
}
}
}
diff --git a/src/Views/Clone.axaml.cs b/src/Views/Clone.axaml.cs
index 1c299211..9316721a 100644
--- a/src/Views/Clone.axaml.cs
+++ b/src/Views/Clone.axaml.cs
@@ -23,7 +23,11 @@ namespace SourceGit.Views
{
var selected = await toplevel.StorageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
- TxtParentFolder.Text = selected[0].Path.LocalPath;
+ {
+ var folder = selected[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
+ TxtParentFolder.Text = folderPath;
+ }
}
catch (Exception exception)
{
diff --git a/src/Views/ConfigureWorkspace.axaml.cs b/src/Views/ConfigureWorkspace.axaml.cs
index 43b28e2f..06294caf 100644
--- a/src/Views/ConfigureWorkspace.axaml.cs
+++ b/src/Views/ConfigureWorkspace.axaml.cs
@@ -32,7 +32,9 @@ namespace SourceGit.Views
var selected = await StorageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
{
- workspace.Selected.DefaultCloneDir = selected[0].Path.LocalPath;
+ var folder = selected[0];
+ var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
+ workspace.Selected.DefaultCloneDir = folderPath;
}
}
catch (Exception ex)
diff --git a/src/Views/Conflict.axaml b/src/Views/Conflict.axaml
index 6e8aceb3..71bb0b41 100644
--- a/src/Views/Conflict.axaml
+++ b/src/Views/Conflict.axaml
@@ -14,7 +14,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -97,27 +105,27 @@
-
-
-
-
+
+
+
+
-