Merge branch 'release/v2025.19'

This commit is contained in:
leo 2025-05-26 09:45:48 +08:00
commit 4887252870
No known key found for this signature in database
95 changed files with 1336 additions and 838 deletions

View file

@ -6,11 +6,18 @@ 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-98.23%25-yellow)
### ![de__DE](https://img.shields.io/badge/de__DE-96.75%25-yellow)
<details>
<summary>Missing keys in de_DE.axaml</summary>
- Text.BranchCM.ResetToSelectedCommit
- Text.CommitDetail.Changes.Count
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
@ -18,7 +25,12 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Pull.RecurseSubmodules
- Text.Repository.ShowSubmodulesAsTree
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@ -28,19 +40,16 @@ This document shows the translation status of each locale file in the repository
</details>
### ![es__ES](https://img.shields.io/badge/es__ES-99.49%25-yellow)
### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow)
<details>
<summary>Missing keys in es_ES.axaml</summary>
- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.Global.SwitchTab
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.CreateBranch.OverwriteExisting
</details>
### ![fr__FR](https://img.shields.io/badge/fr__FR-94.05%25-yellow)
### ![fr__FR](https://img.shields.io/badge/fr__FR-92.62%25-yellow)
<details>
<summary>Missing keys in fr_FR.axaml</summary>
@ -52,16 +61,23 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
@ -70,6 +86,7 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@ -77,6 +94,10 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@ -95,19 +116,31 @@ This document shows the translation status of each locale file in the repository
</details>
### ![it__IT](https://img.shields.io/badge/it__IT-99.49%25-yellow)
### ![it__IT](https://img.shields.io/badge/it__IT-98.00%25-yellow)
<details>
<summary>Missing keys in it_IT.axaml</summary>
- Text.BranchCM.ResetToSelectedCommit
- Text.CommitDetail.Changes.Count
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.Global.SwitchTab
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Pull.RecurseSubmodules
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
</details>
### ![ja__JP](https://img.shields.io/badge/ja__JP-93.80%25-yellow)
### ![ja__JP](https://img.shields.io/badge/ja__JP-92.37%25-yellow)
<details>
<summary>Missing keys in ja_JP.axaml</summary>
@ -119,16 +152,23 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
@ -137,6 +177,7 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@ -146,6 +187,10 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@ -164,7 +209,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![pt__BR](https://img.shields.io/badge/pt__BR-85.57%25-yellow)
### ![pt__BR](https://img.shields.io/badge/pt__BR-84.23%25-yellow)
<details>
<summary>Missing keys in pt_BR.axaml</summary>
@ -184,6 +229,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange
- Text.BranchCM.CustomAction
- Text.BranchCM.MergeMultiBranches
- Text.BranchCM.ResetToSelectedCommit
- Text.BranchUpstreamInvalid
- Text.Checkout.RecurseSubmodules
- Text.Clone.RecurseSubmodules
@ -192,6 +238,7 @@ This document shows the translation status of each locale file in the repository
- Text.CommitCM.CopySubject
- Text.CommitCM.Merge
- Text.CommitCM.MergeMultiple
- Text.CommitDetail.Changes.Count
- Text.CommitDetail.Files.Search
- Text.CommitDetail.Info.Children
- Text.CommitMessageTextBox.SubjectCount
@ -206,11 +253,16 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CopyFullPath
- Text.CreateBranch.Name.WarnSpace
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.DeleteRepositoryNode.Path
- Text.DeleteRepositoryNode.TipForGroup
- Text.DeleteRepositoryNode.TipForRepository
- Text.Diff.First
- Text.Diff.Last
- Text.Diff.Submodule.Deleted
- Text.Diff.UseBlockNavigation
- Text.Fetch.Force
- Text.FileCM.ResolveUsing
@ -238,6 +290,7 @@ 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.Pull.RecurseSubmodules
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@ -258,6 +311,9 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
@ -266,6 +322,7 @@ This document shows the translation status of each locale file in the repository
- Text.Stash.AutoRestore
- Text.Stash.AutoRestore.Tip
- Text.StashCM.SaveAsPatch
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@ -286,17 +343,9 @@ This document shows the translation status of each locale file in the repository
</details>
### ![ru__RU](https://img.shields.io/badge/ru__RU-99.75%25-yellow)
### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)
<details>
<summary>Missing keys in ru_RU.axaml</summary>
- Text.Hotkeys.Global.SwitchTab
- Text.Launcher.Pages
</details>
### ![ta__IN](https://img.shields.io/badge/ta__IN-94.05%25-yellow)
### ![ta__IN](https://img.shields.io/badge/ta__IN-92.62%25-yellow)
<details>
<summary>Missing keys in ta_IN.axaml</summary>
@ -308,16 +357,23 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
@ -326,6 +382,7 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@ -333,6 +390,10 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
@ -351,7 +412,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![uk__UA](https://img.shields.io/badge/uk__UA-95.19%25-yellow)
### ![uk__UA](https://img.shields.io/badge/uk__UA-93.74%25-yellow)
<details>
<summary>Missing keys in uk_UA.axaml</summary>
@ -363,12 +424,19 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.ConfigureWorkspace.Name
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
@ -377,6 +445,7 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@ -384,6 +453,10 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited

View file

@ -1 +1 @@
2025.18
2025.19

View file

@ -548,7 +548,7 @@ namespace SourceGit
private void TryLaunchAsNormal(IClassicDesktopStyleApplicationLifetime desktop)
{
Native.OS.SetupEnternalTools();
Native.OS.SetupExternalTools();
Models.AvatarManager.Instance.Start();
string startupRepo = null;
@ -671,7 +671,16 @@ namespace SourceGit
prevChar = c;
}
trimmed.Add(sb.ToString());
var name = sb.ToString();
var idx = name.IndexOf('#');
if (idx >= 0)
{
if (!name.Equals("fonts:Inter#Inter", StringComparison.Ordinal) &&
!name.Equals("fonts:SourceGit#JetBrains Mono", StringComparison.Ordinal))
continue;
}
trimmed.Add(name);
}
return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty;

View file

@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Text;
namespace SourceGit.Commands
{
public static class Branch
{
@ -11,12 +13,20 @@
return cmd.ReadToEnd().StdOut.Trim();
}
public static bool Create(string repo, string name, string basedOn, Models.ICommandLog log)
public static bool Create(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("branch ");
if (force)
builder.Append("-f ");
builder.Append(name);
builder.Append(" ");
builder.Append(basedOn);
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch {name} {basedOn}";
cmd.Args = builder.ToString();
cmd.Log = log;
return cmd.Exec();
}

View file

@ -13,15 +13,28 @@ namespace SourceGit.Commands
public bool Branch(string branch, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --progress {branch}";
var builder = new StringBuilder();
builder.Append("checkout --progress ");
if (force)
builder.Append("--force ");
builder.Append(branch);
Args = builder.ToString();
return Exec();
}
public bool Branch(string branch, string basedOn, bool force)
public bool Branch(string branch, string basedOn, bool force, bool allowOverwrite)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout --progress -b {branch} {basedOn}";
var builder = new StringBuilder();
builder.Append("checkout --progress ");
builder.Append(allowOverwrite ? "-B " : "-b ");
if (force)
builder.Append("--force ");
builder.Append(branch);
builder.Append(" ");
builder.Append(basedOn);
Args = builder.ToString();
return Exec();
}

View file

@ -36,44 +36,14 @@ namespace SourceGit.Commands
public bool Exec()
{
Log?.AppendLine($"$ git {Args}\n");
var start = CreateGitStartInfo();
var errs = new List<string>();
var proc = new Process() { StartInfo = start };
Log?.AppendLine($"$ git {Args}\n");
proc.OutputDataReceived += (_, e) =>
{
if (e.Data == null)
return;
Log?.AppendLine(e.Data);
};
proc.ErrorDataReceived += (_, e) =>
{
if (string.IsNullOrEmpty(e.Data))
{
errs.Add(string.Empty);
return;
}
Log?.AppendLine(e.Data);
// Ignore progress messages
if (e.Data.StartsWith("remote: Enumerating objects:", StringComparison.Ordinal))
return;
if (e.Data.StartsWith("remote: Counting objects:", StringComparison.Ordinal))
return;
if (e.Data.StartsWith("remote: Compressing objects:", StringComparison.Ordinal))
return;
if (e.Data.StartsWith("Filtering content:", StringComparison.Ordinal))
return;
if (REG_PROGRESS().IsMatch(e.Data))
return;
errs.Add(e.Data);
};
proc.OutputDataReceived += (_, e) => HandleOutput(e.Data, errs);
proc.ErrorDataReceived += (_, e) => HandleOutput(e.Data, errs);
var dummy = null as Process;
var dummyProcLock = new object();
@ -222,6 +192,28 @@ namespace SourceGit.Commands
return start;
}
private void HandleOutput(string line, List<string> errs)
{
line = line ?? string.Empty;
Log?.AppendLine(line);
// Lines to hide in error message.
if (line.Length > 0)
{
if (line.StartsWith("remote: Enumerating objects:", StringComparison.Ordinal) ||
line.StartsWith("remote: Counting objects:", StringComparison.Ordinal) ||
line.StartsWith("remote: Compressing objects:", StringComparison.Ordinal) ||
line.StartsWith("Filtering content:", StringComparison.Ordinal) ||
line.StartsWith("hint:", StringComparison.Ordinal))
return;
if (REG_PROGRESS().IsMatch(line))
return;
}
errs.Add(line);
}
[GeneratedRegex(@"\d+%")]
private static partial Regex REG_PROGRESS();
}

View file

@ -27,7 +27,7 @@ namespace SourceGit.Commands
}
}
public static void RunAndWait(string repo, string file, string args, Action<string> outputHandler)
public static void RunAndWait(string repo, string file, string args, Models.ICommandLog log)
{
var start = new ProcessStartInfo();
start.FileName = file;
@ -40,20 +40,22 @@ namespace SourceGit.Commands
start.StandardErrorEncoding = Encoding.UTF8;
start.WorkingDirectory = repo;
log?.AppendLine($"$ {file} {args}\n");
var proc = new Process() { StartInfo = start };
var builder = new StringBuilder();
proc.OutputDataReceived += (_, e) =>
{
if (e.Data != null)
outputHandler?.Invoke(e.Data);
log?.AppendLine(e.Data);
};
proc.ErrorDataReceived += (_, e) =>
{
if (e.Data != null)
{
outputHandler?.Invoke(e.Data);
log?.AppendLine(e.Data);
builder.AppendLine(e.Data);
}
};

View file

@ -1,53 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text;
using Avalonia.Threading;
namespace SourceGit.Commands
{
public static class GitFlow
{
public class BranchDetectResult
public static bool Init(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
{
public bool IsGitFlowBranch { get; set; } = false;
public string Type { get; set; } = string.Empty;
public string Prefix { get; set; } = string.Empty;
}
public static bool IsEnabled(string repo, List<Models.Branch> branches)
{
var localBrancheNames = new HashSet<string>();
foreach (var branch in branches)
{
if (branch.IsLocal)
localBrancheNames.Add(branch.Name);
}
var config = new Config(repo).ListAll();
if (!config.TryGetValue("gitflow.branch.master", out string master) || !localBrancheNames.Contains(master))
return false;
if (!config.TryGetValue("gitflow.branch.develop", out string develop) || !localBrancheNames.Contains(develop))
return false;
return config.ContainsKey("gitflow.prefix.feature") &&
config.ContainsKey("gitflow.prefix.release") &&
config.ContainsKey("gitflow.prefix.hotfix");
}
public static bool Init(string repo, List<Models.Branch> branches, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
{
var current = branches.Find(x => x.IsCurrent);
var masterBranch = branches.Find(x => x.Name == master);
if (masterBranch == null && current != null)
Branch.Create(repo, master, current.Head, log);
var devBranch = branches.Find(x => x.Name == develop);
if (devBranch == null && current != null)
Branch.Create(repo, develop, current.Head, log);
var config = new Config(repo);
config.Set("gitflow.branch.master", master);
config.Set("gitflow.branch.develop", develop);
@ -66,90 +25,53 @@ namespace SourceGit.Commands
return init.Exec();
}
public static string GetPrefix(string repo, string type)
public static bool Start(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log)
{
return new Config(repo).Get($"gitflow.prefix.{type}");
}
public static BranchDetectResult DetectType(string repo, List<Models.Branch> branches, string branch)
{
var rs = new BranchDetectResult();
var localBrancheNames = new HashSet<string>();
foreach (var b in branches)
{
if (b.IsLocal)
localBrancheNames.Add(b.Name);
}
var config = new Config(repo).ListAll();
if (!config.TryGetValue("gitflow.branch.master", out string master) || !localBrancheNames.Contains(master))
return rs;
if (!config.TryGetValue("gitflow.branch.develop", out string develop) || !localBrancheNames.Contains(develop))
return rs;
if (!config.TryGetValue("gitflow.prefix.feature", out var feature) ||
!config.TryGetValue("gitflow.prefix.release", out var release) ||
!config.TryGetValue("gitflow.prefix.hotfix", out var hotfix))
return rs;
if (branch.StartsWith(feature, StringComparison.Ordinal))
{
rs.IsGitFlowBranch = true;
rs.Type = "feature";
rs.Prefix = feature;
}
else if (branch.StartsWith(release, StringComparison.Ordinal))
{
rs.IsGitFlowBranch = true;
rs.Type = "release";
rs.Prefix = release;
}
else if (branch.StartsWith(hotfix, StringComparison.Ordinal))
{
rs.IsGitFlowBranch = true;
rs.Type = "hotfix";
rs.Prefix = hotfix;
}
return rs;
}
public static bool Start(string repo, string type, string name, Models.ICommandLog log)
{
if (!SUPPORTED_BRANCH_TYPES.Contains(type))
{
Dispatcher.UIThread.Post(() =>
{
App.RaiseException(repo, "Bad branch type!!!");
});
return false;
}
var start = new Command();
start.WorkingDirectory = repo;
start.Context = repo;
start.Args = $"flow {type} start {name}";
switch (type)
{
case Models.GitFlowBranchType.Feature:
start.Args = $"flow feature start {name}";
break;
case Models.GitFlowBranchType.Release:
start.Args = $"flow release start {name}";
break;
case Models.GitFlowBranchType.Hotfix:
start.Args = $"flow hotfix start {name}";
break;
default:
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, "Bad git-flow branch type!!!"));
return false;
}
start.Log = log;
return start.Exec();
}
public static bool Finish(string repo, string type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
public static bool Finish(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
{
if (!SUPPORTED_BRANCH_TYPES.Contains(type))
{
Dispatcher.UIThread.Post(() =>
{
App.RaiseException(repo, "Bad branch type!!!");
});
return false;
}
var builder = new StringBuilder();
builder.Append("flow ");
builder.Append(type);
switch (type)
{
case Models.GitFlowBranchType.Feature:
builder.Append("feature");
break;
case Models.GitFlowBranchType.Release:
builder.Append("release");
break;
case Models.GitFlowBranchType.Hotfix:
builder.Append("hotfix");
break;
default:
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, "Bad git-flow branch type!!!"));
return false;
}
builder.Append(" finish ");
if (squash)
builder.Append("--squash ");
@ -166,14 +88,5 @@ namespace SourceGit.Commands
finish.Log = log;
return finish.Exec();
}
private static readonly List<string> SUPPORTED_BRANCH_TYPES = new List<string>()
{
"feature",
"release",
"bugfix",
"hotfix",
"support",
};
}
}

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 {commit} --numstat -- \"{path}\"";
Args = $"diff {Models.Commit.EmptyTreeSHA1} {commit} --numstat -- \"{path}\"";
RaiseError = false;
}

View file

@ -2,7 +2,7 @@
{
public class Pull : Command
{
public Pull(string repo, string remote, string branch, bool useRebase, bool noTags)
public Pull(string repo, string remote, string branch, bool useRebase)
{
WorkingDirectory = repo;
Context = repo;
@ -12,9 +12,6 @@
if (useRebase)
Args += "--rebase=true ";
if (noTags)
Args += "--no-tags ";
Args += $"{remote} {branch}";
}
}

View file

@ -27,7 +27,7 @@ namespace SourceGit.Commands
return branches;
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var remoteBranches = new HashSet<string>();
var remoteHeads = new Dictionary<string, string>();
foreach (var line in lines)
{
var b = ParseLine(line);
@ -35,7 +35,7 @@ namespace SourceGit.Commands
{
branches.Add(b);
if (!b.IsLocal)
remoteBranches.Add(b.FullName);
remoteHeads.Add(b.FullName, b.Head);
else
localBranchesCount++;
}
@ -44,7 +44,22 @@ namespace SourceGit.Commands
foreach (var b in branches)
{
if (b.IsLocal && !string.IsNullOrEmpty(b.Upstream))
b.IsUpstreamGone = !remoteBranches.Contains(b.Upstream);
{
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
{
b.IsUpstreamGone = false;
if (b.TrackStatus == null)
b.TrackStatus = new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
}
else
{
b.IsUpstreamGone = true;
if (b.TrackStatus == null)
b.TrackStatus = new Models.BranchTrackStatus();
}
}
}
return branches;
@ -93,9 +108,10 @@ namespace SourceGit.Commands
branch.Upstream = parts[4];
branch.IsUpstreamGone = false;
if (branch.IsLocal && !string.IsNullOrEmpty(parts[5]) && !parts[5].Equals("=", StringComparison.Ordinal))
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
else
if (!branch.IsLocal ||
string.IsNullOrEmpty(branch.Upstream) ||
string.IsNullOrEmpty(parts[5]) ||
parts[5].Equals("=", StringComparison.Ordinal))
branch.TrackStatus = new Models.BranchTrackStatus();
return branch;

View file

@ -128,30 +128,16 @@ namespace SourceGit.Commands
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied);
break;
case "DD":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Deleted);
break;
case "AU":
change.Set(Models.ChangeState.Added, Models.ChangeState.Unmerged);
break;
case "UD":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Deleted);
break;
case "UA":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Added);
break;
case "DU":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Unmerged);
break;
case "AA":
change.Set(Models.ChangeState.Added, Models.ChangeState.Added);
break;
case "UU":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Unmerged);
change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted);
break;
case "??":
change.Set(Models.ChangeState.Untracked, Models.ChangeState.Untracked);
break;
default:
change.Set(Models.ChangeState.None, Models.ChangeState.Untracked);
break;
}

View file

@ -6,7 +6,7 @@ namespace SourceGit.Commands
{
public partial class QueryStagedChangesWithAmend : Command
{
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMTUX])\d{0,6}\t(.*)$")]
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMT])\d{0,6}\t(.*)$")]
private static partial Regex REG_FORMAT1();
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")]
private static partial Regex REG_FORMAT2();
@ -22,76 +22,71 @@ namespace SourceGit.Commands
public List<Models.Change> Result()
{
var rs = ReadToEnd();
if (rs.IsSuccess)
if (!rs.IsSuccess)
return [];
var changes = new List<Models.Change>();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var changes = new List<Models.Change>();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
var match = REG_FORMAT2().Match(line);
if (match.Success)
{
var match = REG_FORMAT2().Match(line);
if (match.Success)
var change = new Models.Change()
{
var change = new Models.Change()
Path = match.Groups[3].Value,
DataForAmend = new Models.ChangeDataForAmend()
{
Path = match.Groups[3].Value,
DataForAmend = new Models.ChangeDataForAmend()
{
FileMode = match.Groups[1].Value,
ObjectHash = match.Groups[2].Value,
ParentSHA = _parent,
},
};
change.Set(Models.ChangeState.Renamed);
changes.Add(change);
continue;
}
match = REG_FORMAT1().Match(line);
if (match.Success)
{
var change = new Models.Change()
{
Path = match.Groups[4].Value,
DataForAmend = new Models.ChangeDataForAmend()
{
FileMode = match.Groups[1].Value,
ObjectHash = match.Groups[2].Value,
ParentSHA = _parent,
},
};
var type = match.Groups[3].Value;
switch (type)
{
case "A":
change.Set(Models.ChangeState.Added);
break;
case "C":
change.Set(Models.ChangeState.Copied);
break;
case "D":
change.Set(Models.ChangeState.Deleted);
break;
case "M":
change.Set(Models.ChangeState.Modified);
break;
case "T":
change.Set(Models.ChangeState.TypeChanged);
break;
case "U":
change.Set(Models.ChangeState.Unmerged);
break;
}
changes.Add(change);
}
FileMode = match.Groups[1].Value,
ObjectHash = match.Groups[2].Value,
ParentSHA = _parent,
},
};
change.Set(Models.ChangeState.Renamed);
changes.Add(change);
continue;
}
return changes;
match = REG_FORMAT1().Match(line);
if (match.Success)
{
var change = new Models.Change()
{
Path = match.Groups[4].Value,
DataForAmend = new Models.ChangeDataForAmend()
{
FileMode = match.Groups[1].Value,
ObjectHash = match.Groups[2].Value,
ParentSHA = _parent,
},
};
var type = match.Groups[3].Value;
switch (type)
{
case "A":
change.Set(Models.ChangeState.Added);
break;
case "C":
change.Set(Models.ChangeState.Copied);
break;
case "D":
change.Set(Models.ChangeState.Deleted);
break;
case "M":
change.Set(Models.ChangeState.Modified);
break;
case "T":
change.Set(Models.ChangeState.TypeChanged);
break;
}
changes.Add(change);
}
}
return [];
return changes;
}
private string _parent = string.Empty;
private readonly string _parent;
}
}

View file

@ -112,7 +112,7 @@ namespace SourceGit.Commands
}
}
Args = $"--no-optional-locks status -uno --porcelain -- {builder}";
Args = $"--no-optional-locks status --porcelain -- {builder}";
rs = ReadToEnd();
if (!rs.IsSuccess)
return submodules;

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace SourceGit.Commands
{
public partial class QueryUpdatableSubmodules : Command
{
[GeneratedRegex(@"^([U\-\+ ])([0-9a-f]+)\s(.*?)(\s\(.*\))?$")]
private static partial Regex REG_FORMAT_STATUS();
public QueryUpdatableSubmodules(string repo)
{
WorkingDirectory = repo;
Context = repo;
Args = "submodule status";
}
public List<string> Result()
{
var submodules = new List<string>();
var rs = ReadToEnd();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var match = REG_FORMAT_STATUS().Match(line);
if (match.Success)
{
var stat = match.Groups[1].Value;
var path = match.Groups[3].Value;
if (!stat.StartsWith(' '))
submodules.Add(path);
}
}
return submodules;
}
}
}

View file

@ -13,7 +13,7 @@ namespace SourceGit.Commands
public bool Add(string url, string relativePath, bool recursive)
{
Args = $"submodule add {url} \"{relativePath}\"";
Args = $"-c protocol.file.allow=always submodule add \"{url}\" \"{relativePath}\"";
if (!Exec())
return false;
@ -29,23 +29,7 @@ namespace SourceGit.Commands
}
}
public bool Update(string module, bool init, bool recursive, bool useRemote)
{
Args = "submodule update";
if (init)
Args += " --init";
if (recursive)
Args += " --recursive";
if (useRemote)
Args += " --remote";
if (!string.IsNullOrEmpty(module))
Args += $" -- \"{module}\"";
return Exec();
}
public bool Update(List<Models.Submodule> modules, bool init, bool recursive, bool useRemote)
public bool Update(List<string> modules, bool init, bool recursive, bool useRemote = false)
{
var builder = new StringBuilder();
builder.Append("submodule update");
@ -60,20 +44,22 @@ namespace SourceGit.Commands
{
builder.Append(" --");
foreach (var module in modules)
builder.Append($" \"{module.Path}\"");
builder.Append($" \"{module}\"");
}
Args = builder.ToString();
return Exec();
}
public bool Delete(string relativePath)
public bool Deinit(string module, bool force)
{
Args = $"submodule deinit -f \"{relativePath}\"";
if (!Exec())
return false;
Args = force ? $"submodule deinit -f -- \"{module}\"" : $"submodule deinit -- \"{module}\"";
return Exec();
}
Args = $"rm -rf \"{relativePath}\"";
public bool Delete(string module)
{
Args = $"rm -rf \"{module}\"";
return Exec();
}
}

View file

@ -1,12 +0,0 @@
namespace SourceGit.Commands
{
public class UpdateRef : Command
{
public UpdateRef(string repo, string refName, string toRevision)
{
WorkingDirectory = repo;
Context = repo;
Args = $"update-ref {refName} {toRevision}";
}
}
}

View file

@ -7,6 +7,9 @@ namespace SourceGit.Converters
{
public static class ListConverters
{
public static readonly FuncValueConverter<IList, string> Count =
new FuncValueConverter<IList, string>(v => v == null ? "0" : $"{v.Count}");
public static readonly FuncValueConverter<IList, string> ToCount =
new FuncValueConverter<IList, string>(v => v == null ? "(0)" : $"({v.Count})");

View file

@ -18,8 +18,8 @@ namespace SourceGit.Models
Deleted,
Renamed,
Copied,
Unmerged,
Untracked
Untracked,
Conflicted,
}
public class ChangeDataForAmend
@ -36,20 +36,7 @@ namespace SourceGit.Models
public string Path { get; set; } = "";
public string OriginalPath { get; set; } = "";
public ChangeDataForAmend DataForAmend { get; set; } = null;
public bool IsConflict
{
get
{
if (Index == ChangeState.Unmerged || WorkTree == ChangeState.Unmerged)
return true;
if (Index == ChangeState.Added && WorkTree == ChangeState.Added)
return true;
if (Index == ChangeState.Deleted && WorkTree == ChangeState.Deleted)
return true;
return false;
}
}
public bool IsConflicted => WorkTree == ChangeState.Conflicted;
public void Set(ChangeState index, ChangeState workTree = ChangeState.None)
{
@ -77,6 +64,7 @@ namespace SourceGit.Models
if (Path[0] == '"')
Path = Path.Substring(1, Path.Length - 2);
if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"')
OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2);
}

View file

@ -18,6 +18,9 @@ namespace SourceGit.Models
public class Commit
{
// As retrieved by: git mktree </dev/null
public static readonly string EmptyTreeSHA1 = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
public static double OpacityForNotMerged
{
get;

19
src/Models/Count.cs Normal file
View file

@ -0,0 +1,19 @@
using System;
namespace SourceGit.Models
{
public class Count : IDisposable
{
public int Value { get; set; } = 0;
public Count(int value)
{
Value = value;
}
public void Dispose()
{
// Ignore
}
}
}

View file

@ -65,7 +65,7 @@ namespace SourceGit.Models
/// <param name="change"></param>
public DiffOption(Commit commit, Change change)
{
var baseRevision = commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : $"{commit.SHA}^";
var baseRevision = commit.Parents.Count == 0 ? Commit.EmptyTreeSHA1 : $"{commit.SHA}^";
_revisions.Add(baseRevision);
_revisions.Add(commit.SHA);
_path = change.Path;
@ -79,7 +79,7 @@ namespace SourceGit.Models
/// <param name="file"></param>
public DiffOption(Commit commit, string file)
{
var baseRevision = commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : $"{commit.SHA}^";
var baseRevision = commit.Parents.Count == 0 ? Commit.EmptyTreeSHA1 : $"{commit.SHA}^";
_revisions.Add(baseRevision);
_revisions.Add(commit.SHA);
_path = file;
@ -124,6 +124,6 @@ namespace SourceGit.Models
private readonly string _path;
private readonly string _orgPath = string.Empty;
private readonly string _extra = string.Empty;
private readonly List<string> _revisions = new List<string>();
private readonly List<string> _revisions = [];
}
}

46
src/Models/GitFlow.cs Normal file
View file

@ -0,0 +1,46 @@
namespace SourceGit.Models
{
public enum GitFlowBranchType
{
None = 0,
Feature,
Release,
Hotfix,
}
public class GitFlow
{
public string Master { get; set; } = string.Empty;
public string Develop { get; set; } = string.Empty;
public string FeaturePrefix { get; set; } = string.Empty;
public string ReleasePrefix { get; set; } = string.Empty;
public string HotfixPrefix { get; set; } = string.Empty;
public bool IsValid
{
get
{
return !string.IsNullOrEmpty(Master) &&
!string.IsNullOrEmpty(Develop) &&
!string.IsNullOrEmpty(FeaturePrefix) &&
!string.IsNullOrEmpty(ReleasePrefix) &&
!string.IsNullOrEmpty(HotfixPrefix);
}
}
public string GetPrefix(GitFlowBranchType type)
{
switch (type)
{
case GitFlowBranchType.Feature:
return FeaturePrefix;
case GitFlowBranchType.Release:
return ReleasePrefix;
case GitFlowBranchType.Hotfix:
return HotfixPrefix;
default:
return string.Empty;
}
}
}
}

View file

@ -2,6 +2,8 @@
{
public interface IRepository
{
bool MayHaveSubmodules();
void RefreshBranches();
void RefreshWorktrees();
void RefreshTags();

View file

@ -6,8 +6,10 @@ namespace SourceGit.Models
{
public partial class Remote
{
[GeneratedRegex(@"^https?://([-a-zA-Z0-9:%._\+~#=]+@)?[-a-zA-Z0-9:%._\+~#=]{1,256}(\.[a-zA-Z0-9()]{1,6})?(:[0-9]{1,5})?\b(/[-a-zA-Z0-9()@:%_\+.~#?&=]+)+(\.git)?$")]
[GeneratedRegex(@"^https?://[^/]+/.+[^/\.]$")]
private static partial Regex REG_HTTPS();
[GeneratedRegex(@"^git://[^/]+/.+[^/\.]$")]
private static partial Regex REG_GIT();
[GeneratedRegex(@"^[\w\-]+@[\w\.\-]+(\:[0-9]+)?:([a-zA-z0-9~%][\w\-\./~%]*)?[a-zA-Z0-9](\.git)?$")]
private static partial Regex REG_SSH1();
[GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/([a-zA-z0-9~%][\w\-\./~%]*)?[a-zA-Z0-9](\.git)?$")]
@ -18,6 +20,7 @@ namespace SourceGit.Models
private static readonly Regex[] URL_FORMATS = [
REG_HTTPS(),
REG_GIT(),
REG_SSH1(),
REG_SSH2(),
];
@ -30,13 +33,10 @@ namespace SourceGit.Models
if (string.IsNullOrWhiteSpace(url))
return false;
for (int i = 1; i < URL_FORMATS.Length; i++)
{
if (URL_FORMATS[i].IsMatch(url))
return true;
}
if (REG_SSH1().IsMatch(url))
return true;
return false;
return REG_SSH2().IsMatch(url);
}
public static bool IsValidURL(string url)
@ -50,7 +50,10 @@ namespace SourceGit.Models
return true;
}
return url.EndsWith(".git", StringComparison.Ordinal) && Directory.Exists(url);
return url.StartsWith("file://", StringComparison.Ordinal) ||
url.StartsWith("./", StringComparison.Ordinal) ||
url.StartsWith("../", StringComparison.Ordinal) ||
Directory.Exists(url);
}
public bool TryGetVisitURL(out string url)

View file

@ -80,18 +80,6 @@ namespace SourceGit.Models
set;
} = true;
public bool FetchWithoutTagsOnPull
{
get;
set;
} = false;
public bool FetchAllBranchesOnPull
{
get;
set;
} = true;
public bool CheckSubmodulesOnPush
{
get;
@ -417,6 +405,7 @@ namespace SourceGit.Models
public void PushCommitMessage(string message)
{
message = message.Trim().ReplaceLineEndings("\n");
var existIdx = CommitMessages.IndexOf(message);
if (existIdx == 0)
return;

View file

@ -107,7 +107,6 @@ namespace SourceGit.Models
{
_updateBranch = 0;
_updateWC = 0;
_updateSubmodules = 0;
if (_updateTags > 0)
{
@ -115,10 +114,15 @@ namespace SourceGit.Models
Task.Run(_repo.RefreshTags);
}
if (_updateSubmodules > 0 || _repo.MayHaveSubmodules())
{
_updateSubmodules = 0;
Task.Run(_repo.RefreshSubmodules);
}
Task.Run(_repo.RefreshBranches);
Task.Run(_repo.RefreshCommits);
Task.Run(_repo.RefreshWorkingCopyChanges);
Task.Run(_repo.RefreshSubmodules);
Task.Run(_repo.RefreshWorktrees);
}
@ -150,14 +154,29 @@ namespace SourceGit.Models
private void OnRepositoryChanged(object o, FileSystemEventArgs e)
{
if (string.IsNullOrEmpty(e.Name) || e.Name.EndsWith(".lock", StringComparison.Ordinal))
if (string.IsNullOrEmpty(e.Name))
return;
var name = e.Name.Replace("\\", "/");
if (name.StartsWith("modules", StringComparison.Ordinal) && name.EndsWith("HEAD", StringComparison.Ordinal))
if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) ||
name.EndsWith(".lock", StringComparison.Ordinal) ||
name.StartsWith("lfs/", StringComparison.Ordinal))
return;
if (name.StartsWith("modules", StringComparison.Ordinal))
{
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
_updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
if (name.EndsWith("/HEAD", StringComparison.Ordinal) ||
name.EndsWith("/ORIG_HEAD", StringComparison.Ordinal))
{
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
_updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
}
}
else if (name.Equals("MERGE_HEAD", StringComparison.Ordinal) ||
name.Equals("AUTO_MERGE", StringComparison.Ordinal))
{
if (_repo.MayHaveSubmodules())
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
}
else if (name.StartsWith("refs/tags", StringComparison.Ordinal))
{
@ -187,9 +206,20 @@ namespace SourceGit.Models
return;
var name = e.Name.Replace("\\", "/");
if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal))
if (name.Equals(".git", StringComparison.Ordinal) ||
name.StartsWith(".git/", StringComparison.Ordinal) ||
name.EndsWith("/.git", StringComparison.Ordinal))
return;
if (name.StartsWith(".vs/", StringComparison.Ordinal))
return;
if (name.Equals(".gitmodules", StringComparison.Ordinal))
{
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
return;
}
lock (_lockSubmodule)
{
foreach (var submodule in _submodules)

View file

@ -124,7 +124,7 @@ namespace SourceGit.Native
Directory.CreateDirectory(DataDir);
}
public static void SetupEnternalTools()
public static void SetupExternalTools()
{
ExternalTools = _backend.FindExternalTools();
}

View file

@ -292,7 +292,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Ausgewähltes Repository bearbeiten</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Führe benutzerdefinierte Aktion aus</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Name der Aktion:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (ohne Auschecken)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Alle Remotes fetchen</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Aktiviere '--force' Option</x:String>
@ -527,12 +526,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Worktree Informationen in `$GIT_COMMON_DIR/worktrees` löschen</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote-Branch:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Alle Branches fetchen</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Lokaler Branch:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Ohne Tags fetchen</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Rebase anstatt Merge verwenden</x:String>

View file

@ -63,6 +63,7 @@
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ on ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Reset ${0}$ to ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Invalid upstream!</x:String>
@ -124,6 +125,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash into Parent</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Children into Here</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGES</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">changed file(s)</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Search Changes...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FILES</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS File</x:String>
@ -215,6 +217,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter branch name.</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Spaces will be replaced with dashes.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Create Local Branch</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Overwrite existing branch</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Create Tag...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">New Tag At:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">GPG signing</x:String>
@ -229,6 +232,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Hold Ctrl to start directly</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Cut</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">De-initialize Submodule</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">Force de-init even if it contains local changes.</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">Submodule:</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Delete Branch</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">You are about to delete a remote branch!!!</x:String>
@ -264,6 +270,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Show hidden symbols</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Side-By-Side Diff</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMODULE</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">DELETED</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NEW</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Swap</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
@ -288,7 +295,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Run Custom Action</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Action Name:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Force override local refs</x:String>
@ -530,12 +536,11 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Prune worktree information in `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Remote Branch:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch all branches</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Fetch without tags</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Use rebase instead of merge</x:String>
@ -646,6 +651,9 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Move To:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Current Branch:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">Reset Branch (Without Checkout)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">Move To:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Reveal in File Explorer</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Revert Commit</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
@ -705,6 +713,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Add Submodule</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copy Relative Path</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">De-initialize Submodule</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch nested submodules</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Open Submodule Repository</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relative Path:</x:String>

View file

@ -67,6 +67,7 @@
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ en ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renombrar ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Resetear ${0}$ a ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Establecer Rama de Seguimiento...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparar Ramas</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">¡Upstream inválido!</x:String>
@ -128,6 +129,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash en Parent</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Commits Hijos hasta Aquí</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CAMBIOS</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">archivo(s) modificado(s)</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Buscar Cambios...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">ARCHIVOS</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Archivo LFS</x:String>
@ -233,6 +235,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">ligera</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Mantenga Ctrl para iniciar directamente</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Cortar</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">Desinicializar Submódulo</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">Forzar desinicialización incluso si contiene cambios locales.</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">Submódulo:</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Eliminar Rama</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">¡Estás a punto de eliminar una rama remota!</x:String>
@ -268,6 +273,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Mostrar símbolos ocultos</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diferencia Lado a Lado</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMÓDULO</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">BORRADO</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NUEVO</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Intercambiar</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Resaltado de Sintaxis</x:String>
@ -292,7 +298,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Editar Repositorio Seleccionado</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Ejecutar Acción Personalizada</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nombre de la Acción:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (sin checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch todos los remotos</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Utilizar opción '--force'</x:String>
@ -390,6 +395,8 @@
<x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Ir a la página anterior</x:String>
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Crear nueva página</x:String>
<x:String x:Key="Text.Hotkeys.Global.OpenPreferences" xml:space="preserve">Abrir diálogo de preferencias</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchWorkspace" xml:space="preserve">Cambiar espacio de trabajo activo</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchTab" xml:space="preserve">Cambiar página activa</x:String>
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORIO</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit cambios staged</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit y push cambios staged</x:String>
@ -432,6 +439,8 @@
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Abrir en el Navegador</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">AVISO</x:String>
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Espacios de trabajo</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Páginas</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Rama</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Opción de Merge:</x:String>
@ -530,12 +539,11 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Podar información de worktree en `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Rama Remota:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch todas las ramas</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Cambios Locales:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Fetch sin etiquetas</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">Actualizar todos los submódulos</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Usar rebase en lugar de merge</x:String>
@ -646,6 +654,9 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Modo de Reset:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Mover a:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Rama Actual:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">Resetear Rama (Sin hacer Checkout)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">Mover A:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Revelar en el Explorador de Archivos</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Revertir Commit</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
@ -705,6 +716,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMÓDULOS</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Añadir Submódulo</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copiar Ruta Relativa</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">Desinicializar Submódulo</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch submódulos anidados</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Abrir Repositorio del Submódulo</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Ruta Relativa:</x:String>

View file

@ -275,7 +275,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Éditer le dépôt sélectionné</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Lancer action personnalisée</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nom de l'action :</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (sans récupération)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch toutes les branches distantes</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Outrepasser les vérifications de refs</x:String>
@ -509,12 +508,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve"> Élaguer les information de worktree dans `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branche distante :</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch toutes les branches</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Dans :</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Changements locaux :</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Réappliquer</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Fetch sans les tags</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Dépôt distant :</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Utiliser rebase au lieu de merge</x:String>

View file

@ -292,7 +292,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Modifica Repository Selezionato</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Esegui Azione Personalizzata</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nome Azione:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Avanzamento Veloce (senza verifica)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Recupera</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Recupera da tutti i remoti</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Forza la sovrascrittura dei riferimenti locali</x:String>
@ -530,12 +529,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Potatura delle informazioni di worktree in `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Scarica</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Recupera tutti i branch</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">In:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Modifiche Locali:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Scarta</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stasha e Riapplica</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Recupera senza tag</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Scarica (Recupera e Unisci)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Riallineare anziché unire</x:String>

View file

@ -275,7 +275,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">選択中のリポジトリを編集</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">カスタムアクションを実行</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">アクション名:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">(チェックアウトせずに)ブランチを早送りする</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">フェッチ</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">すべてのリモートをフェッチ</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">ローカル参照を強制的に上書き</x:String>
@ -509,12 +508,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">`$GIT_DIR/worktrees` の作業ツリー情報を削除</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">プル</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">ブランチ:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">すべてのブランチをフェッチ</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">宛先:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">ローカルの変更:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">破棄</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">スタッシュして再適用</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">タグなしでフェッチ</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">リモート:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">プル (フェッチ &amp; マージ)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">マージの代わりにリベースを使用</x:String>

View file

@ -249,7 +249,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Editar Repositório Selecionado</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Executar ação customizada</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Nome da ação:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (sem checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Buscar</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Buscar todos os remotos</x:String>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Buscar sem tags</x:String>
@ -465,12 +464,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Podar informações de worktree em `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Puxar</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch Remoto:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Buscar todos os branches</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Para:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Alterações Locais:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Descartar</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Guardar &amp; Reaplicar</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Buscar sem tags</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remoto:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Puxar (Buscar &amp; Mesclar)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Usar rebase em vez de merge</x:String>

View file

@ -67,6 +67,7 @@
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Выложить ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Переместить ${0}$ на ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Переименовать ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Сбросить ${0}$ к ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Отслеживать ветку...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Сравнение веток</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Недопустимая основная ветка!</x:String>
@ -128,6 +129,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Объединить с предыдущей ревизией</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Объединить все следующие ревизии с этим</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ИЗМЕНЕНИЯ</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">изменённый(х) файл(ов)</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Найти изменения....</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">ФАЙЛЫ</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Файл LFS</x:String>
@ -219,6 +221,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Введите имя ветки.</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Пробелы будут заменены на тире.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Создать локальную ветку</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Перезаписать существующую ветку</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Создать метку...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Новая метка у:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">GPG подпись</x:String>
@ -233,6 +236,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">Простой</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Удерживайте Ctrl, чтобы сразу начать</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Вырезать</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">Удалить подмодуль</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">Принудительно удалить даже если содержит локальные изменения.</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">Подмодуль:</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Удалить ветку</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">Вы собираетесь удалить внешнюю ветку!!!</x:String>
@ -268,6 +274,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Показывать скрытые символы</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Сравнение рядом</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">ПОДМОДУЛЬ</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">УДАЛЁН</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">НОВЫЙ</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Обмен</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Подсветка синтаксиса </x:String>
@ -292,7 +299,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Редактировать выбранный репозиторий</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Выполнить пользовательское действие</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Имя действия:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Быстрая перемотка вперёд (без проверки)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Извлечь</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Извлечь все внешние репозитории</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Разрешить опцию (--force)</x:String>
@ -391,6 +397,7 @@
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Создать новую вкладку</x:String>
<x:String x:Key="Text.Hotkeys.Global.OpenPreferences" xml:space="preserve">Открыть диалоговое окно настроек</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchWorkspace" xml:space="preserve">Переключить активное рабочее место</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchTab" xml:space="preserve">Переключить активную страницу</x:String>
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">РЕПОЗИТОРИЙ</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Зафиксировать сформированные изменения</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Зафиксировать и выложить сформированные изменения</x:String>
@ -434,6 +441,7 @@
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ОШИБКА</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">УВЕДОМЛЕНИЕ</x:String>
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Рабочие места</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Страницы</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Влить ветку</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">В:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Опции слияния:</x:String>
@ -532,12 +540,11 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Информация об обрезке рабочего каталога в «$GIT_COMMON_DIR/worktrees»</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Загрузить</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Ветка внешнего репозитория:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Извлечь все ветки</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">В:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Локальные изменения:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Отклонить</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Отложить и применить повторно</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Загрузить без меток</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">Обновить все подмодули</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Внешний репозиторий:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Загрузить (Получить и слить)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Использовать перемещение вместо слияния</x:String>
@ -648,6 +655,9 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Режим сброса:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Переместить в:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Текущая ветка:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">Сброс ветки (без переключения)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">Переместить в:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Открыть в файловом менеджере</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Отменить ревизию</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Ревизия:</x:String>
@ -707,6 +717,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">ПОДМОДУЛИ</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Добавить подмодули</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Копировать относительный путь</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">Удалить подмодуль</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Извлечение вложенных подмодулей</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Открыть подмодуль репозитория</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Каталог:</x:String>

View file

@ -275,7 +275,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">தேர்ந்தெடுக்கப்பட்ட களஞ்சியத்தைத் திருத்து</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">தனிப்பயன் செயலை இயக்கு</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">செயல் பெயர்:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">வேகமாக முன்னோக்கி (சரிபார்க்காமல்)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">பெறு</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">எல்லா தொலைகளையும் பெறு</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">உள்ளக குறிப்புகளை கட்டாயமாக மீறு</x:String>
@ -509,12 +508,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">`$GIT_COMMON_DIR/பணிமரங்கள்` இதில் பணிமரம் தகவலை கத்தரி</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">இழு</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">தொலை கிளை:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">எல்லா கிளைகளையும் எடு</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">இதனுள்:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">உள்ளக மாற்றங்கள்:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">நிராகரி</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">பதுக்கிவை &amp; மீண்டும் இடு</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">குறிச்சொற்கள் இல்லாமல் பெறு</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">தொலை:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">இழு (எடுத்து ஒன்றிணை)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">ஒன்றிணை என்பதற்குப் பதிலாக மறுதளத்தைப் பயன்படுத்து</x:String>

View file

@ -279,7 +279,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Редагувати вибраний репозиторій</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Виконати спеціальну дію</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Ім'я дії:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Перемотати (без перемкнуття)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Витягти</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Витягти всі віддалені сховища</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Примусово перезаписати локальні refs</x:String>
@ -513,12 +512,10 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">Видалити застарілу інформацію про робочі дерева в `$GIT_COMMON_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull (Витягти)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Віддалена гілка:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Отримати всі гілки</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">В:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Локальні зміни:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Скасувати</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Сховати та Застосувати</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Отримати без тегів</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Віддалене сховище:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Використовувати rebase замість merge</x:String>

View file

@ -65,8 +65,9 @@
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">拉回(pull) ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">拉回(pull) ${0}$ 内容至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送(push)${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 分支至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重置 ${0}$ 到 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支 ...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">跟踪的上游分支不存在或已删除!</x:String>
@ -128,6 +129,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">合并此提交到上一个提交</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">合并之后的提交到此处</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">变更对比</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">个文件发生变更</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">查找变更...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">文件列表</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS文件</x:String>
@ -219,6 +221,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填写分支名称。</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格将被替换为'-'符号</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">创建本地分支</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允许重置已存在的分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新建标签 ...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">标签位于 </x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用GPG签名</x:String>
@ -233,6 +236,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">轻量标签</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">按住Ctrl键点击将以默认参数运行</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">剪切</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">取消初始化子模块</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">强制取消,即使包含本地变更</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">子模块 </x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">删除分支确认</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名 </x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在删除远程上的分支,请务必小心!!!</x:String>
@ -268,6 +274,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">显示隐藏符号</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">分列对比</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">子模块</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">删除</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">新增</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">交换比对双方</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
@ -292,7 +299,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">执行自定义操作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自定义操作 </x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">强制覆盖本地REFs</x:String>
@ -534,12 +540,11 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">清理在`$GIT_COMMON_DIR/worktrees`中的无效工作树信息</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">拉取远程中的所有分支变更</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">未提交更改 </x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">丢弃更改</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">不拉取远程标签</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">远程 </x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">拉回(拉取并合并)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">使用变基方式合并分支</x:String>
@ -650,6 +655,9 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">重置模式 </x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">提交 </x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">当前分支 </x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">重置所选分支(非当前分支)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">重置点 </x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">操作分支 </x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">在文件浏览器中查看</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">回滚操作确认</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">目标提交 </x:String>
@ -709,6 +717,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">子模块</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">添加子模块</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">复制路径</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">取消初始化</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">拉取子孙模块</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">打开仓库</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">相对仓库路径 </x:String>

View file

@ -67,6 +67,7 @@
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">推送 (push) ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 分支至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重設 ${0}$ 至 ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">追蹤上游分支不存在或已刪除!</x:String>
@ -128,6 +129,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">合併此提交到上一個提交</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">合併之後的提交到此處</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">變更對比</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">個檔案已變更</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">搜尋變更...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">檔案列表</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS 檔案</x:String>
@ -219,6 +221,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">輸入分支名稱。</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格將以英文破折號取代</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">建立本機分支</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允許覆寫現有分支</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">新增標籤...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">標籤位於:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">使用 GPG 簽章</x:String>
@ -233,6 +236,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">輕量標籤</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">按住 Ctrl 鍵將直接以預設參數執行</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">剪下</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">取消初始化子模組</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">強制取消,即使它包含本地變更</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">子模組 </x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">刪除分支確認</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">分支名稱:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">您正在刪除遠端上的分支,請務必小心!</x:String>
@ -268,6 +274,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">顯示隱藏符號</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">並排對比</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">子模組</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">已刪除</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">新增</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">交換比對雙方</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">語法上色</x:String>
@ -292,7 +299,6 @@
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">執行自訂動作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自訂動作:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">強制覆寫本機 REFs</x:String>
@ -534,12 +540,11 @@
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve">清理在 `$GIT_COMMON_DIR/worktrees` 中的無效工作區資訊</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉取 (pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支:</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">拉取遠端中的所有分支</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本機分支:</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">未提交變更:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">捨棄變更</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">不拉取遠端標籤</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">遠端:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">拉取 (提取並合併)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">使用重定基底 (rebase) 合併分支</x:String>
@ -650,6 +655,9 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">重設模式:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">移至提交:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">目前分支:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">重設選取的分支(非目前分支)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">重設位置 </x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">選取分支 </x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">在檔案瀏覽器中檢視</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">復原操作確認</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">目標提交:</x:String>
@ -709,6 +717,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">子模組</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">新增子模組</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">複製路徑</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">取消初始化</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">提取子模組</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">開啟存放庫</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">相對存放庫路徑:</x:String>

View file

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading.Tasks;
@ -14,12 +15,10 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _url, value, true);
}
[Required(ErrorMessage = "Reletive path is required!!!")]
[CustomValidation(typeof(AddSubmodule), nameof(ValidateRelativePath))]
public string RelativePath
{
get => _relativePath;
set => SetProperty(ref _relativePath, value, true);
set => SetProperty(ref _relativePath, value);
}
public bool Recursive
@ -37,20 +36,6 @@ namespace SourceGit.ViewModels
{
if (!Models.Remote.IsValidURL(url))
return new ValidationResult("Invalid repository URL format");
return ValidationResult.Success;
}
public static ValidationResult ValidateRelativePath(string path, ValidationContext ctx)
{
if (Path.Exists(path))
{
return new ValidationResult("Give path is exists already!");
}
if (Path.IsPathRooted(path))
{
return new ValidationResult("Path must be relative to this repository!");
}
return ValidationResult.Success;
}
@ -63,9 +48,20 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Add Submodule");
Use(log);
var relativePath = _relativePath;
if (string.IsNullOrEmpty(relativePath))
{
if (_url.EndsWith("/.git", StringComparison.Ordinal))
relativePath = Path.GetFileName(Path.GetDirectoryName(_url));
else if (_url.EndsWith(".git", StringComparison.Ordinal))
relativePath = Path.GetFileNameWithoutExtension(_url);
else
relativePath = Path.GetFileName(_url);
}
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Add(_url, _relativePath, Recursive);
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Add(_url, relativePath, Recursive);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));

View file

@ -17,8 +17,7 @@ namespace SourceGit.ViewModels
public bool IsRecurseSubmoduleVisible
{
get;
private set;
get => _repo.Submodules.Count > 0;
}
public bool RecurseSubmodules
@ -32,7 +31,6 @@ namespace SourceGit.ViewModels
_repo = repo;
Branch = branch;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public override Task<bool> Sure()
@ -76,9 +74,9 @@ namespace SourceGit.ViewModels
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPopStash)

View file

@ -17,8 +17,7 @@ namespace SourceGit.ViewModels
public bool IsRecurseSubmoduleVisible
{
get;
private set;
get => _repo.Submodules.Count > 0;
}
public bool RecurseSubmodules
@ -32,7 +31,6 @@ namespace SourceGit.ViewModels
_repo = repo;
Commit = commit;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public override Task<bool> Sure()
@ -76,9 +74,9 @@ namespace SourceGit.ViewModels
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPop)

View file

@ -140,9 +140,9 @@ namespace SourceGit.ViewModels
if (InitAndUpdateSubmodules)
{
var submodules = new Commands.QuerySubmodules(path).Result();
var submodules = new Commands.QueryUpdatableSubmodules(path).Result();
if (submodules.Count > 0)
new Commands.Submodule(path).Use(log).Update(submodules, true, true, false);
new Commands.Submodule(path).Use(log).Update(submodules, true, true);
}
log.Complete();

View file

@ -15,7 +15,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public partial class CommitDetail : ObservableObject
public partial class CommitDetail : ObservableObject, IDisposable
{
public int ActivePageIndex
{
@ -137,7 +137,7 @@ namespace SourceGit.ViewModels
WebLinks = Models.CommitLink.Get(repo.Remotes);
}
public void Cleanup()
public void Dispose()
{
_repo = null;
_commit = null;
@ -149,6 +149,7 @@ namespace SourceGit.ViewModels
_diffContext = null;
_viewRevisionFileContent = null;
_cancellationSource = null;
_requestingRevisionFiles = false;
_revisionFiles = null;
_revisionFileSearchSuggestion = null;
}
@ -335,7 +336,7 @@ namespace SourceGit.ViewModels
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var baseRevision = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];
var baseRevision = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0];
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
@ -546,6 +547,7 @@ namespace SourceGit.ViewModels
private void Refresh()
{
_changes = null;
_requestingRevisionFiles = false;
_revisionFiles = null;
SignInfo = null;
@ -593,7 +595,7 @@ namespace SourceGit.ViewModels
Task.Run(() =>
{
var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];
var parent = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0];
var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token };
var changes = cmd.Result();
var visible = changes;
@ -812,16 +814,22 @@ namespace SourceGit.ViewModels
{
if (_revisionFiles == null)
{
if (_requestingRevisionFiles)
return;
var sha = Commit.SHA;
_requestingRevisionFiles = true;
Task.Run(() =>
{
var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result();
Dispatcher.UIThread.Invoke(() =>
{
if (sha == Commit.SHA)
if (sha == Commit.SHA && _requestingRevisionFiles)
{
_revisionFiles = files;
_requestingRevisionFiles = false;
if (!string.IsNullOrEmpty(_revisionFileSearchFilter))
CalcRevisionFileSearchSuggestion();
}
@ -907,6 +915,7 @@ namespace SourceGit.ViewModels
private DiffContext _diffContext = null;
private object _viewRevisionFileContent = null;
private CancellationTokenSource _cancellationSource = null;
private bool _requestingRevisionFiles = false;
private List<string> _revisionFiles = null;
private string _revisionFileSearchFilter = string.Empty;
private List<string> _revisionFileSearchSuggestion = null;

View file

@ -1,4 +1,6 @@
namespace SourceGit.ViewModels
using System;
namespace SourceGit.ViewModels
{
public class ConflictSourceBranch
{
@ -46,7 +48,8 @@
_wc = wc;
_change = change;
IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).Result();
var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null;
IsResolved = !isSubmodule && new Commands.IsConflictResolved(repo.FullPath, change).Result();
var context = wc.InProgressContext;
if (context is CherryPickInProgress cherryPick)

View file

@ -43,10 +43,19 @@ namespace SourceGit.ViewModels
get => _repo.IsBare;
}
public bool AllowOverwrite
{
get => _allowOverwrite;
set
{
if (SetProperty(ref _allowOverwrite, value))
ValidateProperty(_name, nameof(Name));
}
}
public bool IsRecurseSubmoduleVisible
{
get;
private set;
get => _repo.Submodules.Count > 0;
}
public bool RecurseSubmodules
@ -67,7 +76,6 @@ namespace SourceGit.ViewModels
BasedOn = branch;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public CreateBranch(Repository repo, Models.Commit commit)
@ -77,7 +85,6 @@ namespace SourceGit.ViewModels
BasedOn = commit;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public CreateBranch(Repository repo, Models.Tag tag)
@ -87,23 +94,28 @@ namespace SourceGit.ViewModels
BasedOn = tag;
DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
}
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
{
var creator = ctx.ObjectInstance as CreateBranch;
if (creator == null)
return new ValidationResult("Missing runtime context to create branch!");
var fixedName = creator.FixName(name);
foreach (var b in creator._repo.Branches)
if (ctx.ObjectInstance is CreateBranch creator)
{
if (b.FriendlyName == fixedName)
return new ValidationResult("A branch with same name already exists!");
}
if (!creator._allowOverwrite)
{
var fixedName = creator.FixName(name);
foreach (var b in creator._repo.Branches)
{
if (b.FriendlyName == fixedName)
return new ValidationResult("A branch with same name already exists!");
}
}
return ValidationResult.Success;
return ValidationResult.Success;
}
else
{
return new ValidationResult("Missing runtime context to create branch!");
}
}
public override Task<bool> Sure()
@ -123,7 +135,7 @@ namespace SourceGit.ViewModels
var needPopStash = false;
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true, _allowOverwrite);
}
else
{
@ -141,16 +153,16 @@ namespace SourceGit.ViewModels
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false);
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false, _allowOverwrite);
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPopStash)
@ -159,7 +171,7 @@ namespace SourceGit.ViewModels
}
else
{
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, log);
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
}
log.Complete();
@ -205,5 +217,6 @@ namespace SourceGit.ViewModels
private readonly Repository _repo = null;
private string _name = null;
private readonly string _baseOnRevision = null;
private bool _allowOverwrite = false;
}
}

View file

@ -0,0 +1,45 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class DeinitSubmodule : Popup
{
public string Submodule
{
get;
private set;
}
public bool Force
{
get;
set;
}
public DeinitSubmodule(Repository repo, string submodule)
{
_repo = repo;
Submodule = submodule;
Force = false;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "De-initialize Submodule";
var log = _repo.CreateLog("De-initialize Submodule");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Deinit(Submodule, false);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private Repository _repo;
}
}

View file

@ -36,13 +36,17 @@ namespace SourceGit.ViewModels
_repo.SetWatcherEnabled(false);
ProgressDescription = "Run custom action ...";
var log = _repo.CreateLog(CustomAction.Name);
Use(log);
return Task.Run(() =>
{
if (CustomAction.WaitForExit)
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, output => CallUIThread(() => ProgressDescription = output));
Commands.ExecuteCustomAction.RunAndWait(_repo.FullPath, CustomAction.Executable, _args, log);
else
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});

View file

@ -1,47 +0,0 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class FastForwardWithoutCheckout : Popup
{
public Models.Branch Local
{
get;
}
public Models.Branch To
{
get;
}
public FastForwardWithoutCheckout(Repository repo, Models.Branch local, Models.Branch upstream)
{
_repo = repo;
Local = local;
To = upstream;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fast-Forward ...";
var log = _repo.CreateLog("Fast-Forward (No checkout)");
Use(log);
return Task.Run(() =>
{
new Commands.UpdateRef(_repo.FullPath, Local.FullName, To.FullName).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.NavigateToCommit(To.Head);
_repo.SetWatcherEnabled(true);
});
return true;
});
}
private readonly Repository _repo = null;
}
}

View file

@ -80,9 +80,16 @@ namespace SourceGit.ViewModels
log.Complete();
var upstream = _repo.CurrentBranch?.Upstream;
var upstreamHead = string.Empty;
if (!string.IsNullOrEmpty(upstream))
upstreamHead = new Commands.QueryRevisionByRefName(_repo.FullPath, upstream.Substring(13)).Result();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.Upstream);
if (!string.IsNullOrEmpty(upstreamHead))
_repo.NavigateToCommitDelayed(upstreamHead);
_repo.MarkFetched();
_repo.SetWatcherEnabled(true);
});

View file

@ -33,11 +33,14 @@ namespace SourceGit.ViewModels
{
new Commands.Fetch(_repo.FullPath, Local, Upstream).Use(log).Exec();
log.Complete();
var changedLocalBranchHead = new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).Result();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(Upstream.FullName);
_repo.NavigateToCommitDelayed(changedLocalBranchHead);
_repo.SetWatcherEnabled(true);
});
return true;
});
}

View file

@ -9,9 +9,11 @@ namespace SourceGit.ViewModels
get;
}
public bool IsFeature => _type == "feature";
public bool IsRelease => _type == "release";
public bool IsHotfix => _type == "hotfix";
public Models.GitFlowBranchType Type
{
get;
private set;
}
public bool Squash
{
@ -31,27 +33,27 @@ namespace SourceGit.ViewModels
set;
} = false;
public GitFlowFinish(Repository repo, Models.Branch branch, string type, string prefix)
public GitFlowFinish(Repository repo, Models.Branch branch, Models.GitFlowBranchType type)
{
_repo = repo;
_type = type;
_prefix = prefix;
Branch = branch;
Type = type;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Git Flow - Finish {Branch.Name} ...";
var name = Branch.Name.StartsWith(_prefix) ? Branch.Name.Substring(_prefix.Length) : Branch.Name;
ProgressDescription = $"Git Flow - finishing {_type} {name} ...";
var log = _repo.CreateLog("Gitflow - Finish");
var log = _repo.CreateLog("GitFlow - Finish");
Use(log);
var prefix = _repo.GitFlow.GetPrefix(Type);
var name = Branch.Name.StartsWith(prefix) ? Branch.Name.Substring(prefix.Length) : Branch.Name;
return Task.Run(() =>
{
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, Squash, AutoPush, KeepBranch, log);
var succ = Commands.GitFlow.Finish(_repo.FullPath, Type, name, Squash, AutoPush, KeepBranch, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
@ -59,7 +61,5 @@ namespace SourceGit.ViewModels
}
private readonly Repository _repo;
private readonly string _type;
private readonly string _prefix;
}
}

View file

@ -5,6 +5,18 @@ namespace SourceGit.ViewModels
{
public class GitFlowStart : Popup
{
public Models.GitFlowBranchType Type
{
get;
private set;
}
public string Prefix
{
get;
private set;
}
[Required(ErrorMessage = "Name is required!!!")]
[RegularExpression(@"^[\w\-/\.#]+$", ErrorMessage = "Bad branch name format!")]
[CustomValidation(typeof(GitFlowStart), nameof(ValidateBranchName))]
@ -14,27 +26,19 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _name, value, true);
}
public string Prefix
{
get => _prefix;
}
public bool IsFeature => _type == "feature";
public bool IsRelease => _type == "release";
public bool IsHotfix => _type == "hotfix";
public GitFlowStart(Repository repo, string type)
public GitFlowStart(Repository repo, Models.GitFlowBranchType type)
{
_repo = repo;
_type = type;
_prefix = Commands.GitFlow.GetPrefix(repo.FullPath, type);
Type = type;
Prefix = _repo.GitFlow.GetPrefix(type);
}
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
{
if (ctx.ObjectInstance is GitFlowStart starter)
{
var check = $"{starter._prefix}{name}";
var check = $"{starter.Prefix}{name}";
foreach (var b in starter._repo.Branches)
{
if (b.FriendlyName == check)
@ -48,14 +52,14 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Git Flow - starting {_type} {_name} ...";
ProgressDescription = $"Git Flow - Start {Prefix}{_name} ...";
var log = _repo.CreateLog("Gitflow - Start");
var log = _repo.CreateLog("GitFlow - Start");
Use(log);
return Task.Run(() =>
{
var succ = Commands.GitFlow.Start(_repo.FullPath, _type, _name, log);
var succ = Commands.GitFlow.Start(_repo.FullPath, Type, _name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
@ -63,8 +67,6 @@ namespace SourceGit.ViewModels
}
private readonly Repository _repo;
private readonly string _type;
private readonly string _prefix;
private string _name = null;
}
}

View file

@ -12,7 +12,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class Histories : ObservableObject
public class Histories : ObservableObject, IDisposable
{
public Repository Repo
{
@ -57,7 +57,7 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _navigationId, value);
}
public object DetailContext
public IDisposable DetailContext
{
get => _detailContext;
set => SetProperty(ref _detailContext, value);
@ -98,23 +98,13 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public void Cleanup()
public void Dispose()
{
Commits = new List<Models.Commit>();
Commits = [];
_repo = null;
_graph = null;
_autoSelectedCommit = null;
if (_detailContext is CommitDetail cd)
{
cd.Cleanup();
}
else if (_detailContext is RevisionCompare rc)
{
rc.Cleanup();
}
_detailContext?.Dispose();
_detailContext = null;
}
@ -220,7 +210,7 @@ namespace SourceGit.ViewModels
else
{
_repo.SelectedSearchedCommit = null;
DetailContext = commits.Count;
DetailContext = new Models.Count(commits.Count);
}
}
@ -985,8 +975,8 @@ namespace SourceGit.ViewModels
if (!_repo.IsBare)
{
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name);
if (detect.IsGitFlowBranch)
var type = _repo.GetGitFlowType(current);
if (type != Models.GitFlowBranchType.None)
{
var finish = new MenuItem();
finish.Header = App.Text("BranchCM.Finish", current.Name);
@ -994,7 +984,7 @@ namespace SourceGit.ViewModels
finish.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix));
_repo.ShowPopup(new GitFlowFinish(_repo, current, type));
e.Handled = true;
};
submenu.Items.Add(finish);
@ -1073,8 +1063,8 @@ namespace SourceGit.ViewModels
if (!_repo.IsBare)
{
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name);
if (detect.IsGitFlowBranch)
var type = _repo.GetGitFlowType(branch);
if (type != Models.GitFlowBranchType.None)
{
var finish = new MenuItem();
finish.Header = App.Text("BranchCM.Finish", branch.Name);
@ -1082,7 +1072,7 @@ namespace SourceGit.ViewModels
finish.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix));
_repo.ShowPopup(new GitFlowFinish(_repo, branch, type));
e.Handled = true;
};
submenu.Items.Add(finish);
@ -1256,7 +1246,7 @@ namespace SourceGit.ViewModels
private Models.CommitGraph _graph = null;
private Models.Commit _autoSelectedCommit = null;
private long _navigationId = 0;
private object _detailContext = null;
private IDisposable _detailContext = null;
private Models.Bisect _bisect = null;

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@ -109,9 +110,35 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
var succ = Commands.GitFlow.Init(
var succ = false;
var current = _repo.CurrentBranch;
var masterBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_master, StringComparison.Ordinal));
if (masterBranch == null)
{
succ = Commands.Branch.Create(_repo.FullPath, _master, current.Head, true, log);
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
}
var developBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_develop, StringComparison.Ordinal));
if (developBranch == null)
{
succ = Commands.Branch.Create(_repo.FullPath, _develop, current.Head, true, log);
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
}
succ = Commands.GitFlow.Init(
_repo.FullPath,
_repo.Branches,
_master,
_develop,
_featurePrefix,
@ -121,7 +148,23 @@ namespace SourceGit.ViewModels
log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
CallUIThread(() =>
{
if (succ)
{
var gitflow = new Models.GitFlow();
gitflow.Master = _master;
gitflow.Develop = _develop;
gitflow.FeaturePrefix = _featurePrefix;
gitflow.ReleasePrefix = _releasePrefix;
gitflow.HotfixPrefix = _hotfixPrefix;
_repo.GitFlow = gitflow;
}
_repo.SetWatcherEnabled(true);
});
return succ;
});
}

View file

@ -19,10 +19,23 @@ namespace SourceGit.ViewModels
private set;
}
public bool CanSquashOrFixup
{
get => _canSquashOrFixup;
set
{
if (SetProperty(ref _canSquashOrFixup, value))
{
if (_action == Models.InteractiveRebaseAction.Squash || _action == Models.InteractiveRebaseAction.Fixup)
Action = Models.InteractiveRebaseAction.Pick;
}
}
}
public Models.InteractiveRebaseAction Action
{
get => _action;
private set => SetProperty(ref _action, value);
set => SetProperty(ref _action, value);
}
public string Subject
@ -48,20 +61,17 @@ namespace SourceGit.ViewModels
}
}
public InteractiveRebaseItem(Models.Commit c, string message)
public InteractiveRebaseItem(Models.Commit c, string message, bool canSquashOrFixup)
{
Commit = c;
FullMessage = message;
}
public void SetAction(object param)
{
Action = (Models.InteractiveRebaseAction)param;
CanSquashOrFixup = canSquashOrFixup;
}
private Models.InteractiveRebaseAction _action = Models.InteractiveRebaseAction.Pick;
private string _subject;
private string _fullMessage;
private bool _canSquashOrFixup = true;
}
public class InteractiveRebase : ObservableObject
@ -88,7 +98,7 @@ namespace SourceGit.ViewModels
{
get;
private set;
} = new AvaloniaList<InteractiveRebaseItem>();
} = [];
public InteractiveRebaseItem SelectedItem
{
@ -121,8 +131,11 @@ namespace SourceGit.ViewModels
var commits = new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).Result();
var list = new List<InteractiveRebaseItem>();
foreach (var c in commits)
list.Add(new InteractiveRebaseItem(c.Commit, c.Message));
for (var i = 0; i < commits.Count; i++)
{
var c = commits[i];
list.Add(new InteractiveRebaseItem(c.Commit, c.Message, i < commits.Count - 1));
}
Dispatcher.UIThread.Invoke(() =>
{
@ -141,6 +154,7 @@ namespace SourceGit.ViewModels
Items.RemoveAt(idx - 1);
Items.Insert(idx, prev);
SelectedItem = item;
UpdateItems();
}
}
@ -153,9 +167,22 @@ namespace SourceGit.ViewModels
Items.RemoveAt(idx + 1);
Items.Insert(idx, next);
SelectedItem = item;
UpdateItems();
}
}
public void ChangeAction(InteractiveRebaseItem item, Models.InteractiveRebaseAction action)
{
if (!item.CanSquashOrFixup)
{
if (action == Models.InteractiveRebaseAction.Squash || action == Models.InteractiveRebaseAction.Fixup)
return;
}
item.Action = action;
UpdateItems();
}
public Task<bool> Start()
{
_repo.SetWatcherEnabled(false);
@ -186,6 +213,27 @@ namespace SourceGit.ViewModels
});
}
private void UpdateItems()
{
if (Items.Count == 0)
return;
var hasValidParent = false;
for (var i = Items.Count - 1; i >= 0; i--)
{
var item = Items[i];
if (hasValidParent)
{
item.CanSquashOrFixup = true;
}
else
{
item.CanSquashOrFixup = false;
hasValidParent = item.Action != Models.InteractiveRebaseAction.Drop;
}
}
}
private Repository _repo = null;
private bool _isLoading = false;
private InteractiveRebaseItem _selectedItem = null;

View file

@ -64,9 +64,10 @@ namespace SourceGit.ViewModels
new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg).Use(log).Exec();
log.Complete();
var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.FullName);
_repo.NavigateToCommitDelayed(head);
_repo.SetWatcherEnabled(true);
});
return true;

View file

@ -48,7 +48,14 @@ namespace SourceGit.ViewModels
protected void Use(CommandLog log)
{
log.Register(newline => ProgressDescription = newline.Trim());
log.Register(SetDescription);
}
private void SetDescription(string data)
{
var desc = data.Trim();
if (!string.IsNullOrEmpty(desc))
ProgressDescription = desc;
}
private bool _inProgress = false;

View file

@ -50,16 +50,15 @@ namespace SourceGit.ViewModels
set => _repo.Settings.PreferRebaseInsteadOfMerge = value;
}
public bool FetchAllBranches
public bool IsRecurseSubmoduleVisible
{
get => _repo.Settings.FetchAllBranchesOnPull;
set => _repo.Settings.FetchAllBranchesOnPull = value;
get => _repo.Submodules.Count > 0;
}
public bool NoTags
public bool RecurseSubmodules
{
get => _repo.Settings.FetchWithoutTagsOnPull;
set => _repo.Settings.FetchWithoutTagsOnPull = value;
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public Pull(Repository repo, Models.Branch specifiedRemoteBranch)
@ -119,6 +118,7 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Pull");
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
@ -143,47 +143,31 @@ namespace SourceGit.ViewModels
}
}
bool rs;
if (FetchAllBranches)
bool rs = new Commands.Pull(
_repo.FullPath,
_selectedRemote.Name,
!string.IsNullOrEmpty(_current.Upstream) && _current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name,
UseRebase).Use(log).Exec();
if (rs)
{
rs = new Commands.Fetch(
_repo.FullPath,
_selectedRemote.Name,
NoTags,
false).Use(log).Exec();
if (!rs)
if (updateSubmodules)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
_repo.MarkFetched();
// Use merge/rebase instead of pull as fetch is done manually.
if (UseRebase)
rs = new Commands.Rebase(_repo.FullPath, _selectedBranch.FriendlyName, false).Use(log).Exec();
else
rs = new Commands.Merge(_repo.FullPath, _selectedBranch.FriendlyName, "").Use(log).Exec();
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
else
{
rs = new Commands.Pull(
_repo.FullPath,
_selectedRemote.Name,
_selectedBranch.Name,
UseRebase,
NoTags).Use(log).Exec();
}
if (rs && needPopStash)
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
log.Complete();
var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result();
CallUIThread(() =>
{
_repo.NavigateToBranchDelayed(_repo.CurrentBranch?.FullName);
_repo.NavigateToCommitDelayed(head);
_repo.SetWatcherEnabled(true);
});

View file

@ -51,6 +51,12 @@ namespace SourceGit.ViewModels
get => _settings;
}
public Models.GitFlow GitFlow
{
get;
set;
} = new Models.GitFlow();
public Models.FilterMode HistoriesFilterMode
{
get => _historiesFilterMode;
@ -294,6 +300,7 @@ namespace SourceGit.ViewModels
SelectedSearchedCommit = null;
SearchCommitFilter = string.Empty;
MatchedFilesForSearching = null;
_requestingWorktreeFiles = false;
_worktreeFiles = null;
}
}
@ -545,9 +552,9 @@ namespace SourceGit.ViewModels
_historiesFilterMode = Models.FilterMode.None;
_watcher?.Dispose();
_histories.Cleanup();
_workingCopy.Cleanup();
_stashesPage.Cleanup();
_histories.Dispose();
_workingCopy.Dispose();
_stashesPage.Dispose();
_watcher = null;
_histories = null;
@ -568,6 +575,7 @@ namespace SourceGit.ViewModels
_searchedCommits.Clear();
_selectedSearchedCommit = null;
_requestingWorktreeFiles = false;
_worktreeFiles = null;
_matchedFilesForSearching = null;
}
@ -593,6 +601,28 @@ namespace SourceGit.ViewModels
GetOwnerPage()?.StartPopup(popup);
}
public bool IsGitFlowEnabled()
{
return GitFlow is { IsValid: true } &&
_branches.Find(x => x.IsLocal && x.Name.Equals(GitFlow.Master, StringComparison.Ordinal)) != null &&
_branches.Find(x => x.IsLocal && x.Name.Equals(GitFlow.Develop, StringComparison.Ordinal)) != null;
}
public Models.GitFlowBranchType GetGitFlowType(Models.Branch b)
{
if (!IsGitFlowEnabled())
return Models.GitFlowBranchType.None;
var name = b.Name;
if (name.StartsWith(GitFlow.FeaturePrefix, StringComparison.Ordinal))
return Models.GitFlowBranchType.Feature;
if (name.StartsWith(GitFlow.ReleasePrefix, StringComparison.Ordinal))
return Models.GitFlowBranchType.Release;
if (name.StartsWith(GitFlow.HotfixPrefix, StringComparison.Ordinal))
return Models.GitFlowBranchType.Hotfix;
return Models.GitFlowBranchType.None;
}
public CommandLog CreateLog(string name)
{
var log = new CommandLog(name);
@ -602,19 +632,30 @@ namespace SourceGit.ViewModels
public void RefreshAll()
{
Task.Run(() =>
{
var allowedSignersFile = new Commands.Config(_fullpath).Get("gpg.ssh.allowedSignersFile");
_hasAllowedSignersFile = !string.IsNullOrEmpty(allowedSignersFile);
});
Task.Run(RefreshCommits);
Task.Run(RefreshBranches);
Task.Run(RefreshTags);
Task.Run(RefreshCommits);
Task.Run(RefreshSubmodules);
Task.Run(RefreshWorktrees);
Task.Run(RefreshWorkingCopyChanges);
Task.Run(RefreshStashes);
Task.Run(() =>
{
var config = new Commands.Config(_fullpath).ListAll();
_hasAllowedSignersFile = config.TryGetValue("gpg.ssh.allowedSignersFile", out var allowedSignersFile) && !string.IsNullOrEmpty(allowedSignersFile);
if (config.TryGetValue("gitflow.branch.master", out var masterName))
GitFlow.Master = masterName;
if (config.TryGetValue("gitflow.branch.develop", out var developName))
GitFlow.Develop = developName;
if (config.TryGetValue("gitflow.prefix.feature", out var featurePrefix))
GitFlow.FeaturePrefix = featurePrefix;
if (config.TryGetValue("gitflow.prefix.release", out var releasePrefix))
GitFlow.ReleasePrefix = releasePrefix;
if (config.TryGetValue("gitflow.prefix.hotfix", out var hotfixPrefix))
GitFlow.HotfixPrefix = hotfixPrefix;
});
}
public ContextMenu CreateContextMenuForExternalTools()
@ -881,17 +922,17 @@ namespace SourceGit.ViewModels
}
}
public void NavigateToCommitDelayed(string sha)
{
_navigateToCommitDelayed = sha;
}
public void NavigateToCurrentHead()
{
if (_currentBranch != null)
NavigateToCommit(_currentBranch.Head);
}
public void NavigateToBranchDelayed(string branch)
{
_navigateToBranchDelayed = branch;
}
public void ClearHistoriesFilter()
{
_settings.HistoriesFilters.Clear();
@ -1052,6 +1093,13 @@ namespace SourceGit.ViewModels
});
}
public bool MayHaveSubmodules()
{
var modulesFile = Path.Combine(_fullpath, ".gitmodules");
var info = new FileInfo(modulesFile);
return info.Exists && info.Length > 20;
}
public void RefreshBranches()
{
var branches = new Commands.QueryBranches(_fullpath).Result(out var localBranchesCount);
@ -1141,27 +1189,64 @@ namespace SourceGit.ViewModels
BisectState = _histories.UpdateBisectInfo();
if (!string.IsNullOrEmpty(_navigateToBranchDelayed))
{
var branch = _branches.Find(x => x.FullName == _navigateToBranchDelayed);
if (branch != null)
NavigateToCommit(branch.Head);
}
if (!string.IsNullOrEmpty(_navigateToCommitDelayed))
NavigateToCommit(_navigateToCommitDelayed);
}
_navigateToBranchDelayed = string.Empty;
_navigateToCommitDelayed = string.Empty;
});
}
public void RefreshSubmodules()
{
if (!MayHaveSubmodules())
{
if (_submodules.Count > 0)
{
Dispatcher.UIThread.Invoke(() =>
{
Submodules = [];
VisibleSubmodules = BuildVisibleSubmodules();
});
}
return;
}
var submodules = new Commands.QuerySubmodules(_fullpath).Result();
_watcher?.SetSubmodules(submodules);
Dispatcher.UIThread.Invoke(() =>
{
Submodules = submodules;
VisibleSubmodules = BuildVisibleSubmodules();
bool hasChanged = _submodules.Count != submodules.Count;
if (!hasChanged)
{
var old = new Dictionary<string, Models.Submodule>();
foreach (var module in _submodules)
old.Add(module.Path, module);
foreach (var module in submodules)
{
if (!old.TryGetValue(module.Path, out var exist))
{
hasChanged = true;
break;
}
hasChanged = !exist.SHA.Equals(module.SHA, StringComparison.Ordinal) ||
!exist.URL.Equals(module.URL, StringComparison.Ordinal) ||
exist.Status != module.Status;
if (hasChanged)
break;
}
}
if (hasChanged)
{
Submodules = submodules;
VisibleSubmodules = BuildVisibleSubmodules();
}
});
}
@ -1375,8 +1460,7 @@ namespace SourceGit.ViewModels
var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
var isGitFlowEnabled = Commands.GitFlow.IsEnabled(_fullpath, _branches);
if (isGitFlowEnabled)
if (IsGitFlowEnabled())
{
var startFeature = new MenuItem();
startFeature.Header = App.Text("GitFlow.StartFeature");
@ -1384,7 +1468,7 @@ namespace SourceGit.ViewModels
startFeature.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new GitFlowStart(this, "feature"));
ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Feature));
e.Handled = true;
};
@ -1394,7 +1478,7 @@ namespace SourceGit.ViewModels
startRelease.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new GitFlowStart(this, "release"));
ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Release));
e.Handled = true;
};
@ -1404,7 +1488,7 @@ namespace SourceGit.ViewModels
startHotfix.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new GitFlowStart(this, "hotfix"));
ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Hotfix));
e.Handled = true;
};
@ -1419,8 +1503,15 @@ namespace SourceGit.ViewModels
init.Icon = App.CreateMenuIcon("Icons.Init");
init.Click += (_, e) =>
{
if (CanCreatePopup())
if (_currentBranch == null)
{
App.RaiseException(_fullpath, "Git flow init failed: No branch found!!!");
}
else if (CanCreatePopup())
{
ShowPopup(new InitGitFlow(this));
}
e.Handled = true;
};
menu.Items.Add(init);
@ -1770,9 +1861,25 @@ namespace SourceGit.ViewModels
fastForward.Click += (_, e) =>
{
if (CanCreatePopup())
ShowAndStartPopup(new FastForwardWithoutCheckout(this, branch, upstream));
ShowAndStartPopup(new ResetWithoutCheckout(this, branch, upstream));
e.Handled = true;
};
menu.Items.Add(fastForward);
var selectedCommit = (_histories?.DetailContext as CommitDetail)?.Commit;
if (selectedCommit != null && !selectedCommit.SHA.Equals(branch.Head, StringComparison.Ordinal))
{
var move = new MenuItem();
move.Header = App.Text("BranchCM.ResetToSelectedCommit", branch.Name, selectedCommit.SHA.Substring(0, 10));
move.Icon = App.CreateMenuIcon("Icons.Reset");
move.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new ResetWithoutCheckout(this, branch, selectedCommit));
e.Handled = true;
};
menu.Items.Add(move);
}
var fetchInto = new MenuItem();
fetchInto.Header = App.Text("BranchCM.FetchInto", upstream.FriendlyName, branch.Name);
@ -1785,7 +1892,6 @@ namespace SourceGit.ViewModels
e.Handled = true;
};
menu.Items.Add(fastForward);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(fetchInto);
}
@ -1850,8 +1956,8 @@ namespace SourceGit.ViewModels
if (!IsBare)
{
var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name);
if (detect.IsGitFlowBranch)
var type = GetGitFlowType(branch);
if (type != Models.GitFlowBranchType.None)
{
var finish = new MenuItem();
finish.Header = App.Text("BranchCM.Finish", branch.Name);
@ -1859,7 +1965,7 @@ namespace SourceGit.ViewModels
finish.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix));
ShowPopup(new GitFlowFinish(this, branch, type));
e.Handled = true;
};
menu.Items.Add(new MenuItem() { Header = "-" });
@ -2370,12 +2476,14 @@ namespace SourceGit.ViewModels
ev.Handled = true;
};
var copy = new MenuItem();
copy.Header = App.Text("Submodule.CopyPath");
copy.Icon = App.CreateMenuIcon("Icons.Copy");
copy.Click += (_, ev) =>
var deinit = new MenuItem();
deinit.Header = App.Text("Submodule.Deinit");
deinit.Icon = App.CreateMenuIcon("Icons.Undo");
deinit.IsEnabled = submodule.Status != Models.SubmoduleStatus.NotInited;
deinit.Click += (_, ev) =>
{
App.CopyText(submodule.Path);
if (CanCreatePopup())
ShowPopup(new DeinitSubmodule(this, submodule.Path));
ev.Handled = true;
};
@ -2389,10 +2497,22 @@ namespace SourceGit.ViewModels
ev.Handled = true;
};
var copy = new MenuItem();
copy.Header = App.Text("Submodule.CopyPath");
copy.Icon = App.CreateMenuIcon("Icons.Copy");
copy.Click += (_, ev) =>
{
App.CopyText(submodule.Path);
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(open);
menu.Items.Add(copy);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(deinit);
menu.Items.Add(rm);
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(copy);
return menu;
}
@ -2683,19 +2803,27 @@ namespace SourceGit.ViewModels
{
if (!IsSearchingCommitsByFilePath())
{
_requestingWorktreeFiles = false;
_worktreeFiles = null;
MatchedFilesForSearching = null;
GC.Collect();
return;
}
if (_requestingWorktreeFiles)
return;
_requestingWorktreeFiles = true;
Task.Run(() =>
{
_worktreeFiles = new Commands.QueryRevisionFileNames(_fullpath, "HEAD").Result();
Dispatcher.UIThread.Invoke(() =>
{
if (IsSearchingCommitsByFilePath())
if (IsSearchingCommitsByFilePath() && _requestingWorktreeFiles)
CalcMatchedFilesForSearching();
_requestingWorktreeFiles = false;
});
});
}
@ -2781,6 +2909,7 @@ namespace SourceGit.ViewModels
private string _searchCommitFilter = string.Empty;
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
private Models.Commit _selectedSearchedCommit = null;
private bool _requestingWorktreeFiles = false;
private List<string> _worktreeFiles = null;
private List<string> _matchedFilesForSearching = null;
@ -2804,6 +2933,6 @@ namespace SourceGit.ViewModels
private Models.BisectState _bisectState = Models.BisectState.None;
private bool _isBisectCommandRunning = false;
private string _navigateToBranchDelayed = string.Empty;
private string _navigateToCommitDelayed = string.Empty;
}
}

View file

@ -0,0 +1,53 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class ResetWithoutCheckout : Popup
{
public Models.Branch Target
{
get;
}
public object To
{
get;
}
public ResetWithoutCheckout(Repository repo, Models.Branch target, Models.Branch to)
{
_repo = repo;
_revision = to.Head;
Target = target;
To = to;
}
public ResetWithoutCheckout(Repository repo, Models.Branch target, Models.Commit to)
{
_repo = repo;
_revision = to.SHA;
Target = target;
To = to;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Reset {Target.Name} to {_revision} ...";
var log = _repo.CreateLog($"Reset '{Target.Name}' to '{_revision}'");
Use(log);
return Task.Run(() =>
{
var succ = Commands.Branch.Create(_repo.FullPath, Target.Name, _revision, true, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private readonly Repository _repo = null;
private readonly string _revision = string.Empty;
}
}

View file

@ -10,7 +10,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class RevisionCompare : ObservableObject
public class RevisionCompare : ObservableObject, IDisposable
{
public object StartPoint
{
@ -83,7 +83,7 @@ namespace SourceGit.ViewModels
Task.Run(Refresh);
}
public void Cleanup()
public void Dispose()
{
_repo = null;
_startPoint = null;

View file

@ -11,7 +11,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class StashesPage : ObservableObject
public class StashesPage : ObservableObject, IDisposable
{
public List<Models.Stash> Stashes
{
@ -69,7 +69,7 @@ namespace SourceGit.ViewModels
changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
if (value.Parents.Count == 3)
{
var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result();
var untracked = new Commands.CompareRevisions(_repo.FullPath, Models.Commit.EmptyTreeSHA1, value.Parents[2]).Result();
var needSort = changes.Count > 0;
foreach (var c in untracked)
@ -107,7 +107,7 @@ namespace SourceGit.ViewModels
if (value == null)
DiffContext = null;
else if (value.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], value), _diffContext);
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(Models.Commit.EmptyTreeSHA1, _selectedStash.Parents[2], value), _diffContext);
else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext);
}
@ -125,14 +125,13 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public void Cleanup()
public void Dispose()
{
_stashes?.Clear();
_changes?.Clear();
_repo = null;
if (_stashes != null)
_stashes.Clear();
_selectedStash = null;
if (_changes != null)
_changes.Clear();
_selectedChange = null;
_diffContext = null;
}
@ -183,7 +182,7 @@ namespace SourceGit.ViewModels
foreach (var c in _changes)
{
if (c.Index == Models.ChangeState.Added && _selectedStash.Parents.Count == 3)
opts.Add(new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], c));
opts.Add(new Models.DiffOption(Models.Commit.EmptyTreeSHA1, _selectedStash.Parents[2], c));
else
opts.Add(new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, c));
}

View file

@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
{
public class SubmoduleTreeNode : ObservableObject
{
public string FullPath { get; set; } = string.Empty;
public string FullPath { get; private set; } = string.Empty;
public int Depth { get; private set; } = 0;
public Models.Submodule Module { get; private set; } = null;
public List<SubmoduleTreeNode> Children { get; private set; } = [];

View file

@ -23,7 +23,7 @@ namespace SourceGit.ViewModels
public class TagTreeNode : ObservableObject
{
public string FullPath { get; set; }
public string FullPath { get; private set; }
public int Depth { get; private set; } = 0;
public Models.Tag Tag { get; private set; } = null;
public TagTreeNodeToolTip ToolTip { get; private set; } = null;

View file

@ -65,14 +65,9 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
foreach (var submodule in targets)
{
new Commands.Submodule(_repo.FullPath).Use(log).Update(
submodule,
EnableInit,
EnableRecursive,
EnableRemote);
}
new Commands.Submodule(_repo.FullPath)
.Use(log)
.Update(targets, EnableInit, EnableRecursive, EnableRemote);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));

View file

@ -11,7 +11,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class WorkingCopy : ObservableObject
public class WorkingCopy : ObservableObject, IDisposable
{
public bool IncludeUntracked
{
@ -210,7 +210,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public void Cleanup()
public void Dispose()
{
_repo = null;
_inProgressContext = null;
@ -244,7 +244,7 @@ namespace SourceGit.ViewModels
// Just force refresh selected changes.
Dispatcher.UIThread.Invoke(() =>
{
HasUnsolvedConflicts = _cached.Find(x => x.IsConflict) != null;
HasUnsolvedConflicts = _cached.Find(x => x.IsConflicted) != null;
UpdateDetail();
UpdateInProgressState();
@ -276,7 +276,7 @@ namespace SourceGit.ViewModels
if (c.WorkTree != Models.ChangeState.None)
{
unstaged.Add(c);
hasConflict |= c.IsConflict;
hasConflict |= c.IsConflicted;
}
}
@ -378,7 +378,7 @@ namespace SourceGit.ViewModels
foreach (var change in changes)
{
if (!change.IsConflict)
if (!change.IsConflicted)
continue;
if (change.WorkTree == Models.ChangeState.Deleted)
@ -420,7 +420,7 @@ namespace SourceGit.ViewModels
foreach (var change in changes)
{
if (!change.IsConflict)
if (!change.IsConflicted)
continue;
if (change.Index == Models.ChangeState.Deleted)
@ -547,17 +547,17 @@ namespace SourceGit.ViewModels
public void Commit()
{
DoCommit(false, false, false);
DoCommit(false, false);
}
public void CommitWithAutoStage()
{
DoCommit(true, false, false);
DoCommit(true, false);
}
public void CommitWithPush()
{
DoCommit(false, true, false);
DoCommit(false, true);
}
public ContextMenu CreateContextMenuForUnstagedChanges()
@ -594,7 +594,7 @@ namespace SourceGit.ViewModels
menu.Items.Add(openWith);
menu.Items.Add(new MenuItem() { Header = "-" });
if (change.IsConflict)
if (change.IsConflicted)
{
var useTheirs = new MenuItem();
useTheirs.Icon = App.CreateMenuIcon("Icons.Incoming");
@ -949,7 +949,7 @@ namespace SourceGit.ViewModels
var hasNonConflicts = false;
foreach (var change in _selectedUnstaged)
{
if (change.IsConflict)
if (change.IsConflicted)
hasConflicts = true;
else
hasNonConflicts = true;
@ -1528,14 +1528,13 @@ namespace SourceGit.ViewModels
if (_useAmend)
{
var head = new Commands.QuerySingleCommit(_repo.FullPath, "HEAD").Result();
return new Commands.QueryStagedChangesWithAmend(_repo.FullPath, head.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : $"{head.SHA}^").Result();
return new Commands.QueryStagedChangesWithAmend(_repo.FullPath, head.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : $"{head.SHA}^").Result();
}
var rs = new List<Models.Change>();
foreach (var c in _cached)
{
if (c.Index != Models.ChangeState.None &&
c.Index != Models.ChangeState.Untracked)
if (c.Index != Models.ChangeState.None)
rs.Add(c);
}
return rs;
@ -1681,7 +1680,7 @@ namespace SourceGit.ViewModels
if (change == null)
DetailContext = null;
else if (change.IsConflict && isUnstaged)
else if (change.IsConflicted)
DetailContext = new Conflict(_repo, this, change);
else
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
@ -1763,14 +1762,17 @@ namespace SourceGit.ViewModels
{
if (old.Count != cur.Count)
return true;
var oldSet = new HashSet<string>();
var oldMap = new Dictionary<string, Models.Change>();
foreach (var c in old)
oldSet.Add($"{c.Path}\n{c.WorkTree}\n{c.Index}");
oldMap.Add(c.Path, c);
foreach (var c in cur)
{
if (!oldSet.Contains($"{c.Path}\n{c.WorkTree}\n{c.Index}"))
if (!oldMap.TryGetValue(c.Path, out var o))
return true;
if (o.Index != c.Index || o.WorkTree != c.WorkTree)
return true;
}

View file

@ -296,8 +296,6 @@ namespace SourceGit.Views
TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeparatorMargin(this));
TextArea.Caret.PositionChanged += OnTextAreaCaretPositionChanged;
TextArea.LayoutUpdated += OnTextAreaLayoutUpdated;
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged;
TextArea.TextView.Margin = new Thickness(4, 0);
@ -341,8 +339,6 @@ namespace SourceGit.Views
TextArea.LeftMargins.Clear();
TextArea.Caret.PositionChanged -= OnTextAreaCaretPositionChanged;
TextArea.LayoutUpdated -= OnTextAreaLayoutUpdated;
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
TextArea.TextView.VisualLinesChanged -= OnTextViewVisualLinesChanged;
@ -392,42 +388,21 @@ namespace SourceGit.Views
InvalidateVisual();
}
private void OnTextAreaLayoutUpdated(object sender, EventArgs e)
{
if (TextArea.IsFocused)
InvalidateVisual();
}
private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e)
{
if (!TextArea.IsFocused && !string.IsNullOrEmpty(_highlight))
Focus();
}
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
{
var selected = SelectedText;
if (string.IsNullOrEmpty(selected))
return;
var copy = new MenuItem() { Header = App.Text("Copy") };
var copy = new MenuItem();
copy.Header = App.Text("Copy");
copy.Icon = App.CreateMenuIcon("Icons.Copy");
copy.Click += (_, ev) =>
{
App.CopyText(selected);
ev.Handled = true;
};
if (this.FindResource("Icons.Copy") is StreamGeometry geo)
{
copy.Icon = new Avalonia.Controls.Shapes.Path()
{
Width = 10,
Height = 10,
Stretch = Stretch.Fill,
Data = geo,
};
}
var menu = new ContextMenu();
menu.Items.Add(copy);
menu.Open(TextArea.TextView);
@ -445,6 +420,8 @@ namespace SourceGit.Views
break;
}
}
InvalidateVisual();
}
private TextMate.Installation _textMate = null;

View file

@ -30,7 +30,8 @@
<UserControl.DataTemplates>
<DataTemplate DataType="vm:ChangeCollectionAsTree">
<v:ChangeCollectionContainer ItemsSource="{Binding Rows}"
<v:ChangeCollectionContainer Focusable="True"
ItemsSource="{Binding Rows}"
SelectedItems="{Binding SelectedRows, Mode=TwoWay}"
SelectionMode="{Binding #ThisControl.SelectionMode}"
SelectionChanged="OnRowSelectionChanged">
@ -66,7 +67,8 @@
</DataTemplate>
<DataTemplate DataType="vm:ChangeCollectionAsGrid">
<v:ChangeCollectionContainer ItemsSource="{Binding Changes}"
<v:ChangeCollectionContainer Focusable="True"
ItemsSource="{Binding Changes}"
SelectedItems="{Binding SelectedChanges, Mode=TwoWay}"
SelectionMode="{Binding #ThisControl.SelectionMode}"
SelectionChanged="OnRowSelectionChanged">
@ -98,7 +100,8 @@
</DataTemplate>
<DataTemplate DataType="vm:ChangeCollectionAsList">
<v:ChangeCollectionContainer ItemsSource="{Binding Changes}"
<v:ChangeCollectionContainer Focusable="True"
ItemsSource="{Binding Changes}"
SelectedItems="{Binding SelectedChanges, Mode=TwoWay}"
SelectionMode="{Binding #ThisControl.SelectionMode}"
SelectionChanged="OnRowSelectionChanged">

View file

@ -145,6 +145,7 @@ namespace SourceGit.Views
removeCount++;
}
tree.Rows.RemoveRange(idx + 1, removeCount);
}
}
@ -209,6 +210,13 @@ namespace SourceGit.Views
return null;
}
public void TakeFocus()
{
var container = this.FindDescendantOfType<ChangeCollectionContainer>();
if (container is { IsFocused: false })
container.Focus();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);

View file

@ -48,21 +48,16 @@ namespace SourceGit.Views
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
},
new LinearGradientBrush
{
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(238, 160, 14), 0), new GradientStop(Color.FromRgb(228, 172, 67), 1) },
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
},
new LinearGradientBrush
{
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(47, 185, 47), 0), new GradientStop(Color.FromRgb(75, 189, 75), 1) },
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
},
Brushes.OrangeRed,
];
private static readonly string[] INDICATOR = ["?", "±", "T", "+", "", "➜", "❏", "U", "★"];
private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Unmerged", "Untracked"];
private static readonly string[] INDICATOR = ["?", "±", "T", "+", "", "➜", "❏", "★", "!"];
private static readonly string[] TIPS = ["Unknown", "Modified", "Type Changed", "Added", "Deleted", "Renamed", "Copied", "Untracked", "Conflict"];
public static readonly StyledProperty<bool> IsUnstagedChangeProperty =
AvaloniaProperty.Register<ChangeStatusIcon, bool>(nameof(IsUnstagedChange));
@ -93,16 +88,8 @@ namespace SourceGit.Views
string indicator;
if (IsUnstagedChange)
{
if (Change.IsConflict)
{
background = Brushes.OrangeRed;
indicator = "!";
}
else
{
background = BACKGROUNDS[(int)Change.WorkTree];
indicator = INDICATOR[(int)Change.WorkTree];
}
background = BACKGROUNDS[(int)Change.WorkTree];
indicator = INDICATOR[(int)Change.WorkTree];
}
else
{
@ -139,7 +126,7 @@ namespace SourceGit.Views
}
if (isUnstaged)
ToolTip.SetTip(this, c.IsConflict ? "Conflict" : TIPS[(int)c.WorkTree]);
ToolTip.SetTip(this, TIPS[(int)c.WorkTree]);
else
ToolTip.SetTip(this, TIPS[(int)c.Index]);

View file

@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CommitChanges"
x:DataType="vm:CommitDetail">
@ -14,7 +15,7 @@
<ColumnDefinition Width="*" MinWidth="100"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" RowDefinitions="26,*">
<Grid Grid.Column="0" RowDefinitions="26,*,26">
<!-- Search & Display Mode -->
<Grid Grid.Row="0" ColumnDefinitions="*,Auto">
<TextBox Grid.Column="0"
@ -52,6 +53,16 @@
AutoSelectFirstChange="True"
ContextRequested="OnChangeContextRequested"/>
</Border>
<!-- Summary -->
<Border Grid.Row="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1,0,1,1" Background="Transparent">
<TextBlock Margin="4,0,0,0"
Foreground="{DynamicResource Brush.FG2}"
HorizontalAlignment="Left" VerticalAlignment="Center">
<Run Text="{Binding Changes, Converter={x:Static c:ListConverters.Count}, Mode=OneWay}" FontWeight="Bold"/>
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
</TextBlock>
</Border>
</Grid>
<GridSplitter Grid.Column="1"

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,Auto" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,32,Auto,Auto,Auto" ColumnDefinitions="140,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -80,11 +80,16 @@
</Border>
<CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.OverwriteExisting}"
IsChecked="{Binding AllowOverwrite, Mode=TwoWay}"
ToolTip.Tip="checkout -B or branch -f"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
<CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
ToolTip.Tip="--recurse-submodules">

View file

@ -0,0 +1,28 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.DeinitSubmodule"
x:DataType="vm:DeinitSubmodule">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.DeinitSubmodule}"/>
<Grid Margin="0,16,8,0" RowDefinitions="32,Auto" ColumnDefinitions="120,*">
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right" Text="{DynamicResource Text.DeinitSubmodule.Path}"/>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
<Path Width="14" Height="14" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
<TextBlock Text="{Binding Submodule}"/>
</StackPanel>
<CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.DeinitSubmodule.Force}"
IsChecked="{Binding Force, Mode=TwoWay}"
ToolTip.Tip="--force"/>
</Grid>
</StackPanel>
</UserControl>

View file

@ -2,9 +2,9 @@ using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class FastForwardWithoutCheckout : UserControl
public partial class DeinitSubmodule : UserControl
{
public FastForwardWithoutCheckout()
public DeinitSubmodule()
{
InitializeComponent();
}

View file

@ -178,12 +178,12 @@
<Button Classes="icon_button"
Width="28"
Command="{Binding OpenExternalMergeTool}"
HotKey="{OnPlatform Ctrl+D, macOS=⌘+D}">
HotKey="{OnPlatform Ctrl+Shift+D, macOS=⌘+Shift+D}">
<ToolTip.Tip>
<TextBlock>
<Run Text="{DynamicResource Text.Diff.UseMerger}"/>
<Run Text=" "/>
<Run Text="{OnPlatform Ctrl+D, macOS=⌘+D}" Foreground="{DynamicResource Brush.FG2}"/>
<Run Text="{OnPlatform Ctrl+Shift+D, macOS=⌘+⇧+D}" Foreground="{DynamicResource Brush.FG2}"/>
</TextBlock>
</ToolTip.Tip>
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.OpenWith}"/>
@ -279,8 +279,18 @@
<Path Width="16" Height="16" Data="{StaticResource Icons.DoubleDown}" HorizontalAlignment="Center" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<Border Margin="0,8,0,0" BorderThickness="1" BorderBrush="Green" Background="{DynamicResource Brush.Window}">
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding New.Commit}" FullMessage="{Binding New.FullMessage}"/>
<Border Margin="0,8,0,0" BorderThickness="1" BorderBrush="Green" Background="{DynamicResource Brush.Window}" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Content="{Binding New}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:RevisionSubmodule">
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding Commit}" FullMessage="{Binding FullMessage}"/>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Border>
<Border Margin="0,8,0,0" Height="16" HorizontalAlignment="Center" Background="Red" CornerRadius="8" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNull}}">
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Submodule.Deleted}" Margin="8,0" FontSize="10"/>
</Border>
</StackPanel>
</ScrollViewer>

View file

@ -1,21 +0,0 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.FastForwardWithoutCheckout"
x:DataType="vm:FastForwardWithoutCheckout">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.FastForwardWithoutCheck}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch}"/>
<TextBlock Text="{Binding Local.Name}" Margin="8,0,0,0"/>
<TextBlock Text="→" Margin="8,0"/>
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch}"/>
<TextBlock Text="{Binding To.FriendlyName}" Margin="8,0,0,0"/>
</StackPanel>
</StackPanel>
</UserControl>

View file

@ -2,7 +2,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.GitFlowFinish"
x:DataType="vm:GitFlowFinish">
@ -10,15 +12,15 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.FinishFeature}"
IsVisible="{Binding IsFeature}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Feature}}"/>
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.FinishRelease}"
IsVisible="{Binding IsRelease}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Release}}"/>
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.FinishHotfix}"
IsVisible="{Binding IsHotfix}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Hotfix}}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"

View file

@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.GitFlowStart"
x:DataType="vm:GitFlowStart">
@ -11,15 +13,15 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.StartFeatureTitle}"
IsVisible="{Binding IsFeature}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Feature}}"/>
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.StartReleaseTitle}"
IsVisible="{Binding IsRelease}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Release}}"/>
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.GitFlow.StartHotfixTitle}"
IsVisible="{Binding IsHotfix}"/>
IsVisible="{Binding Type, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:GitFlowBranchType.Hotfix}}"/>
<Grid Margin="0,16,0,0" ColumnDefinitions="120,*">
<TextBlock Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"

View file

@ -257,7 +257,7 @@
<v:RevisionCompare/>
</DataTemplate>
<DataTemplate DataType="x:Int32">
<DataTemplate DataType="m:Count">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Width="128" Height="128"
Data="{StaticResource Icons.Detail}"
@ -268,7 +268,7 @@
Margin="0,16"
FontSize="24" FontWeight="Bold"
Foreground="{DynamicResource Brush.FG2}"
Text="{Binding Converter={x:Static c:StringConverters.FormatByResourceKey}, ConverterParameter='Histories.Selected'}"/>
Text="{Binding Value, Converter={x:Static c:StringConverters.FormatByResourceKey}, ConverterParameter='Histories.Selected'}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>

View file

@ -149,7 +149,7 @@
<TextBlock Grid.Row="3" Grid.Column="0" Classes="primary bold" Text="ESC"/>
<TextBlock Grid.Row="3" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.TextEditor.CloseSearch}" />
<TextBlock Grid.Row="4" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+D, macOS=⌘+D}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+D, macOS=⌘+⇧+D}"/>
<TextBlock Grid.Row="4" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.TextEditor.OpenExternalMergeTool}" />
</Grid>
</StackPanel>

View file

@ -107,7 +107,7 @@
<Button Grid.Column="1" Opacity="1" Margin="4,0,0,0" Padding="8,2" Background="Transparent">
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-4">
<MenuItem InputGesture="P" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Pick}">
<MenuItem InputGesture="P" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Pick}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Green"/>
</MenuItem.Icon>
@ -119,7 +119,7 @@
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="E" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Edit}">
<MenuItem InputGesture="E" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Edit}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Orange"/>
</MenuItem.Icon>
@ -131,7 +131,7 @@
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="R" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Reword}">
<MenuItem InputGesture="R" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Reword}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Orange"/>
</MenuItem.Icon>
@ -143,7 +143,7 @@
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="S" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Squash}">
<MenuItem InputGesture="S" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Squash}" IsVisible="{Binding CanSquashOrFixup}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="LightGray"/>
</MenuItem.Icon>
@ -155,7 +155,7 @@
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="F" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Fixup}">
<MenuItem InputGesture="F" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Fixup}" IsVisible="{Binding CanSquashOrFixup}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="LightGray"/>
</MenuItem.Icon>
@ -167,7 +167,7 @@
</MenuItem.Header>
</MenuItem>
<MenuItem InputGesture="D" Command="{Binding SetAction}" CommandParameter="{x:Static m:InteractiveRebaseAction.Drop}">
<MenuItem InputGesture="D" Click="OnChangeRebaseAction" Tag="{x:Static m:InteractiveRebaseAction.Drop}">
<MenuItem.Icon>
<Ellipse Width="14" Height="14" Fill="Red"/>
</MenuItem.Icon>
@ -280,7 +280,7 @@
Minimum="0"
Maximum="100"
IsVisible="False"/>
<Button Grid.Column="1" Classes="flat primary" MinWidth="80" Content="{DynamicResource Text.Start}" Click="StartJobs"/>
<Button Grid.Column="1" Classes="flat primary" MinWidth="80" Content="{DynamicResource Text.Start}" Click="OnStartJobs"/>
<Button Grid.Column="2" Classes="flat" Margin="8,0,0,0" MinWidth="80" Content="{DynamicResource Text.Cancel}" Click="CloseWindow"/>
</Grid>
</Grid>

View file

@ -29,32 +29,32 @@ namespace SourceGit.Views
if (e.Key == Key.P)
{
item.SetAction(Models.InteractiveRebaseAction.Pick);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Pick);
e.Handled = true;
}
else if (e.Key == Key.E)
{
item.SetAction(Models.InteractiveRebaseAction.Edit);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Edit);
e.Handled = true;
}
else if (e.Key == Key.R)
{
item.SetAction(Models.InteractiveRebaseAction.Reword);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Reword);
e.Handled = true;
}
else if (e.Key == Key.S)
{
item.SetAction(Models.InteractiveRebaseAction.Squash);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Squash);
e.Handled = true;
}
else if (e.Key == Key.F)
{
item.SetAction(Models.InteractiveRebaseAction.Fixup);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Fixup);
e.Handled = true;
}
else if (e.Key == Key.D)
{
item.SetAction(Models.InteractiveRebaseAction.Drop);
vm.ChangeAction(item, Models.InteractiveRebaseAction.Drop);
e.Handled = true;
}
else if (e.KeyModifiers == KeyModifiers.Alt && e.Key == Key.Up)
@ -153,8 +153,21 @@ namespace SourceGit.Views
e.Handled = true;
}
}
private void OnChangeRebaseAction(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.InteractiveRebase vm &&
sender is Control
{
DataContext: ViewModels.InteractiveRebaseItem item,
Tag: Models.InteractiveRebaseAction action
})
vm.ChangeAction(item, action);
private async void StartJobs(object _1, RoutedEventArgs _2)
e.Handled = true;
}
private async void OnStartJobs(object _1, RoutedEventArgs _2)
{
var vm = DataContext as ViewModels.InteractiveRebase;
if (vm == null)

View file

@ -35,7 +35,7 @@
<Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,2,3" IsVisible="{OnPlatform True, macOS=False}">
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-8">
<MenuItem Header="{DynamicResource Text.Preferences}" Command="{x:Static s:App.OpenPreferencesCommand}" InputGesture="Ctrl+Shift+P">
<MenuItem Header="{DynamicResource Text.Preferences}" Command="{x:Static s:App.OpenPreferencesCommand}" InputGesture="Ctrl+,">
<MenuItem.Icon>
<Path Width="14" Height="14" Data="{StaticResource Icons.Settings}"/>
</MenuItem.Icon>

View file

@ -264,8 +264,11 @@ namespace SourceGit.Views
}
else if (e.Key == Key.Escape)
{
vm.ActivePage.CancelPopup();
vm.CancelSwitcher();
if (vm.Switcher != null)
vm.CancelSwitcher();
else
vm.ActivePage.CancelPopup();
e.Handled = true;
return;
}

View file

@ -19,8 +19,7 @@
<RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
@ -93,18 +92,16 @@
</WrapPanel>
<CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.Pull.FetchAllBranches}"
IsChecked="{Binding FetchAllBranches, Mode=TwoWay}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Pull.NoTags}"
IsChecked="{Binding NoTags, Mode=TwoWay}"
ToolTip.Tip="--no-tags"/>
<CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Pull.UseRebase}"
IsChecked="{Binding UseRebase, Mode=TwoWay}"
ToolTip.Tip="--rebase"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Pull.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsRecurseSubmoduleVisible}"
ToolTip.Tip="--recurse-submodules"/>
</Grid>
</StackPanel>
</UserControl>

View file

@ -206,7 +206,7 @@
<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">
<Run Text="{DynamicResource Text.Repository.LocalBranches}"/>
<Run Text="{Binding LocalBranchesCount, StringFormat='({0})'}"/>
<Run Text="{Binding LocalBranchesCount, StringFormat='({0})', Mode=OneWay}"/>
</TextBlock>
<Button Grid.Column="2"
Classes="icon_button"
@ -236,7 +236,7 @@
<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">
<Run Text="{DynamicResource Text.Repository.Remotes}"/>
<Run Text="{Binding Remotes, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Remotes, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<Button Grid.Column="2"
Classes="icon_button"
@ -266,7 +266,7 @@
<Path Grid.Column="0" Width="11" Height="11" Margin="2,1,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Tags}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
<Run Text="{DynamicResource Text.Repository.Tags}"/>
<Run Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<ToggleButton Grid.Column="2"
Classes="show_as_tree"
@ -308,7 +308,7 @@
<Path Grid.Column="0" Width="10" Height="10" Margin="2,0,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Submodules}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
<Run Text="{DynamicResource Text.Repository.Submodules}"/>
<Run Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<ToggleButton Grid.Column="2"
Classes="show_as_tree"
@ -350,7 +350,7 @@
<Path Grid.Column="0" Width="11" Height="11" Margin="1,0,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Worktrees}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
<Run Text="{DynamicResource Text.Repository.Worktrees}"/>
<Run Text="{Binding Worktrees, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Worktrees, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<Button Grid.Column="2"
Classes="icon_button"

View file

@ -0,0 +1,49 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.ResetWithoutCheckout"
x:DataType="vm:ResetWithoutCheckout">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.ResetWithoutCheckout}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.ResetWithoutCheckout.Target}"/>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Height="20" VerticalAlignment="Center">
<Path Margin="0,0,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Branch}"/>
<TextBlock Text="{Binding Target.Name}"/>
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.ResetWithoutCheckout.MoveTo}"/>
<ContentControl Grid.Row="1" Grid.Column="1" Content="{Binding To}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:Branch">
<StackPanel Orientation="Horizontal">
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch}"/>
<SelectableTextBlock VerticalAlignment="Center" Text="{Binding FriendlyName}" Margin="8,0,0,0"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:Commit">
<Grid ColumnDefinitions="Auto,Auto,*">
<Path Grid.Column="0" Width="14" Height="14" Data="{StaticResource Icons.Commit}"/>
<TextBlock Grid.Column="1" Classes="primary" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
</Grid>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class ResetWithoutCheckout : UserControl
{
public ResetWithoutCheckout()
{
InitializeComponent();
}
}
}

View file

@ -23,7 +23,7 @@
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Stashes}"/>
<TextBlock Grid.Column="1" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0">
<Run Text="{DynamicResource Text.Stashes.Stashes}"/>
<Run Text="{Binding Stashes, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Stashes, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<Button Grid.Column="2"
Classes="icon_button"
@ -111,7 +111,7 @@
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0">
<Run Text="{DynamicResource Text.Stashes.Changes}"/>
<Run Text="{Binding Changes, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Changes, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
</Grid>
</Border>

View file

@ -108,7 +108,7 @@
Classes="primary"
Margin="8,0,0,0"
TextTrimming="CharacterEllipsis">
<Run Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}}"/>
<Run Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}, Mode=OneWay}"/>
<Run Text="{Binding ChildCounter}" Foreground="{DynamicResource Brush.FG2}"/>
</TextBlock>

View file

@ -65,7 +65,7 @@
<TextBlock Grid.Column="2"
Classes="primary"
Margin="8,0,0,0">
<Run Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}}"/>
<Run Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}, Mode=OneWay}"/>
<Run Text="{Binding TagsCount}" Foreground="{DynamicResource Brush.FG2}"/>
</TextBlock>

View file

@ -65,7 +65,7 @@
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0">
<Run Text="{DynamicResource Text.WorkingCopy.Unstaged}"/>
<Run Text="{Binding Unstaged, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Unstaged, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<v:LoadingIcon Grid.Column="2" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsStaging}"/>
@ -122,7 +122,6 @@
<!-- Unstaged Changes -->
<v:ChangeCollectionView Grid.Row="1"
x:Name="UnstagedChangesView"
Focusable="True"
IsUnstagedChange="True"
SelectionMode="Multiple"
Background="{DynamicResource Brush.Contents}"
@ -148,7 +147,7 @@
<Path Grid.Column="0" Margin="8,0,0,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold" Margin="4,0,0,0">
<Run Text="{DynamicResource Text.WorkingCopy.Staged}"/>
<Run Text="{Binding Staged, Converter={x:Static c:ListConverters.ToCount}}"/>
<Run Text="{Binding Staged, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
</TextBlock>
<v:LoadingIcon Grid.Column="2" Width="14" Height="14" Margin="8,0,0,0" IsVisible="{Binding IsUnstaging}"/>
<Button Grid.Column="4" Classes="icon_button" Width="26" Height="14" Padding="0" Click="OnUnstageSelectedButtonClicked">
@ -173,7 +172,6 @@
<!-- Staged Changes -->
<v:ChangeCollectionView Grid.Row="1"
x:Name="StagedChangesView"
Focusable="True"
IsUnstagedChange="False"
SelectionMode="Multiple"
Background="{DynamicResource Brush.Contents}"

View file

@ -51,7 +51,7 @@ namespace SourceGit.Views
{
var next = UnstagedChangesView.GetNextChangeWithoutSelection();
vm.StageSelected(next);
UnstagedChangesView.Focus();
UnstagedChangesView.TakeFocus();
e.Handled = true;
}
}
@ -62,7 +62,7 @@ namespace SourceGit.Views
{
var next = StagedChangesView.GetNextChangeWithoutSelection();
vm.UnstageSelected(next);
StagedChangesView.Focus();
StagedChangesView.TakeFocus();
e.Handled = true;
}
}
@ -75,7 +75,7 @@ namespace SourceGit.Views
{
var next = UnstagedChangesView.GetNextChangeWithoutSelection();
vm.StageSelected(next);
UnstagedChangesView.Focus();
UnstagedChangesView.TakeFocus();
e.Handled = true;
return;
}
@ -94,7 +94,7 @@ namespace SourceGit.Views
{
var next = StagedChangesView.GetNextChangeWithoutSelection();
vm.UnstageSelected(next);
StagedChangesView.Focus();
StagedChangesView.TakeFocus();
e.Handled = true;
}
}
@ -105,7 +105,7 @@ namespace SourceGit.Views
{
var next = UnstagedChangesView.GetNextChangeWithoutSelection();
vm.StageSelected(next);
UnstagedChangesView.Focus();
UnstagedChangesView.TakeFocus();
}
e.Handled = true;
@ -117,7 +117,7 @@ namespace SourceGit.Views
{
var next = StagedChangesView.GetNextChangeWithoutSelection();
vm.UnstageSelected(next);
StagedChangesView.Focus();
StagedChangesView.TakeFocus();
}
e.Handled = true;