Merge branch 'release/v2025.17'

This commit is contained in:
leo 2025-05-12 09:23:46 +08:00
commit 01625ada1a
No known key found for this signature in database
48 changed files with 887 additions and 352 deletions

View file

@ -6,55 +6,19 @@ This document shows the translation status of each locale file in the repository
### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)
### ![de__DE](https://img.shields.io/badge/de__DE-95.07%25-yellow)
### ![de__DE](https://img.shields.io/badge/de__DE-99.74%25-yellow)
<details>
<summary>Missing keys in de_DE.axaml</summary>
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
- Text.Bisect.Detecting
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchUpstreamInvalid
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.CustomAction.WaitForExit
- Text.Configure.Git.PreferredMergeMode
- Text.Configure.IssueTracker.AddSampleAzure
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CopyFullPath
- Text.Diff.First
- Text.Diff.Last
- Text.Preferences.AI.Streaming
- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.StashCM.SaveAsPatch
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
- Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
</details>
### ![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen)
### ![fr__FR](https://img.shields.io/badge/fr__FR-96.37%25-yellow)
### ![fr__FR](https://img.shields.io/badge/fr__FR-95.50%25-yellow)
<details>
<summary>Missing keys in fr_FR.axaml</summary>
@ -66,6 +30,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
@ -75,9 +40,15 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
@ -90,7 +61,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![it__IT](https://img.shields.io/badge/it__IT-96.11%25-yellow)
### ![it__IT](https://img.shields.io/badge/it__IT-95.24%25-yellow)
<details>
<summary>Missing keys in it_IT.axaml</summary>
@ -102,6 +73,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
@ -112,10 +84,16 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CopyFullPath
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
@ -128,7 +106,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![ja__JP](https://img.shields.io/badge/ja__JP-96.11%25-yellow)
### ![ja__JP](https://img.shields.io/badge/ja__JP-95.24%25-yellow)
<details>
<summary>Missing keys in ja_JP.axaml</summary>
@ -140,6 +118,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
@ -149,11 +128,17 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.FilterCommits
- Text.Repository.Search.ByContent
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
@ -166,7 +151,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![pt__BR](https://img.shields.io/badge/pt__BR-87.68%25-yellow)
### ![pt__BR](https://img.shields.io/badge/pt__BR-86.89%25-yellow)
<details>
<summary>Missing keys in pt_BR.axaml</summary>
@ -187,6 +172,7 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CustomAction
- Text.BranchCM.MergeMultiBranches
- Text.BranchUpstreamInvalid
- Text.Checkout.RecurseSubmodules
- Text.Clone.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
@ -215,6 +201,8 @@ This document shows the translation status of each locale file in the repository
- Text.Diff.UseBlockNavigation
- Text.Fetch.Force
- Text.FileCM.ResolveUsing
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.Clone
- Text.InProgress.CherryPick.Head
- Text.InProgress.Merge.Operating
@ -232,6 +220,9 @@ This document shows the translation status of each locale file in the repository
- Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Preferences.Git.SSLVerify
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.FilterCommits
- Text.Repository.HistoriesLayout
- Text.Repository.HistoriesLayout.Horizontal
@ -247,6 +238,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
@ -271,7 +263,7 @@ This document shows the translation status of each locale file in the repository
### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)
### ![ta__IN](https://img.shields.io/badge/ta__IN-96.37%25-yellow)
### ![ta__IN](https://img.shields.io/badge/ta__IN-95.50%25-yellow)
<details>
<summary>Missing keys in ta_IN.axaml</summary>
@ -283,6 +275,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
@ -292,9 +285,15 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.UpdateSubmodules.Target
- Text.ViewLogs
- Text.ViewLogs.Clear
@ -307,7 +306,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![uk__UA](https://img.shields.io/badge/uk__UA-97.54%25-yellow)
### ![uk__UA](https://img.shields.io/badge/uk__UA-96.66%25-yellow)
<details>
<summary>Missing keys in uk_UA.axaml</summary>
@ -319,14 +318,21 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitMessageTextBox.SubjectCount
- Text.ConfigureWorkspace.Name
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog

View file

@ -1 +1 @@
2025.16
2025.17

View file

@ -78,7 +78,7 @@ namespace SourceGit
return builder;
}
private static void LogException(Exception ex)
public static void LogException(Exception ex)
{
if (ex == null)
return;

View file

@ -11,15 +11,24 @@ namespace SourceGit.Commands
Context = repo;
}
public bool Branch(string branch)
public bool Branch(string branch, bool force)
{
Args = $"checkout --recurse-submodules --progress {branch}";
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --progress {branch}";
return Exec();
}
public bool Branch(string branch, string basedOn)
public bool Branch(string branch, string basedOn, bool force)
{
Args = $"checkout --recurse-submodules --progress -b {branch} {basedOn}";
var option = force ? "--force" : string.Empty;
Args = $"checkout --progress -b {branch} {basedOn}";
return Exec();
}
public bool Commit(string commitId, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --detach --progress {commitId}";
return Exec();
}
@ -56,11 +65,5 @@ namespace SourceGit.Commands
Args = $"checkout --no-overlay {revision} -- \"{file}\"";
return Exec();
}
public bool Commit(string commitId)
{
Args = $"checkout --detach --progress {commitId}";
return Exec();
}
}
}

View file

@ -1,31 +1,12 @@
using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands
namespace SourceGit.Commands
{
public class Clean : Command
{
public Clean(string repo, bool includeIgnored)
public Clean(string repo)
{
WorkingDirectory = repo;
Context = repo;
Args = includeIgnored ? "clean -qfdx" : "clean -qfd";
}
public Clean(string repo, List<string> files)
{
var builder = new StringBuilder();
builder.Append("clean -qfd --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
WorkingDirectory = repo;
Context = repo;
Args = builder.ToString();
Args = "clean -qfdx";
}
}
}

View file

@ -28,11 +28,11 @@ namespace SourceGit.Commands
Context = repo;
if (ignoreWhitespace)
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --ignore-all-space --unified={unified} {opt}";
Args = $"diff --no-ext-diff --patch --ignore-all-space --unified={unified} {opt}";
else if (Models.DiffOption.IgnoreCRAtEOL)
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --ignore-cr-at-eol --unified={unified} {opt}";
Args = $"diff --no-ext-diff --patch --ignore-cr-at-eol --unified={unified} {opt}";
else
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --unified={unified} {opt}";
Args = $"diff --no-ext-diff --patch --unified={unified} {opt}";
}
public Models.DiffResult Result()

View file

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Avalonia.Threading;
namespace SourceGit.Commands
{
@ -7,33 +10,71 @@ namespace SourceGit.Commands
{
public static void All(string repo, bool includeIgnored, Models.ICommandLog log)
{
var changes = new QueryLocalChanges(repo).Result();
try
{
foreach (var c in changes)
{
if (c.WorkTree == Models.ChangeState.Untracked ||
c.WorkTree == Models.ChangeState.Added ||
c.Index == Models.ChangeState.Added ||
c.Index == Models.ChangeState.Renamed)
{
var fullPath = Path.Combine(repo, c.Path);
if (Directory.Exists(fullPath))
Directory.Delete(fullPath, true);
else
File.Delete(fullPath);
}
}
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
});
}
new Restore(repo) { Log = log }.Exec();
new Clean(repo, includeIgnored) { Log = log }.Exec();
if (includeIgnored)
new Clean(repo) { Log = log }.Exec();
}
public static void Changes(string repo, List<Models.Change> changes, Models.ICommandLog log)
{
var needClean = new List<string>();
var needCheckout = new List<string>();
var restores = new List<string>();
try
{
foreach (var c in changes)
{
if (c.WorkTree == Models.ChangeState.Untracked || c.WorkTree == Models.ChangeState.Added)
needClean.Add(c.Path);
{
var fullPath = Path.Combine(repo, c.Path);
if (Directory.Exists(fullPath))
Directory.Delete(fullPath, true);
else
needCheckout.Add(c.Path);
File.Delete(fullPath);
}
else
{
restores.Add(c.Path);
}
}
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
});
}
for (int i = 0; i < needClean.Count; i += 10)
for (int i = 0; i < restores.Count; i += 10)
{
var count = Math.Min(10, needClean.Count - i);
new Clean(repo, needClean.GetRange(i, count)) { Log = log }.Exec();
}
for (int i = 0; i < needCheckout.Count; i += 10)
{
var count = Math.Min(10, needCheckout.Count - i);
new Restore(repo, needCheckout.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
var count = Math.Min(10, restores.Count - i);
new Restore(repo, restores.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Threading;
@ -134,7 +135,7 @@ namespace SourceGit.Commands
return start.Exec();
}
public static bool Finish(string repo, string type, string name, bool keepBranch, Models.ICommandLog log)
public static bool Finish(string repo, string type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
{
if (!SUPPORTED_BRANCH_TYPES.Contains(type))
{
@ -146,11 +147,22 @@ namespace SourceGit.Commands
return false;
}
var option = keepBranch ? "-k" : string.Empty;
var builder = new StringBuilder();
builder.Append("flow ");
builder.Append(type);
builder.Append(" finish ");
if (squash)
builder.Append("--squash ");
if (push)
builder.Append("--push ");
if (keepBranch)
builder.Append("-k ");
builder.Append(name);
var finish = new Command();
finish.WorkingDirectory = repo;
finish.Context = repo;
finish.Args = $"flow {type} finish {option} {name}";
finish.Args = builder.ToString();
finish.Log = log;
return finish.Exec();
}

View file

@ -14,7 +14,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "branch -l --all -v --format=\"%(refname)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
}
public List<Models.Branch> Result()
@ -49,7 +49,7 @@ namespace SourceGit.Commands
private Models.Branch ParseLine(string line)
{
var parts = line.Split('\0');
if (parts.Length != 5)
if (parts.Length != 6)
return null;
var branch = new Models.Branch();
@ -83,12 +83,13 @@ namespace SourceGit.Commands
}
branch.FullName = refName;
branch.Head = parts[1];
branch.IsCurrent = parts[2] == "*";
branch.Upstream = parts[3];
branch.CommitterDate = ulong.Parse(parts[1]);
branch.Head = parts[2];
branch.IsCurrent = parts[3] == "*";
branch.Upstream = parts[4];
branch.IsUpstreamGone = false;
if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal))
if (branch.IsLocal && !string.IsNullOrEmpty(parts[5]) && !parts[5].Equals("=", StringComparison.Ordinal))
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
else
branch.TrackStatus = new Models.BranchTrackStatus();

View file

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

View file

@ -23,10 +23,17 @@ namespace SourceGit.Models
}
}
public enum BranchSortMode
{
Name = 0,
CommitterDate,
}
public class Branch
{
public string Name { get; set; }
public string FullName { get; set; }
public ulong CommitterDate { get; set; }
public string Head { get; set; }
public bool IsLocal { get; set; }
public bool IsCurrent { get; set; }

View file

@ -64,8 +64,8 @@ namespace SourceGit.Models
{
const double unitWidth = 12;
const double halfWidth = 6;
const double unitHeight = 28;
const double halfHeight = 14;
const double unitHeight = 1;
const double halfHeight = 0.5;
var temp = new CommitGraph();
var unsolved = new List<PathHelper>();

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
namespace SourceGit.Models
@ -22,24 +22,24 @@ namespace SourceGit.Models
{
if (remote.TryGetVisitURL(out var url))
{
var trimmedUrl = url;
var trimmedUrl = url.AsSpan();
if (url.EndsWith(".git"))
trimmedUrl = url.Substring(0, url.Length - 4);
trimmedUrl = url.AsSpan(0, url.Length - 4);
if (url.StartsWith("https://github.com/", StringComparison.Ordinal))
outs.Add(new($"Github ({trimmedUrl.Substring(19)})", $"{url}/commit/"));
outs.Add(new($"Github ({trimmedUrl.Slice(19)})", $"{url}/commit/"));
else if (url.StartsWith("https://gitlab.", StringComparison.Ordinal))
outs.Add(new($"GitLab ({trimmedUrl.Substring(trimmedUrl.Substring(15).IndexOf('/') + 16)})", $"{url}/-/commit/"));
outs.Add(new($"GitLab ({trimmedUrl.Slice(trimmedUrl.Slice(15).IndexOf('/') + 16)})", $"{url}/-/commit/"));
else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal))
outs.Add(new($"Gitee ({trimmedUrl.Substring(18)})", $"{url}/commit/"));
outs.Add(new($"Gitee ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
else if (url.StartsWith("https://bitbucket.org/", StringComparison.Ordinal))
outs.Add(new($"BitBucket ({trimmedUrl.Substring(22)})", $"{url}/commits/"));
outs.Add(new($"BitBucket ({trimmedUrl.Slice(22)})", $"{url}/commits/"));
else if (url.StartsWith("https://codeberg.org/", StringComparison.Ordinal))
outs.Add(new($"Codeberg ({trimmedUrl.Substring(21)})", $"{url}/commit/"));
outs.Add(new($"Codeberg ({trimmedUrl.Slice(21)})", $"{url}/commit/"));
else if (url.StartsWith("https://gitea.org/", StringComparison.Ordinal))
outs.Add(new($"Gitea ({trimmedUrl.Substring(18)})", $"{url}/commit/"));
outs.Add(new($"Gitea ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
else if (url.StartsWith("https://git.sr.ht/", StringComparison.Ordinal))
outs.Add(new($"sourcehut ({trimmedUrl.Substring(18)})", $"{url}/commit/"));
outs.Add(new($"sourcehut ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Text;
@ -38,6 +38,18 @@ namespace SourceGit.Models
set;
} = false;
public BranchSortMode LocalBranchSortMode
{
get;
set;
} = BranchSortMode.Name;
public BranchSortMode RemoteBranchSortMode
{
get;
set;
} = BranchSortMode.Name;
public TagSortMode TagSortMode
{
get;
@ -110,6 +122,12 @@ namespace SourceGit.Models
set;
} = true;
public bool UpdateSubmodulesOnCheckoutBranch
{
get;
set;
} = true;
public AvaloniaList<Filter> HistoriesFilters
{
get;
@ -326,28 +344,28 @@ namespace SourceGit.Models
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.Substring(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.LocalBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--branches={filter.Pattern.Substring(11)}/*");
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.Substring(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.RemoteBranch)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.Substring(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
}
else if (filter.Type == FilterType.RemoteBranchFolder)
{
if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--remotes={filter.Pattern.Substring(13)}/*");
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.Substring(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
}
else if (filter.Type == FilterType.Tag)
{

View file

@ -42,7 +42,8 @@ namespace SourceGit.Models
new ShellOrTerminal("mac-terminal", "Terminal", ""),
new ShellOrTerminal("iterm2", "iTerm", ""),
new ShellOrTerminal("warp", "Warp", ""),
new ShellOrTerminal("ghostty", "Ghostty", "")
new ShellOrTerminal("ghostty", "Ghostty", ""),
new ShellOrTerminal("kitty", "kitty", "")
};
}
else
@ -58,6 +59,7 @@ namespace SourceGit.Models
new ShellOrTerminal("foot", "Foot", "foot"),
new ShellOrTerminal("wezterm", "WezTerm", "wezterm"),
new ShellOrTerminal("ptyxis", "Ptyxis", "ptyxis"),
new ShellOrTerminal("kitty", "kitty", "kitty"),
new ShellOrTerminal("custom", "Custom", ""),
};
}

View file

@ -59,6 +59,8 @@ namespace SourceGit.Native
return "Warp";
case "ghostty":
return "Ghostty";
case "kitty":
return "kitty";
}
return string.Empty;

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

View file

@ -40,6 +40,13 @@
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.Bisect">Bisect</x:String>
<x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String>
<x:String x:Key="Text.Bisect.Bad">Schlecht</x:String>
<x:String x:Key="Text.Bisect.Detecting">Bisecting. Ist der aktuelle HEAD gut oder fehlerhaft?</x:String>
<x:String x:Key="Text.Bisect.Good">Gut</x:String>
<x:String x:Key="Text.Bisect.Skip">Überspringen</x:String>
<x:String x:Key="Text.Bisect.WaitingForRange">Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken.</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Auschecken von ${0}$...</x:String>
@ -62,6 +69,7 @@
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Benenne ${0}$ um...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Setze verfolgten Branch...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Ungültiger upstream!</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
<x:String x:Key="Text.Cancel" xml:space="preserve">ABBRECHEN</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Auf Vorgänger-Revision zurücksetzen</x:String>
@ -78,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Alle Submodule updaten</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Quelle an Commit-Nachricht anhängen</x:String>
@ -102,8 +111,11 @@
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Mehrere cherry-picken</x:String>
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
<x:String x:Key="Text.CommitCM.CopyAuthor" xml:space="preserve">Author</x:String>
<x:String x:Key="Text.CommitCM.CopyCommitter" xml:space="preserve">Committer</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Information</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitCM.CopySubject" xml:space="preserve">Betreff</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Benutzerdefinierte Aktion</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactives Rebase von ${0}$ auf diesen Commit</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge in ${0}$ hinein</x:String>
@ -135,6 +147,7 @@
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Im Browser öffnen</x:String>
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Details</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">Betreff</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Einstellungen</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
@ -149,13 +162,16 @@
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branch</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Auf Beenden der Aktion warten</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(n)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Standard Remote</x:String>
<x:String x:Key="Text.Configure.Git.PreferredMergeMode" xml:space="preserve">Bevorzugter Merge Modus</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleAzure" xml:space="preserve">Beispiel Azure DevOps Rule hinzufügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteeIssue" xml:space="preserve">Beispiel für Gitee Issue Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteePullRequest" xml:space="preserve">Beispiel für Gitee Pull Request Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String>
@ -178,6 +194,10 @@
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Farbe</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Zuletzt geöffnete Tabs beim Starten wiederherstellen</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">WEITER</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty)?</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">ALLES STAGEN &amp; COMMITTEN</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty) oder alle Änderungen stagen und dann committen?</x:String>
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Konventionelle Commit-Hilfe</x:String>
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Breaking Change:</x:String>
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Geschlossenes Ticket:</x:String>
@ -187,6 +207,7 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Typ der Änderung:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Kopiere gesamten Text</x:String>
<x:String x:Key="Text.CopyFullPath" xml:space="preserve">Ganzen Pfad kopieren</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Pfad kopieren</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Branch erstellen...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basierend auf:</x:String>
@ -236,7 +257,9 @@
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ALT</x:String>
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Dateimodus geändert</x:String>
<x:String x:Key="Text.Diff.First" xml:space="preserve">Erste Differenz</x:String>
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignoriere Leerzeichenänderungen</x:String>
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Letzte Differenz</x:String>
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJEKT ÄNDERUNG</x:String>
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Nächste Änderung</x:String>
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">KEINE ÄNDERUNG ODER NUR ZEILEN-ENDE ÄNDERUNGEN</x:String>
@ -447,8 +470,10 @@
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modell</x:String>
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Streaming aktivieren</x:String>
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">DARSTELLUNG</x:String>
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Standardschriftart</x:String>
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Editor Tab Breite</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Schriftgröße</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Standard</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Texteditor</x:String>
@ -469,6 +494,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Zeige Nachfolger in den Commit Details</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Zeige Tags im Commit Graph</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Längenvorgabe für Commit-Nachrichten</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Aktiviere Auto-CRLF</x:String>
@ -476,6 +502,7 @@
<x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Globale Git Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.EnablePruneOnFetch" xml:space="preserve">Aktivere --prune beim fetchen</x:String>
<x:String x:Key="Text.Preferences.Git.IgnoreCRAtEOLInDiff" xml:space="preserve">Aktiviere --ignore-cr-at-eol beim Unterschied</x:String>
<x:String x:Key="Text.Preferences.Git.Invalid" xml:space="preserve">Diese App setzt Git (&gt;= 2.23.0) voraus</x:String>
<x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Installationspfad</x:String>
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Aktiviere HTTP SSL Verifizierung</x:String>
@ -549,6 +576,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABBRECHEN</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Änderungen automatisch von Remote fetchen...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Sortieren</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">Nach Commit Datum</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">Nach Name</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Filter aufheben</x:String>
@ -583,6 +613,7 @@
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Commit suchen</x:String>
<x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Autor</x:String>
<x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String>
<x:String x:Key="Text.Repository.Search.ByContent" xml:space="preserve">Inhalt</x:String>
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Dateiname</x:String>
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
@ -601,6 +632,8 @@
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Logs ansehen</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Öffne '{0}' im Browser</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">WORKTREE HINZUFÜGEN</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
@ -651,6 +684,7 @@
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Lokale Änderungen stashen</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Anwenden</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Entfernen</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Als Path speichern...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Stash entfernen</x:String>
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Entfernen:</x:String>
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
@ -685,6 +719,10 @@
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Submodul:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Verwende `--remote` Option</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Logs</x:String>
<x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">ALLES LÖSCHEN</x:String>
<x:String x:Key="Text.ViewLogs.CopyLog" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.ViewLogs.Delete" xml:space="preserve">Löschen</x:String>
<x:String x:Key="Text.Warn" xml:space="preserve">Warnung</x:String>
<x:String x:Key="Text.Welcome" xml:space="preserve">Willkommensseite</x:String>
<x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Erstelle Gruppe</x:String>
@ -714,8 +752,13 @@
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Klick-Ereignis auslösen</x:String>
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Bearbeitung)</x:String>
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Alle Änderungen stagen und committen</x:String>
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">Du hast {0} Datei(en) gestaged, aber nur {1} werden angezeigt ({2} sind herausgefiltert). Willst du trotzdem fortfahren?</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">KONFLIKTE ERKANNT</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeTool" xml:space="preserve">EXTERNES MERGE-TOOL ÖFFNEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts" xml:space="preserve">ALLE KONFLIKTE IN EXTERNEM MERGE-TOOL ÖFFNEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">DATEI KONFLIKTE GELÖST</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.UseMine" xml:space="preserve">MEINE VERSION VERWENDEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.UseTheirs" xml:space="preserve">DEREN VERSION VERWENDEN</x:String>
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String>

View file

@ -82,6 +82,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String>
@ -322,6 +323,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">Push to remote(s) after performing finish</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">Squash during merge</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String>
@ -571,6 +574,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching changes from remotes...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Sort</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">By Committer Date</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">By Name</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
@ -601,7 +607,7 @@
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">Add Remote</x:String>
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String>
<x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Author</x:String>
<x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String>
@ -614,10 +620,10 @@
<x:String x:Key="Text.Repository.Skip" xml:space="preserve">SKIP</x:String>
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistics</x:String>
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">ADD SUBMODULE</x:String>
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String>
<x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">Add Submodule</x:String>
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">Update Submodule</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">By Name (Ascending)</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">By Name (Descending)</x:String>
@ -625,9 +631,10 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">View Logs</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Visit '{0}' in Browser</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">Add Worktree</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String>
<x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String>
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Cambios Locales:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Actualizar todos los submódulos</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Añadir fuente al mensaje de commit</x:String>
@ -101,7 +102,7 @@
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nombre Local:</x:String>
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nombre del repositorio. Opcional.</x:String>
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Carpeta Padre:</x:String>
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Inicializar y actualizar submodulos</x:String>
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Inicializar y actualizar submódulos</x:String>
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL del Repositorio:</x:String>
<x:String x:Key="Text.Close" xml:space="preserve">CERRAR</x:String>
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finalizar Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finalizar Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Destino:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">Push al/los remoto(s) después de Finalizar</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">Squash durante el merge</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Prefijo de Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Inicializar Git-Flow</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORTAR</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching cambios desde remotos...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Ordenar</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">Por Fecha de Committer</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">Por Nombre</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Limpiar (GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Ejecutar comando `git gc` para este repositorio.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Limpiar todo</x:String>
@ -629,6 +635,7 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usar tiempo relativo en las historias</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Ver Logs</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Visitar '{0}' en el Navegador</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">AÑADIR WORKTREE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Локальные изменения:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Отклонить</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Отложить и примненить повторно</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Обновить все подкаталоги</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve"> Частичный выбор</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Добавить источник для ревизии сообщения</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">ПРОЦЕСС - Закончить исправление</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">ПРОЦЕСС - Завершить выпуск</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Цель:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">Выложить на удалённый(ые) после завершения</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">Втиснуть при слиянии</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Исправление:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Префикс исправлений:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Создать Git-процесс</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних репозиторий...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Сортировать</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">По дате ревизора (исполнителя)</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">По имени</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
@ -628,7 +634,8 @@
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Просмотр логов</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Просмотр журналов</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Посетить '{0}' в браузере</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">РАБОЧИЕ КАТАЛОГИ</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ДОБАВИТЬ РАБОЧИЙ КАТАЛОГ</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">ОБРЕЗАТЬ</x:String>
@ -714,7 +721,7 @@
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Подмодуль:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Использовать опцию (--remote)</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">Сетевой адрес:</x:String>
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Логи</x:String>
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Журналы</x:String>
<x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">ОЧИСТИТЬ ВСЁ</x:String>
<x:String x:Key="Text.ViewLogs.CopyLog" xml:space="preserve">Копировать</x:String>
<x:String x:Key="Text.ViewLogs.Delete" xml:space="preserve">Удалить</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交更改 </x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">丢弃更改</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">结束修复分支</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">结束版本分支</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">完成后自动推送</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">压缩变更为单一提交后合并分支</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修复分支 </x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修复分支名前缀 </x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化GIT工作流</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自动拉取远端变更中...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">排序方式</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">按提交时间</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">按名称</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`git gc`命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
@ -629,6 +635,7 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">查看命令日志</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">访问远程仓库 '{0}'</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作树列表</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作树</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交變更:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">捨棄變更</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">完成修復分支</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">完成發行分支</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">完成後自動推送</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">壓縮為單一提交後合併</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修復分支:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修復分支前置詞:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化 Git 工作流</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">中止</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自動提取遠端變更中...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">依建立時間</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">依名稱升序</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本存放庫 (GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行 `git gc` 命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
@ -629,6 +635,7 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">檢視 Git 指令記錄</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">檢視遠端存放庫 '{0}'</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作區列表</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作區</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String>

View file

@ -25,7 +25,7 @@
<Color x:Key="Color.Diff.AddedHighlight">#A7E1A7</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#F19B9D</Color>
<Color x:Key="Color.Link">#0000EE</Color>
<Color x:Key="Color.InlineCode">#FFE5E5E5</Color>
<Color x:Key="Color.InlineCode">#FFE4E4E4</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
@ -52,7 +52,7 @@
<Color x:Key="Color.Diff.AddedHighlight">#A0308D3C</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#A09F4247</Color>
<Color x:Key="Color.Link">#4DAAFC</Color>
<Color x:Key="Color.InlineCode">#FF2E2E2E</Color>
<Color x:Key="Color.InlineCode">#FF383838</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

View file

@ -10,6 +10,7 @@ namespace SourceGit.ViewModels
public string Name { get; private set; } = string.Empty;
public string Path { get; private set; } = string.Empty;
public object Backend { get; private set; } = null;
public ulong TimeToSort { get; private set; } = 0;
public int Depth { get; set; } = 0;
public bool IsSelected { get; set; } = false;
public List<BranchTreeNode> Children { get; private set; } = new List<BranchTreeNode>();
@ -62,6 +63,12 @@ namespace SourceGit.ViewModels
public List<BranchTreeNode> Remotes => _remotes;
public List<string> InvalidExpandedNodes => _invalidExpandedNodes;
public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode)
{
_localSortMode = localSortMode;
_remoteSortMode = remoteSortMode;
}
public void SetExpandedNodes(List<string> expanded)
{
foreach (var node in expanded)
@ -72,6 +79,7 @@ namespace SourceGit.ViewModels
{
var folders = new Dictionary<string, BranchTreeNode>();
var fakeRemoteTime = (ulong)remotes.Count;
foreach (var remote in remotes)
{
var path = $"refs/remotes/{remote.Name}";
@ -81,8 +89,10 @@ namespace SourceGit.ViewModels
Path = path,
Backend = remote,
IsExpanded = bForceExpanded || _expanded.Contains(path),
TimeToSort = fakeRemoteTime,
};
fakeRemoteTime--;
folders.Add(path, node);
_remotes.Add(node);
}
@ -108,12 +118,21 @@ namespace SourceGit.ViewModels
}
folders.Clear();
SortNodes(_locals);
SortNodes(_remotes);
if (_localSortMode == Models.BranchSortMode.Name)
SortNodesByName(_locals);
else
SortNodesByTime(_locals);
if (_remoteSortMode == Models.BranchSortMode.Name)
SortNodesByName(_remotes);
else
SortNodesByTime(_remotes);
}
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded)
{
var time = branch.CommitterDate;
var fullpath = $"{prefix}/{branch.Name}";
var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal);
if (sepIdx == -1 || branch.IsDetachedHead)
@ -124,6 +143,7 @@ namespace SourceGit.ViewModels
Path = fullpath,
Backend = branch,
IsExpanded = false,
TimeToSort = time,
});
return;
}
@ -138,6 +158,7 @@ namespace SourceGit.ViewModels
if (folders.TryGetValue(folder, out var val))
{
lastFolder = val;
lastFolder.TimeToSort = Math.Max(lastFolder.TimeToSort, time);
if (!lastFolder.IsExpanded)
lastFolder.IsExpanded |= (branch.IsCurrent || _expanded.Contains(folder));
}
@ -148,6 +169,7 @@ namespace SourceGit.ViewModels
Name = name,
Path = folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
TimeToSort = time,
};
roots.Add(lastFolder);
folders.Add(folder, lastFolder);
@ -159,6 +181,7 @@ namespace SourceGit.ViewModels
Name = name,
Path = folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
TimeToSort = time,
};
lastFolder.Children.Add(cur);
folders.Add(folder, cur);
@ -175,10 +198,11 @@ namespace SourceGit.ViewModels
Path = fullpath,
Backend = branch,
IsExpanded = false,
TimeToSort = time,
});
}
private void SortNodes(List<BranchTreeNode> nodes)
private void SortNodesByName(List<BranchTreeNode> nodes)
{
nodes.Sort((l, r) =>
{
@ -192,9 +216,39 @@ namespace SourceGit.ViewModels
});
foreach (var node in nodes)
SortNodes(node.Children);
SortNodesByName(node.Children);
}
private void SortNodesByTime(List<BranchTreeNode> nodes)
{
nodes.Sort((l, r) =>
{
if (l.Backend is Models.Branch { IsDetachedHead: true })
return -1;
if (l.Backend is Models.Branch)
{
if (r.Backend is Models.Branch)
return r.TimeToSort == l.TimeToSort ? Models.NumericSort.Compare(l.Name, r.Name) : r.TimeToSort.CompareTo(l.TimeToSort);
else
return 1;
}
if (r.Backend is Models.Branch)
return -1;
if (r.TimeToSort == l.TimeToSort)
return Models.NumericSort.Compare(l.Name, r.Name);
return r.TimeToSort.CompareTo(l.TimeToSort);
});
foreach (var node in nodes)
SortNodesByTime(node.Children);
}
private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name;
private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name;
private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>();
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
private readonly List<string> _invalidExpandedNodes = new List<string>();

View file

@ -15,11 +15,24 @@ namespace SourceGit.ViewModels
set;
}
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public Checkout(Repository repo, string branch)
{
_repo = repo;
Branch = branch;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public override Task<bool> Sure()
@ -30,19 +43,22 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Checkout '{Branch}'");
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var succ = false;
var needPopStash = false;
if (changes > 0)
{
if (DiscardLocalChanges)
{
Commands.Discard.All(_repo.FullPath, false, log);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, true);
}
else
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
@ -52,11 +68,22 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, false);
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch);
if (needPopStash)
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete();
@ -73,7 +100,7 @@ namespace SourceGit.ViewModels
});
Task.Delay(400).Wait();
return rs;
return succ;
});
}

View file

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

View file

@ -101,7 +101,6 @@ namespace SourceGit.ViewModels
{
ProgressDescription = "Clone ...";
// Create a temp log.
var log = new CommandLog("Clone");
Use(log);
@ -139,12 +138,11 @@ namespace SourceGit.ViewModels
config.Set("remote.origin.sshkey", _sshKey);
}
// individually update submodule (if any)
if (InitAndUpdateSubmodules)
{
var submoduleList = new Commands.QuerySubmodules(path).Result();
foreach (var submodule in submoduleList)
new Commands.Submodule(path).Use(log).Update(submodule.Path, true, true, false);
var submodules = new Commands.QuerySubmodules(path).Result();
if (submodules.Count > 0)
new Commands.Submodule(path).Use(log).Update(submodules, true, true, false);
}
log.Complete();

View file

@ -291,7 +291,7 @@ namespace SourceGit.ViewModels
ev.Handled = true;
};
var fullPath = Path.Combine(_repo.FullPath, change.Path);
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
var explore = new MenuItem();
explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
@ -362,11 +362,9 @@ namespace SourceGit.ViewModels
var resetToThisRevision = new MenuItem();
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += (_, ev) =>
resetToThisRevision.Click += async (_, ev) =>
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}");
log.Complete();
await ResetToThisRevision(change.Path);
ev.Handled = true;
};
@ -374,14 +372,9 @@ namespace SourceGit.ViewModels
resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision");
resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += (_, ev) =>
resetToFirstParent.Click += async (_, ev) =>
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
log.Complete();
await ResetToParentRevision(change);
ev.Handled = true;
};
@ -389,8 +382,7 @@ namespace SourceGit.ViewModels
menu.Items.Add(resetToFirstParent);
menu.Items.Add(new MenuItem { Header = "-" });
if (File.Exists(Path.Combine(fullPath)))
TryToAddContextMenuItemsForGitLFS(menu, change.Path);
TryToAddContextMenuItemsForGitLFS(menu, fullPath, change.Path);
}
var copyPath = new MenuItem();
@ -407,7 +399,7 @@ namespace SourceGit.ViewModels
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyFullPath.Click += (_, e) =>
{
App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path));
App.CopyText(fullPath);
e.Handled = true;
};
@ -419,7 +411,7 @@ namespace SourceGit.ViewModels
public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
{
var menu = new ContextMenu();
var fullPath = Path.Combine(_repo.FullPath, file.Path);
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file.Path);
var explore = new MenuItem();
explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
@ -499,29 +491,25 @@ namespace SourceGit.ViewModels
menu.Items.Add(blame);
menu.Items.Add(new MenuItem() { Header = "-" });
if (!_repo.IsBare)
{
var resetToThisRevision = new MenuItem();
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.IsEnabled = File.Exists(fullPath);
resetToThisRevision.Click += (_, ev) =>
resetToThisRevision.Click += async (_, ev) =>
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(file.Path, $"{_commit.SHA}");
log.Complete();
await ResetToThisRevision(file.Path);
ev.Handled = true;
};
var change = _changes.Find(x => x.Path == file.Path) ?? new Models.Change() { Index = Models.ChangeState.None, Path = file.Path };
var resetToFirstParent = new MenuItem();
resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision");
resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout");
var fileInChanges = _changes.Find(x => x.Path == file.Path);
var fileIndex = fileInChanges?.Index;
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0 && fileIndex != Models.ChangeState.Renamed;
resetToFirstParent.Click += (_, ev) =>
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += async (_, ev) =>
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(file.Path, $"{_commit.SHA}~1");
log.Complete();
await ResetToParentRevision(change);
ev.Handled = true;
};
@ -529,8 +517,8 @@ namespace SourceGit.ViewModels
menu.Items.Add(resetToFirstParent);
menu.Items.Add(new MenuItem() { Header = "-" });
if (File.Exists(Path.Combine(fullPath)))
TryToAddContextMenuItemsForGitLFS(menu, file.Path);
TryToAddContextMenuItemsForGitLFS(menu, fullPath, file.Path);
}
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
@ -546,7 +534,7 @@ namespace SourceGit.ViewModels
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyFullPath.Click += (_, e) =>
{
App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, file.Path));
App.CopyText(fullPath);
e.Handled = true;
};
@ -725,8 +713,11 @@ namespace SourceGit.ViewModels
}
}
private void TryToAddContextMenuItemsForGitLFS(ContextMenu menu, string path)
private void TryToAddContextMenuItemsForGitLFS(ContextMenu menu, string fullPath, string path)
{
if (_repo.Remotes.Count == 0 || !File.Exists(fullPath))
return;
var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled();
if (!lfsEnabled)
return;
@ -738,7 +729,6 @@ namespace SourceGit.ViewModels
var lfsLock = new MenuItem();
lfsLock.Header = App.Text("GitLFS.Locks.Lock");
lfsLock.Icon = App.CreateMenuIcon("Icons.Lock");
lfsLock.IsEnabled = _repo.Remotes.Count > 0;
if (_repo.Remotes.Count == 1)
{
lfsLock.Click += async (_, e) =>
@ -777,7 +767,6 @@ namespace SourceGit.ViewModels
var lfsUnlock = new MenuItem();
lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock");
lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock");
lfsUnlock.IsEnabled = _repo.Remotes.Count > 0;
if (_repo.Remotes.Count == 1)
{
lfsUnlock.Click += async (_, e) =>
@ -867,6 +856,31 @@ namespace SourceGit.ViewModels
RevisionFileSearchSuggestion = suggestion;
}
private Task ResetToThisRevision(string path)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
return Task.Run(() =>
{
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(path, $"{_commit.SHA}");
log.Complete();
});
}
private Task ResetToParentRevision(Models.Change change)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
return Task.Run(() =>
{
if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
log.Complete();
});
}
[GeneratedRegex(@"\b(https?://|ftp://)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]")]
private static partial Regex REG_URL_FORMAT();

View file

@ -28,7 +28,14 @@ namespace SourceGit.ViewModels
public bool CheckoutAfterCreated
{
get => _repo.Settings.CheckoutBranchOnCreateBranch;
set => _repo.Settings.CheckoutBranchOnCreateBranch = value;
set
{
if (_repo.Settings.CheckoutBranchOnCreateBranch != value)
{
_repo.Settings.CheckoutBranchOnCreateBranch = value;
OnPropertyChanged();
}
}
}
public bool IsBareRepository
@ -36,6 +43,18 @@ namespace SourceGit.ViewModels
get => _repo.IsBare;
}
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public CreateBranch(Repository repo, Models.Branch branch)
{
_repo = repo;
@ -48,6 +67,7 @@ namespace SourceGit.ViewModels
BasedOn = branch;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public CreateBranch(Repository repo, Models.Commit commit)
@ -57,6 +77,7 @@ namespace SourceGit.ViewModels
BasedOn = commit;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public CreateBranch(Repository repo, Models.Tag tag)
@ -66,6 +87,7 @@ namespace SourceGit.ViewModels
BasedOn = tag;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
@ -92,20 +114,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Create Branch '{fixedName}'");
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
bool succ;
bool succ = false;
if (CheckoutAfterCreated && !_repo.IsBare)
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false;
if (changes > 0)
{
if (DiscardLocalChanges)
{
Commands.Discard.All(_repo.FullPath, false, log);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
if (!succ)
@ -117,12 +140,23 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false);
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision);
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
}
else
{
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, log);
@ -144,6 +178,8 @@ namespace SourceGit.ViewModels
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
ProgressDescription = "Waiting for branch updated...";
}
_repo.MarkBranchesDirtyManually();
@ -151,10 +187,7 @@ namespace SourceGit.ViewModels
});
if (CheckoutAfterCreated)
{
CallUIThread(() => ProgressDescription = "Waiting for branch updated...");
Task.Delay(400).Wait();
}
return true;
});

View file

@ -13,6 +13,18 @@ namespace SourceGit.ViewModels
public bool IsRelease => _type == "release";
public bool IsHotfix => _type == "hotfix";
public bool Squash
{
get;
set;
} = false;
public bool AutoPush
{
get;
set;
} = false;
public bool KeepBranch
{
get;
@ -39,7 +51,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, KeepBranch, log);
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, Squash, AutoPush, KeepBranch, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;

View file

@ -100,23 +100,32 @@ namespace SourceGit.ViewModels
public async void ProcessPopup()
{
if (_popup is { InProgress: false })
if (_popup is { InProgress: false } dump)
{
if (!_popup.Check())
if (!dump.Check())
return;
_popup.InProgress = true;
var task = _popup.Sure();
dump.InProgress = true;
var task = dump.Sure();
var finished = false;
if (task != null)
{
var finished = await task;
_popup.InProgress = false;
try
{
finished = await task;
}
catch (Exception e)
{
App.LogException(e);
}
dump.InProgress = false;
if (finished)
Popup = null;
}
else
{
_popup.InProgress = false;
dump.InProgress = false;
Popup = null;
}
}

View file

@ -583,30 +583,42 @@ namespace SourceGit.ViewModels
Task.Run(RefreshStashes);
}
public void OpenInFileManager()
{
Native.OS.OpenInFileManager(_fullpath);
}
public void OpenInTerminal()
{
Native.OS.OpenTerminal(_fullpath);
}
public ContextMenu CreateContextMenuForExternalTools()
{
var tools = Native.OS.ExternalTools;
if (tools.Count == 0)
{
App.RaiseException(_fullpath, "No available external editors found!");
return null;
}
var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality);
foreach (var tool in tools)
RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality);
RenderOptions.SetEdgeMode(menu, EdgeMode.Antialias);
RenderOptions.SetTextRenderingMode(menu, TextRenderingMode.Antialias);
var explore = new MenuItem();
explore.Header = App.Text("Repository.Explore");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
explore.Click += (_, e) =>
{
Native.OS.OpenInFileManager(_fullpath);
e.Handled = true;
};
var terminal = new MenuItem();
terminal.Header = App.Text("Repository.Terminal");
terminal.Icon = App.CreateMenuIcon("Icons.Terminal");
terminal.Click += (_, e) =>
{
Native.OS.OpenTerminal(_fullpath);
e.Handled = true;
};
menu.Items.Add(explore);
menu.Items.Add(terminal);
var tools = Native.OS.ExternalTools;
if (tools.Count > 0)
{
menu.Items.Add(new MenuItem() { Header = "-" });
foreach (var tool in Native.OS.ExternalTools)
{
var dupTool = tool;
@ -621,6 +633,36 @@ namespace SourceGit.ViewModels
menu.Items.Add(item);
}
}
var urls = new Dictionary<string, string>();
foreach (var r in _remotes)
{
if (r.TryGetVisitURL(out var visit))
urls.Add(r.Name, visit);
}
if (urls.Count > 0)
{
menu.Items.Add(new MenuItem() { Header = "-" });
foreach (var url in urls)
{
var name = url.Key;
var addr = url.Value;
var item = new MenuItem();
item.Header = App.Text("Repository.Visit", name);
item.Icon = App.CreateMenuIcon("Icons.Remotes");
item.Click += (_, e) =>
{
Native.OS.OpenBrowser(addr);
e.Handled = true;
};
menu.Items.Add(item);
}
}
return menu;
}
@ -1154,7 +1196,7 @@ namespace SourceGit.ViewModels
if (branch.IsLocal)
{
if (_localChangesCount > 0)
if (_localChangesCount > 0 || _submodules.Count > 0)
ShowPopup(new Checkout(this, branch.Name));
else
ShowAndStartPopup(new Checkout(this, branch.Name));
@ -2187,6 +2229,51 @@ namespace SourceGit.ViewModels
return menu;
}
public ContextMenu CreateContextMenuForBranchSortMode(bool local)
{
var mode = local ? _settings.LocalBranchSortMode : _settings.RemoteBranchSortMode;
var changeMode = new Action<Models.BranchSortMode>(m =>
{
if (local)
_settings.LocalBranchSortMode = m;
else
_settings.RemoteBranchSortMode = m;
var builder = BuildBranchTree(_branches, _remotes);
LocalBranchTrees = builder.Locals;
RemoteBranchTrees = builder.Remotes;
});
var byNameAsc = new MenuItem();
byNameAsc.Header = App.Text("Repository.BranchSort.ByName");
if (mode == Models.BranchSortMode.Name)
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check");
byNameAsc.Click += (_, ev) =>
{
if (mode != Models.BranchSortMode.Name)
changeMode(Models.BranchSortMode.Name);
ev.Handled = true;
};
var byCommitterDate = new MenuItem();
byCommitterDate.Header = App.Text("Repository.BranchSort.ByCommitterDate");
if (mode == Models.BranchSortMode.CommitterDate)
byCommitterDate.Icon = App.CreateMenuIcon("Icons.Check");
byCommitterDate.Click += (_, ev) =>
{
if (mode != Models.BranchSortMode.CommitterDate)
changeMode(Models.BranchSortMode.CommitterDate);
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(byNameAsc);
menu.Items.Add(byCommitterDate);
return menu;
}
public ContextMenu CreateContextMenuForTagSortMode()
{
var mode = _settings.TagSortMode;
@ -2356,7 +2443,7 @@ namespace SourceGit.ViewModels
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
{
var builder = new BranchTreeNode.Builder();
var builder = new BranchTreeNode.Builder(_settings.LocalBranchSortMode, _settings.RemoteBranchSortMode);
if (string.IsNullOrEmpty(_filter))
{
builder.SetExpandedNodes(_settings.ExpandedBranchNodesInSideBar);

View file

@ -46,7 +46,7 @@
<!-- Compare Targets -->
<Border Grid.Row="1">
<Grid Margin="48,8,48,8" ColumnDefinitions="*,48,*">
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Diff.DeletedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
<v:Avatar Width="16" Height="16"
@ -67,10 +67,10 @@
<!-- Swap Button -->
<Button Grid.Column="1" Classes="icon_button" Command="{Binding Swap}" HorizontalAlignment="Center" ToolTip.Tip="{DynamicResource Text.Diff.SwapCommits}">
<Path Width="16" Height="16" Fill="{DynamicResource Brush.FG2}" Data="{DynamicResource Icons.Compare}"/>
<Path Width="16" Height="16" Data="{DynamicResource Icons.Compare}"/>
</Button>
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Diff.AddedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
<v:Avatar Width="16" Height="16"

View file

@ -17,6 +17,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
@ -35,11 +36,18 @@
<WrapPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton GroupName="LocalChanges"
Margin="0,0,8,0"
Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
Content="{DynamicResource Text.Checkout.LocalChanges.StashAndReply}"
IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/>
<RadioButton GroupName="LocalChanges"
Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"/>
Content="{DynamicResource Text.Checkout.LocalChanges.Discard}"/>
</WrapPanel>
<CheckBox Grid.Row="2" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsRecurseSubmoduleVisible}"
ToolTip.Tip="--recurse-submodules"/>
</Grid>
</StackPanel>
</UserControl>

View file

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

View file

@ -189,7 +189,7 @@
<Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" MinHeight="24" IsVisible="{Binding HasDecorators}">
<v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11"
FontSize="12"
AllowWrap="True"
Margin="0,4,0,0"
UseGraphColor="False"/>

View file

@ -55,23 +55,29 @@ namespace SourceGit.Views
if (list == null)
return;
// Calculate drawing area.
double width = Bounds.Width - 273 - histories.AuthorNameColumnWidth.Value;
double height = Bounds.Height;
double startY = list.Scroll?.Offset.Y ?? 0;
double endY = startY + height + 28;
var container = list.ItemsPanelRoot as VirtualizingStackPanel;
if (container == null)
return;
var item = list.ContainerFromIndex(container.FirstRealizedIndex);
if (item == null)
return;
var width = histories.CommitListHeader.ColumnDefinitions[0].ActualWidth;
var height = Bounds.Height;
var rowHeight = item.Bounds.Height;
var startY = container.FirstRealizedIndex * rowHeight - item.TranslatePoint(new Point(0, 0), list).Value!.Y;
var endY = startY + height + 28;
// Apply scroll offset and clip.
using (context.PushClip(new Rect(0, 0, width, height)))
using (context.PushTransform(Matrix.CreateTranslation(0, -startY)))
{
// Draw contents
DrawCurves(context, graph, startY, endY);
DrawAnchors(context, graph, startY, endY);
DrawCurves(context, graph, startY, endY, rowHeight);
DrawAnchors(context, graph, startY, endY, rowHeight);
}
}
private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight)
{
var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness);
var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch;
@ -82,16 +88,20 @@ namespace SourceGit.Views
{
if (link.IsMerged)
continue;
if (link.End.Y < top)
var startY = link.Start.Y * rowHeight;
var endY = link.End.Y * rowHeight;
if (endY < top)
continue;
if (link.Start.Y > bottom)
if (startY > bottom)
break;
var geo = new StreamGeometry();
using (var ctx = geo.Open())
{
ctx.BeginFigure(link.Start, false);
ctx.QuadraticBezierTo(link.Control, link.End);
ctx.BeginFigure(new Point(link.Start.X, startY), false);
ctx.QuadraticBezierTo(new Point(link.Control.X, link.Control.Y * rowHeight), new Point(link.End.X, endY));
}
context.DrawGeometry(null, grayedPen, geo);
@ -100,10 +110,11 @@ namespace SourceGit.Views
foreach (var line in graph.Paths)
{
var last = line.Points[0];
var last = new Point(line.Points[0].X, line.Points[0].Y * rowHeight);
var size = line.Points.Count;
var endY = line.Points[size - 1].Y * rowHeight;
if (line.Points[size - 1].Y < top)
if (endY < top)
continue;
if (last.Y > bottom)
break;
@ -117,7 +128,7 @@ namespace SourceGit.Views
var ended = false;
for (int i = 1; i < size; i++)
{
var cur = line.Points[i];
var cur = new Point(line.Points[i].X, line.Points[i].Y * rowHeight);
if (cur.Y < top)
{
last = cur;
@ -173,23 +184,27 @@ namespace SourceGit.Views
{
if (onlyHighlightCurrentBranch && !link.IsMerged)
continue;
if (link.End.Y < top)
var startY = link.Start.Y * rowHeight;
var endY = link.End.Y * rowHeight;
if (endY < top)
continue;
if (link.Start.Y > bottom)
if (startY > bottom)
break;
var geo = new StreamGeometry();
using (var ctx = geo.Open())
{
ctx.BeginFigure(link.Start, false);
ctx.QuadraticBezierTo(link.Control, link.End);
ctx.BeginFigure(new Point(link.Start.X, startY), false);
ctx.QuadraticBezierTo(new Point(link.Control.X, link.Control.Y * rowHeight), new Point(link.End.X, endY));
}
context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo);
}
}
private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight)
{
var dotFill = DotBrush;
var dotFillPen = new Pen(dotFill, 2);
@ -198,9 +213,11 @@ namespace SourceGit.Views
foreach (var dot in graph.Dots)
{
if (dot.Center.Y < top)
var center = new Point(dot.Center.X, dot.Center.Y * rowHeight);
if (center.Y < top)
continue;
if (dot.Center.Y > bottom)
if (center.Y > bottom)
break;
var pen = Models.CommitGraph.Pens[dot.Color];
@ -210,16 +227,16 @@ namespace SourceGit.Views
switch (dot.Type)
{
case Models.CommitGraph.DotType.Head:
context.DrawEllipse(dotFill, pen, dot.Center, 6, 6);
context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3);
context.DrawEllipse(dotFill, pen, center, 6, 6);
context.DrawEllipse(pen.Brush, null, center, 3, 3);
break;
case Models.CommitGraph.DotType.Merge:
context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6);
context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3));
context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y));
context.DrawEllipse(pen.Brush, null, center, 6, 6);
context.DrawLine(dotFillPen, new Point(center.X, center.Y - 3), new Point(center.X, center.Y + 3));
context.DrawLine(dotFillPen, new Point(center.X - 3, center.Y), new Point(center.X + 3, center.Y));
break;
default:
context.DrawEllipse(dotFill, pen, dot.Center, 3, 3);
context.DrawEllipse(dotFill, pen, center, 3, 3);
break;
}
}

View file

@ -104,6 +104,14 @@ namespace SourceGit.Views
if (_inlines.Count == 0)
return;
var ro = new RenderOptions()
{
TextRenderingMode = TextRenderingMode.SubpixelAntialias,
EdgeMode = EdgeMode.Antialias
};
using (context.PushRenderOptions(ro))
{
var height = Bounds.Height;
var width = Bounds.Width;
foreach (var inline in _inlines)
@ -124,6 +132,7 @@ namespace SourceGit.Views
}
}
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
@ -299,7 +308,7 @@ namespace SourceGit.Views
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
codeTypeface,
fontSize,
fontSize - 0.5,
foreground);
_inlines.Add(new Inline(x, link, elem));
x += link.WidthIncludingTrailingWhitespace + 8;

View file

@ -52,7 +52,7 @@
<v:CommitRefsPresenter Margin="8,0,0,0"
Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11"
FontSize="12"
VerticalAlignment="Center"
UseGraphColor="False"/>
<TextBlock Margin="4,0,0,0"

View file

@ -14,7 +14,7 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.CreateBranch.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto,Auto" ColumnDefinitions="140,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -83,6 +83,19 @@
Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
ToolTip.Tip="--recurse-submodules">
<CheckBox.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsBareRepository" Converter="{x:Static BoolConverters.Not}"/>
<Binding Path="CheckoutAfterCreated"/>
<Binding Path="IsRecurseSubmoduleVisible"/>
</MultiBinding>
</CheckBox.IsVisible>
</CheckBox>
</Grid>
</StackPanel>
</UserControl>

View file

@ -19,7 +19,7 @@
Classes="bold"
Text="{DynamicResource Text.GitFlow.FinishHotfix}"
IsVisible="{Binding IsHotfix}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -30,8 +30,19 @@
</StackPanel>
<CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.FinishWithSquash}"
IsChecked="{Binding Squash, Mode=TwoWay}"
ToolTip.Tip="--squash"/>
<CheckBox Grid.Row="2" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.FinishWithPush}"
IsChecked="{Binding AutoPush, Mode=TwoWay}"
ToolTip.Tip="--push"/>
<CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.KeepBranchAfterFinish}"
IsChecked="{Binding KeepBranch, Mode=TwoWay}"/>
IsChecked="{Binding KeepBranch, Mode=TwoWay}"
ToolTip.Tip="-k"/>
</Grid>
</StackPanel>
</UserControl>

View file

@ -30,7 +30,7 @@
Background="{DynamicResource Brush.Window}"
BorderThickness="0,0,0,1"
BorderBrush="{DynamicResource Brush.Border0}">
<Grid>
<Grid x:Name="CommitListHeader">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3"/>
@ -76,7 +76,7 @@
<Style Selector="ListBoxItem">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Height" Value="28"/>
<Setter Property="Height" Value="26"/>
<Setter Property="Template">
<ControlTemplate>
<Grid>
@ -145,7 +145,7 @@
Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}"
ShowTags="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowTagsInGraph}"
FontSize="11"
FontSize="12"
VerticalAlignment="Center">
<v:CommitRefsPresenter.UseGraphColor>
<MultiBinding Converter="{x:Static BoolConverters.Or}">

View file

@ -202,9 +202,20 @@
<Grid Grid.Row="2" x:Name="LeftSidebarGroups" Margin="0,4,0,0" RowDefinitions="28,Auto,28,Auto,28,Auto,28,Auto,28,Auto" SizeChanged="OnLeftSidebarSizeChanged">
<!-- Local Branches -->
<ToggleButton Grid.Row="0" Classes="group_expander" IsChecked="{Binding IsLocalBranchGroupExpanded, Mode=TwoWay}">
<Grid ColumnDefinitions="16,*">
<Grid ColumnDefinitions="16,*,Auto,Auto">
<Path Grid.Column="0" Width="11" Height="11" HorizontalAlignment="Left" Data="{StaticResource Icons.Local}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.LocalBranches}"/>
<Button Grid.Column="2"
Classes="icon_button"
Width="14"
Margin="8,0,0,0"
Click="OnOpenSortLocalBranchMenu"
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
</Button>
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding CreateNewBranch}" ToolTip.Tip="{DynamicResource Text.Repository.NewBranch}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch.Add}"/>
</Button>
</Grid>
</ToggleButton>
<v:BranchTree Grid.Row="1"
@ -218,10 +229,18 @@
<!-- Remotes -->
<ToggleButton Grid.Row="2" Classes="group_expander" IsChecked="{Binding IsRemoteGroupExpanded, Mode=TwoWay}">
<Grid ColumnDefinitions="16,*,Auto">
<Grid ColumnDefinitions="16,*,Auto,Auto">
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Remotes}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.Remotes}"/>
<Button Grid.Column="2" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
<Button Grid.Column="2"
Classes="icon_button"
Width="14"
Margin="8,0,0,0"
Click="OnOpenSortRemoteBranchMenu"
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
</Button>
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
</Button>
</Grid>

View file

@ -403,6 +403,28 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnOpenSortLocalBranchMenu(object sender, RoutedEventArgs e)
{
if (sender is Button button && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForBranchSortMode(true);
menu?.Open(button);
}
e.Handled = true;
}
private void OnOpenSortRemoteBranchMenu(object sender, RoutedEventArgs e)
{
if (sender is Button button && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForBranchSortMode(false);
menu?.Open(button);
}
e.Handled = true;
}
private void OnOpenSortTagMenu(object sender, RoutedEventArgs e)
{
if (sender is Button button && DataContext is ViewModels.Repository repo)

View file

@ -9,16 +9,8 @@
x:DataType="vm:Repository">
<Grid ColumnDefinitions="*,Auto,*">
<StackPanel Grid.Column="0" Orientation="Horizontal" Margin="4,0,0,0">
<Button Classes="icon_button" Width="32" Command="{Binding OpenInFileManager}" ToolTip.Tip="{DynamicResource Text.Repository.Explore}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/>
</Button>
<Button Classes="icon_button" Width="32" Click="OpenWithExternalTools" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.Repository.OpenWithExternalTools}">
<Path Width="13" Height="13" Data="{StaticResource Icons.OpenWith}"/>
</Button>
<Button Classes="icon_button" Width="32" Command="{Binding OpenInTerminal}" ToolTip.Tip="{DynamicResource Text.Repository.Terminal}">
<Path Width="13" Height="13" Data="{StaticResource Icons.Terminal}"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/>
</Button>
<Button Classes="icon_button" Width="32" Click="OpenGitLogs" ToolTip.Tip="{DynamicResource Text.Repository.ViewLogs}">

View file

@ -28,16 +28,16 @@
<TextBlock Grid.Column="4" Classes="primary" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid>
<TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" VerticalAlignment="Bottom"/>
<TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" Margin="0,6,0,0"/>
</Grid>
</DataTemplate>
</UserControl.DataTemplates>
<Grid RowDefinitions="50,*" Margin="4">
<Grid RowDefinitions="Auto,*" Margin="4">
<!-- Compare Revision Info -->
<Grid Grid.Row="0" Margin="0,0,0,6" ColumnDefinitions="*,32,*,Auto">
<!-- Base Revision -->
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Diff.DeletedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding StartPoint}"/>
</Border>
@ -47,7 +47,7 @@
</Button>
<!-- Right Revision -->
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Diff.AddedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding EndPoint}"/>
</Border>

View file

@ -1502,7 +1502,7 @@ namespace SourceGit.Views
{
if (line.Content.Length > 10000)
{
builder.Append(line.Content.Substring(0, 1000));
builder.Append(line.Content.AsSpan(0, 1000));
builder.Append($"...({line.Content.Length - 1000} characters trimmed)");
}
else