Merge branch 'release/v2025.03'

This commit is contained in:
leo 2025-01-20 10:06:00 +08:00
commit 0f13c002f5
No known key found for this signature in database
41 changed files with 714 additions and 694 deletions

View file

@ -47,7 +47,7 @@
## Translation Status ## Translation Status
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-97.55%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-100.00%25-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-94.69%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-93.33%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-94.42%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md) [![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-100.00%25-brightgreen)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-100.00%25-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-94.69%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-93.32%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-94.41%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
> [!NOTE] > [!NOTE]
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) > You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
@ -62,7 +62,7 @@ This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationD
| OS | PATH | | OS | PATH |
|---------|-----------------------------------------------------| |---------|-----------------------------------------------------|
| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` | | Windows | `%APPDATA%\SourceGit` |
| Linux | `${HOME}/.config/SourceGit` or `${HOME}/.sourcegit` | | Linux | `${HOME}/.config/SourceGit` or `${HOME}/.sourcegit` |
| macOS | `${HOME}/Library/Application Support/SourceGit` | | macOS | `${HOME}/Library/Application Support/SourceGit` |
@ -107,7 +107,7 @@ For **Linux** users:
`deb` how to: `deb` how to:
```shell ```shell
curl https://codeberg.org/api/packages/yataro/debian/repository.key | sudo tee /etc/apt/keyrings/sourcegit.asc curl https://codeberg.org/api/packages/yataro/debian/repository.key | sudo tee /etc/apt/keyrings/sourcegit.asc
echo "deb [signed-by=/etc/apt/keyrings/sourcegit.asc] https://codeberg.org/api/packages/yataro/debian generic main" | sudo tee /etc/apt/sources.list.d/sourcegit.list echo "deb [signed-by=/etc/apt/keyrings/sourcegit.asc, arch=amd64,arm64] https://codeberg.org/api/packages/yataro/debian generic main" | sudo tee /etc/apt/sources.list.d/sourcegit.list
sudo apt update sudo apt update
sudo apt install sourcegit sudo apt install sourcegit
``` ```

View file

@ -1,27 +1,10 @@
### de_DE.axaml: 97.55% ### de_DE.axaml: 100.00%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.Configure.IssueTracker.AddSampleGiteeIssue
- Text.Configure.IssueTracker.AddSampleGiteePullRequest
- Text.Preferences.General.DateFormat
- Text.Preferences.Git.SSLVerify
- Text.Repository.HistoriesLayout
- Text.Repository.HistoriesLayout.Horizontal
- Text.Repository.HistoriesLayout.Vertical
- Text.Repository.HistoriesOrder
- Text.Repository.OnlyHighlightCurrentBranchInHistories
- Text.Repository.Tags.OrderByCreatorDate
- Text.Repository.Tags.OrderByNameAsc
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
- Text.SetUpstream.Upstream
</details> </details>
@ -83,7 +66,7 @@
</details> </details>
### it_IT.axaml: 93.33% ### it_IT.axaml: 93.32%
<details> <details>
@ -141,7 +124,7 @@
</details> </details>
### pt_BR.axaml: 94.42% ### pt_BR.axaml: 94.41%
<details> <details>

View file

@ -1 +1 @@
2025.02 2025.03

View file

@ -7,7 +7,7 @@ namespace SourceGit.Commands
{ {
public partial class LFS public partial class LFS
{ {
[GeneratedRegex(@"^(.+)\s+(\w+)\s+\w+:(\d+)$")] [GeneratedRegex(@"^(.+)\s+([\w.]+)\s+\w+:(\d+)$")]
private static partial Regex REG_LOCK(); private static partial Regex REG_LOCK();
class SubCmd : Command class SubCmd : Command

View file

@ -1,60 +0,0 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace SourceGit.Commands
{
public partial class QueryStashChanges : Command
{
[GeneratedRegex(@"^(\s?[\w\?]{1,4})\s+(.+)$")]
private static partial Regex REG_FORMAT();
public QueryStashChanges(string repo, string sha)
{
WorkingDirectory = repo;
Context = repo;
Args = $"diff --name-status --pretty=format: {sha}^ {sha}";
}
public List<Models.Change> Result()
{
Exec();
return _changes;
}
protected override void OnReadline(string line)
{
var match = REG_FORMAT().Match(line);
if (!match.Success)
return;
var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value;
switch (status[0])
{
case 'M':
change.Set(Models.ChangeState.Modified);
_changes.Add(change);
break;
case 'A':
change.Set(Models.ChangeState.Added);
_changes.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
_changes.Add(change);
break;
case 'R':
change.Set(Models.ChangeState.Renamed);
_changes.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
_changes.Add(change);
break;
}
}
private readonly List<Models.Change> _changes = new List<Models.Change>();
}
}

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
namespace SourceGit.Commands namespace SourceGit.Commands
{ {
@ -8,7 +9,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "stash list --pretty=format:%H%n%ct%n%gd%n%s"; Args = "stash list --pretty=format:%H%n%P%n%ct%n%gd%n%s";
} }
public List<Models.Stash> Result() public List<Models.Stash> Result()
@ -26,21 +27,32 @@ namespace SourceGit.Commands
_stashes.Add(_current); _stashes.Add(_current);
break; break;
case 1: case 1:
_current.Time = ulong.Parse(line); ParseParent(line);
break; break;
case 2: case 2:
_current.Name = line; _current.Time = ulong.Parse(line);
break; break;
case 3: case 3:
_current.Name = line;
break;
case 4:
_current.Message = line; _current.Message = line;
break; break;
} }
_nextLineIdx++; _nextLineIdx++;
if (_nextLineIdx > 3) if (_nextLineIdx > 4)
_nextLineIdx = 0; _nextLineIdx = 0;
} }
private void ParseParent(string data)
{
if (data.Length < 8)
return;
_current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
}
private readonly List<Models.Stash> _stashes = new List<Models.Stash>(); private readonly List<Models.Stash> _stashes = new List<Models.Stash>();
private Models.Stash _current = null; private Models.Stash _current = null;
private int _nextLineIdx = 0; private int _nextLineIdx = 0;

View file

@ -11,9 +11,19 @@ namespace SourceGit.Commands
Context = repo; Context = repo;
} }
public bool Push(string message) public bool Push(string message, bool includeUntracked = true, bool keepIndex = false)
{ {
Args = $"stash push -m \"{message}\""; var builder = new StringBuilder();
builder.Append("stash push ");
if (includeUntracked)
builder.Append("--include-untracked ");
if (keepIndex)
builder.Append("--keep-index ");
builder.Append("-m \"");
builder.Append(message);
builder.Append("\"");
Args = builder.ToString();
return Exec(); return Exec();
} }
@ -65,13 +75,13 @@ namespace SourceGit.Commands
public bool Apply(string name) public bool Apply(string name)
{ {
Args = $"stash apply -q {name}"; Args = $"stash apply --index -q {name}";
return Exec(); return Exec();
} }
public bool Pop(string name) public bool Pop(string name)
{ {
Args = $"stash pop -q {name}"; Args = $"stash pop --index -q {name}";
return Exec(); return Exec();
} }

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace SourceGit.Models namespace SourceGit.Models
{ {
@ -6,8 +7,10 @@ namespace SourceGit.Models
{ {
public string Name { get; set; } = ""; public string Name { get; set; } = "";
public string SHA { get; set; } = ""; public string SHA { get; set; } = "";
public List<string> Parents { get; set; } = [];
public ulong Time { get; set; } = 0; public ulong Time { get; set; } = 0;
public string Message { get; set; } = ""; public string Message { get; set; } = "";
public bool HasUntracked => Parents.Count == 3;
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
} }

View file

@ -72,6 +72,11 @@ namespace SourceGit.Models
_updateBranch = DateTime.Now.ToFileTime() - 1; _updateBranch = DateTime.Now.ToFileTime() - 1;
} }
public void MarkTagDirtyManually()
{
_updateTags = DateTime.Now.ToFileTime() - 1;
}
public void MarkWorkingCopyDirtyManually() public void MarkWorkingCopyDirtyManually()
{ {
_updateWC = DateTime.Now.ToFileTime() - 1; _updateWC = DateTime.Now.ToFileTime() - 1;

View file

@ -86,6 +86,7 @@
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry> <StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>
<StreamGeometry x:Key="Icons.Pull">M432 0h160c27 0 48 21 48 48v336h175c36 0 53 43 28 68L539 757c-15 15-40 15-55 0L180 452c-25-25-7-68 28-68H384V48c0-27 21-48 48-48zm592 752v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h293l98 98c40 40 105 40 145 0l98-98H976c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry> <StreamGeometry x:Key="Icons.Pull">M432 0h160c27 0 48 21 48 48v336h175c36 0 53 43 28 68L539 757c-15 15-40 15-55 0L180 452c-25-25-7-68 28-68H384V48c0-27 21-48 48-48zm592 752v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h293l98 98c40 40 105 40 145 0l98-98H976c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry>
<StreamGeometry x:Key="Icons.Push">M592 768h-160c-27 0-48-21-48-48V384h-175c-36 0-53-43-28-68L485 11c15-15 40-15 55 0l304 304c25 25 7 68-28 68H640v336c0 27-21 48-48 48zm432-16v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h272v16c0 62 50 112 112 112h160c62 0 112-50 112-112v-16h272c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry> <StreamGeometry x:Key="Icons.Push">M592 768h-160c-27 0-48-21-48-48V384h-175c-36 0-53-43-28-68L485 11c15-15 40-15 55 0l304 304c25 25 7 68-28 68H640v336c0 27-21 48-48 48zm432-16v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h272v16c0 62 50 112 112 112h160c62 0 112-50 112-112v-16h272c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry>
<StreamGeometry x:Key="Icons.Quit">M563 555c0 28-23 51-51 51-28 0-51-23-51-51L461 113c0-28 23-51 51-51s51 23 51 51L563 555 563 555zM85 535c0-153 81-287 201-362 24-15 55-8 70 16C371 214 363 245 340 260 248 318 187 419 187 535c0 180 146 325 325 325 180-0 325-146 325-325 0-119-64-223-160-280-24-14-32-46-18-70 14-24 46-32 70-18 125 74 210 211 210 367 0 236-191 427-427 427C276 963 85 772 85 535</StreamGeometry>
<StreamGeometry x:Key="Icons.Rebase">M277 85a149 149 0 00-43 292v230a32 32 0 0064 0V555h267A160 160 0 00725 395v-12a149 149 0 10-64-5v17a96 96 0 01-96 96H299V383A149 149 0 00277 85zM228 720a32 32 0 00-37-52 150 150 0 00-53 68 32 32 0 1060 23 85 85 0 0130-39zm136-52a32 32 0 00-37 52 86 86 0 0130 39 32 32 0 1060-23 149 149 0 00-53-68zM204 833a32 32 0 10-55 32 149 149 0 0063 58 32 32 0 0028-57 85 85 0 01-36-33zm202 32a32 32 0 00-55-32 85 85 0 01-36 33 32 32 0 0028 57 149 149 0 0063-58z</StreamGeometry> <StreamGeometry x:Key="Icons.Rebase">M277 85a149 149 0 00-43 292v230a32 32 0 0064 0V555h267A160 160 0 00725 395v-12a149 149 0 10-64-5v17a96 96 0 01-96 96H299V383A149 149 0 00277 85zM228 720a32 32 0 00-37-52 150 150 0 00-53 68 32 32 0 1060 23 85 85 0 0130-39zm136-52a32 32 0 00-37 52 86 86 0 0130 39 32 32 0 1060-23 149 149 0 00-53-68zM204 833a32 32 0 10-55 32 149 149 0 0063 58 32 32 0 0028-57 85 85 0 01-36-33zm202 32a32 32 0 00-55-32 85 85 0 01-36 33 32 32 0 0028 57 149 149 0 0063-58z</StreamGeometry>
<StreamGeometry x:Key="Icons.Reference">M467 556c0-0 0-1 0-1C467 555 467 556 467 556zM467 556c0-0 0-0 0-0C467 556 467 556 467 556zM467 556c-0 0-0 0-0 0C467 557 467 557 467 556zM468 549C468 532 468 541 468 549L468 549zM468 549c0 1-0 1-0 2C468 551 468 550 468 549zM468 552c-0 1-0 2-0 3C467 554 468 553 468 552zM736 549C736 532 736 541 736 549L736 549zM289 378l0 179 89 0c-1 80-89 89-89 89l45 45c0 0 129-15 134-134L467 378 289 378zM959 244l0 536c0 99-80 179-179 179L244 959c-99 0-179-80-179-179L65 244c0-99 80-179 179-179l536 0C879 65 959 145 959 244zM869 289c0-74-60-134-134-134L289 155c-74 0-134 60-134 134l0 447c0 74 60 134 134 134l447 0c74 0 134-60 134-134L869 289zM557 557l89 0c-1 80-89 89-89 89l45 45c0 0 129-15 134-134L735 378 557 378 557 557z</StreamGeometry> <StreamGeometry x:Key="Icons.Reference">M467 556c0-0 0-1 0-1C467 555 467 556 467 556zM467 556c0-0 0-0 0-0C467 556 467 556 467 556zM467 556c-0 0-0 0-0 0C467 557 467 557 467 556zM468 549C468 532 468 541 468 549L468 549zM468 549c0 1-0 1-0 2C468 551 468 550 468 549zM468 552c-0 1-0 2-0 3C467 554 468 553 468 552zM736 549C736 532 736 541 736 549L736 549zM289 378l0 179 89 0c-1 80-89 89-89 89l45 45c0 0 129-15 134-134L467 378 289 378zM959 244l0 536c0 99-80 179-179 179L244 959c-99 0-179-80-179-179L65 244c0-99 80-179 179-179l536 0C879 65 959 145 959 244zM869 289c0-74-60-134-134-134L289 155c-74 0-134 60-134 134l0 447c0 74 60 134 134 134l447 0c74 0 134-60 134-134L869 289zM557 557l89 0c-1 80-89 89-89 89l45 45c0 0 129-15 134-134L735 378 557 378 557 557z</StreamGeometry>
<StreamGeometry x:Key="Icons.Relation">m224 154a166 166 0 00-166 166v192a166 166 0 00166 166h64v-76h-64a90 90 0 01-90-90v-192a90 90 0 0190-90h320a90 90 0 0190 90v192a90 90 0 01-90 90h-128v77h128a166 166 0 00166-167v-192a166 166 0 00-166-166h-320zm166 390a90 90 0 0190-90h128v-76h-128a166 166 0 00-166 166v192a166 166 0 00166 166h320a166 166 0 00166-166v-192a166 166 0 00-166-166h-64v77h64a90 90 0 0190 90v192a90 90 0 01-90 90h-320a90 90 0 01-90-90v-192z</StreamGeometry> <StreamGeometry x:Key="Icons.Relation">m224 154a166 166 0 00-166 166v192a166 166 0 00166 166h64v-76h-64a90 90 0 01-90-90v-192a90 90 0 0190-90h320a90 90 0 0190 90v192a90 90 0 01-90 90h-128v77h128a166 166 0 00166-167v-192a166 166 0 00-166-166h-320zm166 390a90 90 0 0190-90h128v-76h-128a166 166 0 00-166 166v192a166 166 0 00166 166h320a166 166 0 00166-166v-192a166 166 0 00-166-166h-64v77h64a90 90 0 0190 90v192a90 90 0 01-90 90h-320a90 90 0 01-90-90v-192z</StreamGeometry>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Auschecken von ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Auschecken von ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Mit Branch vergleichen</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Branch-Namen kopieren</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Branch-Namen kopieren</x:String>
@ -164,6 +163,8 @@
<x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">Aktivere --prune beim fetchen</x:String> <x:String x:Key="Text.Configure.Git.EnablePruneOnFetch" xml:space="preserve">Aktivere --prune beim fetchen</x:String>
<x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Aktiviere --signoff für Commits</x:String> <x:String x:Key="Text.Configure.Git.EnableSignOff" xml:space="preserve">Aktiviere --signoff für Commits</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteeIssue" xml:space="preserve">Beispiel für Gitee Issue Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteePullRequest" xml:space="preserve">Beispiel für Gitee Pull Request Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Beispiel für Jira-Regel hinzufügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Beispiel für Jira-Regel hinzufügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabIssue" xml:space="preserve">Beispiel für Gitlab Issue Regel einfügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGitLabIssue" xml:space="preserve">Beispiel für Gitlab Issue Regel einfügen</x:String>
@ -466,6 +467,7 @@
<x:String x:Key="Text.Preferences.DiffMerge.Type" xml:space="preserve">Tool</x:String> <x:String x:Key="Text.Preferences.DiffMerge.Type" xml:space="preserve">Tool</x:String>
<x:String x:Key="Text.Preferences.General" xml:space="preserve">ALLGEMEIN</x:String> <x:String x:Key="Text.Preferences.General" xml:space="preserve">ALLGEMEIN</x:String>
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Beim Starten nach Updates suchen</x:String> <x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Beim Starten nach Updates suchen</x:String>
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Datumsformat</x:String>
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Sprache</x:String> <x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Sprache</x:String>
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String>
@ -477,6 +479,7 @@
<x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Benutzer Email</x:String> <x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Globale Git Benutzer Email</x:String> <x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Globale Git Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Installationspfad</x:String> <x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Installationspfad</x:String>
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Aktiviere HTTP SSL Verifizierung</x:String>
<x:String x:Key="Text.Preferences.Git.User" xml:space="preserve">Benutzername</x:String> <x:String x:Key="Text.Preferences.Git.User" xml:space="preserve">Benutzername</x:String>
<x:String x:Key="Text.Preferences.Git.User.Placeholder" xml:space="preserve">Globaler Git Benutzername</x:String> <x:String x:Key="Text.Preferences.Git.User.Placeholder" xml:space="preserve">Globaler Git Benutzername</x:String>
<x:String x:Key="Text.Preferences.Git.Version" xml:space="preserve">Git Version</x:String> <x:String x:Key="Text.Preferences.Git.Version" xml:space="preserve">Git Version</x:String>
@ -563,12 +566,17 @@
<x:String x:Key="Text.Repository.FilterCommits.Default" xml:space="preserve">Aufheben</x:String> <x:String x:Key="Text.Repository.FilterCommits.Default" xml:space="preserve">Aufheben</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Exclude" xml:space="preserve">Im Graph ausblenden</x:String> <x:String x:Key="Text.Repository.FilterCommits.Exclude" xml:space="preserve">Im Graph ausblenden</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Include" xml:space="preserve">Im Graph filtern</x:String> <x:String x:Key="Text.Repository.FilterCommits.Include" xml:space="preserve">Im Graph filtern</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout" xml:space="preserve">LAYOUT</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Horizontal" xml:space="preserve">Horizontal</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Vertical" xml:space="preserve">Vertikal</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder" xml:space="preserve">COMMIT SORTIERUNG</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder.ByDate" xml:space="preserve">Commit Zeitpunkt (--date-order)</x:String> <x:String x:Key="Text.Repository.HistoriesOrder.ByDate" xml:space="preserve">Commit Zeitpunkt (--date-order)</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder.Topo" xml:space="preserve">Topologie (--topo-order)</x:String> <x:String x:Key="Text.Repository.HistoriesOrder.Topo" xml:space="preserve">Topologie (--topo-order)</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOKALE BRANCHES</x:String> <x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOKALE BRANCHES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Zum HEAD wechseln</x:String> <x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Zum HEAD wechseln</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Aktiviere '--first-parent' Option</x:String> <x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Aktiviere '--first-parent' Option</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Erstelle Branch</x:String> <x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Erstelle Branch</x:String>
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInHistories" xml:space="preserve">Nur aktuellen Branch im Graphen hervorheben</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Öffne in {0}</x:String> <x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Öffne in {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Öffne in externen Tools</x:String> <x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Öffne in externen Tools</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Aktualisiern</x:String> <x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Aktualisiern</x:String>
@ -588,7 +596,12 @@
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">SUBMODUL AKTUALISIEREN</x:String> <x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">SUBMODUL AKTUALISIEREN</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Nach Erstellungsdatum</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Nach Namen (Aufsteigend)</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Nach Namen (Absteigend)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">WORKTREE HINZUFÜGEN</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">WORKTREE HINZUFÜGEN</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
@ -616,6 +629,10 @@
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Diese Version überspringen</x:String> <x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Diese Version überspringen</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String> <x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Es sind momentan kein Updates verfügbar.</x:String> <x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Es sind momentan kein Updates verfügbar.</x:String>
<x:String x:Key="Text.SetUpstream" xml:space="preserve">Setze verfolgten Branch</x:String>
<x:String x:Key="Text.SetUpstream.Local" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.SetUpstream.Unset" xml:space="preserve">Upstream Verfolgung aufheben</x:String>
<x:String x:Key="Text.SetUpstream.Upstream" xml:space="preserve">Upstream:</x:String>
<x:String x:Key="Text.SHALinkCM.CopySHA" xml:space="preserve">SHA kopieren</x:String> <x:String x:Key="Text.SHALinkCM.CopySHA" xml:space="preserve">SHA kopieren</x:String>
<x:String x:Key="Text.SHALinkCM.NavigateTo" xml:space="preserve">Zum Commit wechseln</x:String> <x:String x:Key="Text.SHALinkCM.NavigateTo" xml:space="preserve">Zum Commit wechseln</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String> <x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>

View file

@ -47,7 +47,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Compare with Branch</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">¡BLAME EN ESTE ARCHIVO NO SOPORTADO!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">¡BLAME EN ESTE ARCHIVO NO SOPORTADO!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparar con Rama</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar con HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar con Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nombre de Rama</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nombre de Rama</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Récupérer ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Récupérer ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparer avec la branche</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparer avec le worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparer avec le worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copier le nom de la branche</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copier le nom de la branche</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Attribuisci</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Attribuisci</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">L'ATTRIBUZIONE SU QUESTO FILE NON È SUPPORTATA!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">L'ATTRIBUZIONE SU QUESTO FILE NON È SUPPORTATA!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Confronta con Branch</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Confronta con HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Confronta con HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Confronta con Worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Confronta con Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copia Nome Branch</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copia Nome Branch</x:String>

View file

@ -75,7 +75,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparar com Branch</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar com HEAD</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparar com HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar com Worktree</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparar com Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nome do Branch</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copiar Nome do Branch</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Проверить ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Проверить ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Сравнить с веткой</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Сравнить с ГОЛОВОЙ (HEAD)</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Сравнить с ГОЛОВОЙ (HEAD)</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout) ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout) ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">与其他分支对比</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String>

View file

@ -50,7 +50,6 @@
<x:String x:Key="Text.Blame" xml:space="preserve">逐行溯源 (blame)</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">逐行溯源 (blame)</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">所選擇的檔案不支援該操作!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">所選擇的檔案不支援該操作!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">簽出 (checkout) ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">簽出 (checkout) ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">與其他分支比較</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與目前 HEAD 比較</x:String> <x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與目前 HEAD 比較</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名稱</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名稱</x:String>

View file

@ -49,7 +49,7 @@
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" /> <PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" /> <PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc4.5" /> <PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5" />
<PackageReference Include="TextMateSharp" Version="1.0.65" /> <PackageReference Include="TextMateSharp" Version="1.0.65" />
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.65" /> <PackageReference Include="TextMateSharp.Grammars" Version="1.0.65" />
</ItemGroup> </ItemGroup>

View file

@ -420,34 +420,37 @@ namespace SourceGit.ViewModels
menu.Items.Add(patch); menu.Items.Add(patch);
menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(new MenuItem { Header = "-" });
var resetToThisRevision = new MenuItem(); if (!_repo.IsBare)
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += (_, ev) =>
{ {
new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}"); var resetToThisRevision = new MenuItem();
ev.Handled = true; resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
}; resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += (_, ev) =>
{
new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}");
ev.Handled = true;
};
var resetToFirstParent = new MenuItem(); var resetToFirstParent = new MenuItem();
resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision");
resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += (_, ev) => resetToFirstParent.Click += (_, ev) =>
{ {
if (change.Index == Models.ChangeState.Renamed) if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1"); new Commands.Checkout(_repo.FullPath).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}~1"); new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}~1");
ev.Handled = true; ev.Handled = true;
}; };
menu.Items.Add(resetToThisRevision); menu.Items.Add(resetToThisRevision);
menu.Items.Add(resetToFirstParent); menu.Items.Add(resetToFirstParent);
menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(new MenuItem { Header = "-" });
if (File.Exists(Path.Combine(fullPath))) if (File.Exists(Path.Combine(fullPath)))
TryToAddContextMenuItemsForGitLFS(menu, change.Path); TryToAddContextMenuItemsForGitLFS(menu, change.Path);
}
var copyPath = new MenuItem(); var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath"); copyPath.Header = App.Text("CopyPath");

View file

@ -31,6 +31,11 @@ namespace SourceGit.ViewModels
set => _repo.Settings.CheckoutBranchOnCreateBranch = value; set => _repo.Settings.CheckoutBranchOnCreateBranch = value;
} }
public bool IsBareRepository
{
get => _repo.IsBare;
}
public CreateBranch(Repository repo, Models.Branch branch) public CreateBranch(Repository repo, Models.Branch branch)
{ {
_repo = repo; _repo = repo;
@ -84,7 +89,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = false; var succ = false;
if (CheckoutAfterCreated) if (CheckoutAfterCreated && !_repo.IsBare)
{ {
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false; var needPopStash = false;

View file

@ -33,7 +33,11 @@ namespace SourceGit.ViewModels
{ {
var remotes = ShouldPushToRemote ? _repo.Remotes : null; var remotes = ShouldPushToRemote ? _repo.Remotes : null;
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes); var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, remotes);
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() =>
{
_repo.MarkTagsDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ; return succ;
}); });
} }

View file

@ -213,7 +213,7 @@ namespace SourceGit.ViewModels
{ {
if (firstRemoteBranch != null) if (firstRemoteBranch != null)
_repo.ShowPopup(new CreateBranch(_repo, firstRemoteBranch)); _repo.ShowPopup(new CreateBranch(_repo, firstRemoteBranch));
else else if (!_repo.IsBare)
_repo.ShowPopup(new CheckoutCommit(_repo, commit)); _repo.ShowPopup(new CheckoutCommit(_repo, commit));
} }
} }
@ -253,36 +253,39 @@ namespace SourceGit.ViewModels
var multipleMenu = new ContextMenu(); var multipleMenu = new ContextMenu();
if (canCherryPick) if (!_repo.IsBare)
{ {
var cherryPickMultiple = new MenuItem(); if (canCherryPick)
cherryPickMultiple.Header = App.Text("CommitCM.CherryPickMultiple");
cherryPickMultiple.Icon = App.CreateMenuIcon("Icons.CherryPick");
cherryPickMultiple.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var cherryPickMultiple = new MenuItem();
_repo.ShowPopup(new CherryPick(_repo, selected)); cherryPickMultiple.Header = App.Text("CommitCM.CherryPickMultiple");
e.Handled = true; cherryPickMultiple.Icon = App.CreateMenuIcon("Icons.CherryPick");
}; cherryPickMultiple.Click += (_, e) =>
multipleMenu.Items.Add(cherryPickMultiple); {
} if (_repo.CanCreatePopup())
_repo.ShowPopup(new CherryPick(_repo, selected));
e.Handled = true;
};
multipleMenu.Items.Add(cherryPickMultiple);
}
if (canMerge) if (canMerge)
{
var mergeMultiple = new MenuItem();
mergeMultiple.Header = App.Text("CommitCM.MergeMultiple");
mergeMultiple.Icon = App.CreateMenuIcon("Icons.Merge");
mergeMultiple.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var mergeMultiple = new MenuItem();
_repo.ShowPopup(new MergeMultiple(_repo, selected)); mergeMultiple.Header = App.Text("CommitCM.MergeMultiple");
e.Handled = true; mergeMultiple.Icon = App.CreateMenuIcon("Icons.Merge");
}; mergeMultiple.Click += (_, e) =>
multipleMenu.Items.Add(mergeMultiple); {
} if (_repo.CanCreatePopup())
_repo.ShowPopup(new MergeMultiple(_repo, selected));
e.Handled = true;
};
multipleMenu.Items.Add(mergeMultiple);
}
if (canCherryPick || canMerge) if (canCherryPick || canMerge)
multipleMenu.Items.Add(new MenuItem() { Header = "-" }); multipleMenu.Items.Add(new MenuItem() { Header = "-" });
}
var saveToPatchMultiple = new MenuItem(); var saveToPatchMultiple = new MenuItem();
saveToPatchMultiple.Icon = App.CreateMenuIcon("Icons.Diff"); saveToPatchMultiple.Icon = App.CreateMenuIcon("Icons.Diff");
@ -394,25 +397,48 @@ namespace SourceGit.ViewModels
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
} }
if (current.Head != commit.SHA) if (!_repo.IsBare)
{ {
var reset = new MenuItem(); if (current.Head != commit.SHA)
reset.Header = new Views.NameHighlightedTextBlock("CommitCM.Reset", current.Name);
reset.Icon = App.CreateMenuIcon("Icons.Reset");
reset.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var reset = new MenuItem();
_repo.ShowPopup(new Reset(_repo, current, commit)); reset.Header = new Views.NameHighlightedTextBlock("CommitCM.Reset", current.Name);
e.Handled = true; reset.Icon = App.CreateMenuIcon("Icons.Reset");
}; reset.Click += (_, e) =>
menu.Items.Add(reset); {
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Reset(_repo, current, commit));
e.Handled = true;
};
menu.Items.Add(reset);
if (commit.IsMerged) if (commit.IsMerged)
{
var squash = new MenuItem();
squash.Header = App.Text("CommitCM.SquashCommitsSinceThis");
squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent");
squash.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Squash(_repo, commit, commit.SHA));
e.Handled = true;
};
menu.Items.Add(squash);
}
}
else
{ {
var squash = new MenuItem(); var reword = new MenuItem();
squash.Header = App.Text("CommitCM.SquashCommitsSinceThis"); reword.Header = App.Text("CommitCM.Reword");
squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent"); reword.Icon = App.CreateMenuIcon("Icons.Edit");
squash.Click += (_, e) => reword.Click += (_, e) =>
{ {
if (_repo.LocalChangesCount > 0) if (_repo.LocalChangesCount > 0)
{ {
@ -421,168 +447,148 @@ namespace SourceGit.ViewModels
} }
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowPopup(new Squash(_repo, commit, commit.SHA)); _repo.ShowPopup(new Reword(_repo, commit));
e.Handled = true;
};
menu.Items.Add(reword);
var squash = new MenuItem();
squash.Header = App.Text("CommitCM.Squash");
squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent");
squash.IsEnabled = commit.Parents.Count == 1;
squash.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
if (commit.Parents.Count == 1)
{
var parent = _commits.Find(x => x.SHA == commit.Parents[0]);
if (parent != null && _repo.CanCreatePopup())
_repo.ShowPopup(new Squash(_repo, parent, commit.SHA));
}
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(squash); menu.Items.Add(squash);
} }
}
else if (!commit.IsMerged)
{
var reword = new MenuItem();
reword.Header = App.Text("CommitCM.Reword");
reword.Icon = App.CreateMenuIcon("Icons.Edit");
reword.Click += (_, e) =>
{ {
if (_repo.LocalChangesCount > 0) var rebase = new MenuItem();
{ rebase.Header = new Views.NameHighlightedTextBlock("CommitCM.Rebase", current.Name);
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
return; rebase.Click += (_, e) =>
}
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Reword(_repo, commit));
e.Handled = true;
};
menu.Items.Add(reword);
var squash = new MenuItem();
squash.Header = App.Text("CommitCM.Squash");
squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent");
squash.IsEnabled = commit.Parents.Count == 1;
squash.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
if (commit.Parents.Count == 1)
{
var parent = _commits.Find(x => x.SHA == commit.Parents[0]);
if (parent != null && _repo.CanCreatePopup())
_repo.ShowPopup(new Squash(_repo, parent, commit.SHA));
}
e.Handled = true;
};
menu.Items.Add(squash);
}
if (!commit.IsMerged)
{
var rebase = new MenuItem();
rebase.Header = new Views.NameHighlightedTextBlock("CommitCM.Rebase", current.Name);
rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
rebase.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Rebase(_repo, current, commit));
e.Handled = true;
};
menu.Items.Add(rebase);
if (!commit.HasDecorators)
{
var merge = new MenuItem();
merge.Header = new Views.NameHighlightedTextBlock("CommitCM.Merge", current.Name);
merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, commit, current.Name)); _repo.ShowPopup(new Rebase(_repo, current, commit));
e.Handled = true;
};
menu.Items.Add(rebase);
if (!commit.HasDecorators)
{
var merge = new MenuItem();
merge.Header = new Views.NameHighlightedTextBlock("CommitCM.Merge", current.Name);
merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, commit, current.Name));
e.Handled = true;
};
menu.Items.Add(merge);
}
var cherryPick = new MenuItem();
cherryPick.Header = App.Text("CommitCM.CherryPick");
cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick");
cherryPick.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
{
if (commit.Parents.Count <= 1)
{
_repo.ShowPopup(new CherryPick(_repo, [commit]));
}
else
{
var parents = new List<Models.Commit>();
foreach (var sha in commit.Parents)
{
var parent = _commits.Find(x => x.SHA == sha);
if (parent == null)
parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent != null)
parents.Add(parent);
}
_repo.ShowPopup(new CherryPick(_repo, commit, parents));
}
}
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(merge); menu.Items.Add(cherryPick);
}
else
{
var revert = new MenuItem();
revert.Header = App.Text("CommitCM.Revert");
revert.Icon = App.CreateMenuIcon("Icons.Undo");
revert.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Revert(_repo, commit));
e.Handled = true;
};
menu.Items.Add(revert);
} }
var cherryPick = new MenuItem(); if (current.Head != commit.SHA)
cherryPick.Header = App.Text("CommitCM.CherryPick");
cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick");
cherryPick.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var checkoutCommit = new MenuItem();
checkoutCommit.Header = App.Text("CommitCM.Checkout");
checkoutCommit.Icon = App.CreateMenuIcon("Icons.Detached");
checkoutCommit.Click += (_, e) =>
{ {
if (commit.Parents.Count <= 1) if (_repo.CanCreatePopup())
{ _repo.ShowPopup(new CheckoutCommit(_repo, commit));
_repo.ShowPopup(new CherryPick(_repo, [commit])); e.Handled = true;
} };
else menu.Items.Add(checkoutCommit);
{ }
var parents = new List<Models.Commit>();
foreach (var sha in commit.Parents)
{
var parent = _commits.Find(x => x.SHA == sha);
if (parent == null)
parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent != null)
parents.Add(parent);
}
_repo.ShowPopup(new CherryPick(_repo, commit, parents));
}
}
e.Handled = true;
};
menu.Items.Add(cherryPick);
}
else
{
var revert = new MenuItem();
revert.Header = App.Text("CommitCM.Revert");
revert.Icon = App.CreateMenuIcon("Icons.Undo");
revert.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Revert(_repo, commit));
e.Handled = true;
};
menu.Items.Add(revert);
}
if (current.Head != commit.SHA)
{
var checkoutCommit = new MenuItem();
checkoutCommit.Header = App.Text("CommitCM.Checkout");
checkoutCommit.Icon = App.CreateMenuIcon("Icons.Detached");
checkoutCommit.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new CheckoutCommit(_repo, commit));
e.Handled = true;
};
menu.Items.Add(checkoutCommit);
}
menu.Items.Add(new MenuItem() { Header = "-" });
if (commit.IsMerged && current.Head != commit.SHA)
{
var interactiveRebase = new MenuItem();
interactiveRebase.Header = new Views.NameHighlightedTextBlock("CommitCM.InteractiveRebase", current.Name);
interactiveRebase.Icon = App.CreateMenuIcon("Icons.InteractiveRebase");
interactiveRebase.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
App.OpenDialog(new Views.InteractiveRebase()
{
DataContext = new InteractiveRebase(_repo, current, commit)
});
e.Handled = true;
};
menu.Items.Add(interactiveRebase);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
if (commit.IsMerged && current.Head != commit.SHA)
{
var interactiveRebase = new MenuItem();
interactiveRebase.Header = new Views.NameHighlightedTextBlock("CommitCM.InteractiveRebase", current.Name);
interactiveRebase.Icon = App.CreateMenuIcon("Icons.InteractiveRebase");
interactiveRebase.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
App.OpenDialog(new Views.InteractiveRebase()
{
DataContext = new InteractiveRebase(_repo, current, commit)
});
e.Handled = true;
};
menu.Items.Add(interactiveRebase);
menu.Items.Add(new MenuItem() { Header = "-" });
}
} }
if (current.Head != commit.SHA) if (current.Head != commit.SHA)
@ -914,20 +920,23 @@ namespace SourceGit.ViewModels
submenu.Items.Add(rename); submenu.Items.Add(rename);
submenu.Items.Add(new MenuItem() { Header = "-" }); submenu.Items.Add(new MenuItem() { Header = "-" });
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name); if (!_repo.IsBare)
if (detect.IsGitFlowBranch)
{ {
var finish = new MenuItem(); var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name);
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name); if (detect.IsGitFlowBranch)
finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
finish.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var finish = new MenuItem();
_repo.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix)); finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name);
e.Handled = true; finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
}; finish.Click += (_, e) =>
submenu.Items.Add(finish); {
submenu.Items.Add(new MenuItem() { Header = "-" }); if (_repo.CanCreatePopup())
_repo.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix));
e.Handled = true;
};
submenu.Items.Add(finish);
submenu.Items.Add(new MenuItem() { Header = "-" });
}
} }
var copy = new MenuItem(); var copy = new MenuItem();
@ -951,27 +960,30 @@ namespace SourceGit.ViewModels
FillBranchVisibilityMenu(submenu, branch); FillBranchVisibilityMenu(submenu, branch);
var checkout = new MenuItem(); if (!_repo.IsBare)
checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name);
checkout.Icon = App.CreateMenuIcon("Icons.Check");
checkout.Click += (_, e) =>
{ {
_repo.CheckoutBranch(branch); var checkout = new MenuItem();
e.Handled = true; checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name);
}; checkout.Icon = App.CreateMenuIcon("Icons.Check");
submenu.Items.Add(checkout); checkout.Click += (_, e) =>
{
_repo.CheckoutBranch(branch);
e.Handled = true;
};
submenu.Items.Add(checkout);
var merge = new MenuItem(); var merge = new MenuItem();
merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, current.Name); merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, current.Name);
merge.Icon = App.CreateMenuIcon("Icons.Merge"); merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.IsEnabled = !merged; merge.IsEnabled = !merged;
merge.Click += (_, e) => merge.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, branch, current.Name)); _repo.ShowPopup(new Merge(_repo, branch, current.Name));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(merge); submenu.Items.Add(merge);
}
var rename = new MenuItem(); var rename = new MenuItem();
rename.Header = new Views.NameHighlightedTextBlock("BranchCM.Rename", branch.Name); rename.Header = new Views.NameHighlightedTextBlock("BranchCM.Rename", branch.Name);
@ -996,20 +1008,23 @@ namespace SourceGit.ViewModels
submenu.Items.Add(delete); submenu.Items.Add(delete);
submenu.Items.Add(new MenuItem() { Header = "-" }); submenu.Items.Add(new MenuItem() { Header = "-" });
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name); if (!_repo.IsBare)
if (detect.IsGitFlowBranch)
{ {
var finish = new MenuItem(); var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name);
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); if (detect.IsGitFlowBranch)
finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
finish.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var finish = new MenuItem();
_repo.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix)); finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
e.Handled = true; finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
}; finish.Click += (_, e) =>
submenu.Items.Add(finish); {
submenu.Items.Add(new MenuItem() { Header = "-" }); if (_repo.CanCreatePopup())
_repo.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix));
e.Handled = true;
};
submenu.Items.Add(finish);
submenu.Items.Add(new MenuItem() { Header = "-" });
}
} }
var copy = new MenuItem(); var copy = new MenuItem();
@ -1104,17 +1119,19 @@ namespace SourceGit.ViewModels
}; };
submenu.Items.Add(push); submenu.Items.Add(push);
var merge = new MenuItem(); if (!_repo.IsBare && !merged)
merge.Header = new Views.NameHighlightedTextBlock("TagCM.Merge", tag.Name, current.Name);
merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.IsEnabled = !merged;
merge.Click += (_, e) =>
{ {
if (_repo.CanCreatePopup()) var merge = new MenuItem();
_repo.ShowPopup(new Merge(_repo, tag, current.Name)); merge.Header = new Views.NameHighlightedTextBlock("TagCM.Merge", tag.Name, current.Name);
e.Handled = true; merge.Icon = App.CreateMenuIcon("Icons.Merge");
}; merge.Click += (_, e) =>
submenu.Items.Add(merge); {
if (_repo.CanCreatePopup())
_repo.ShowPopup(new Merge(_repo, tag, current.Name));
e.Handled = true;
};
submenu.Items.Add(merge);
}
var delete = new MenuItem(); var delete = new MenuItem();
delete.Header = new Views.NameHighlightedTextBlock("TagCM.Delete", tag.Name); delete.Header = new Views.NameHighlightedTextBlock("TagCM.Delete", tag.Name);

View file

@ -280,19 +280,20 @@ namespace SourceGit.ViewModels
return; return;
} }
var gitDir = new Commands.QueryGitDir(node.Id).Result(); var isBare = new Commands.IsBareRepository(node.Id).Result();
if (string.IsNullOrEmpty(gitDir)) var gitDir = node.Id;
if (!isBare)
{ {
var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; gitDir = new Commands.QueryGitDir(node.Id).Result();
App.RaiseException(ctx, "Given path is not a valid git repository!"); if (string.IsNullOrEmpty(gitDir))
return; {
var ctx = page == null ? ActivePage.Node.Id : page.Node.Id;
App.RaiseException(ctx, "Given path is not a valid git repository!");
return;
}
} }
var repo = new Repository() var repo = new Repository(isBare, node.Id, gitDir);
{
FullPath = node.Id,
GitDir = gitDir,
};
repo.Open(); repo.Open();
if (page == null) if (page == null)

View file

@ -18,6 +18,11 @@ namespace SourceGit.ViewModels
{ {
public class Repository : ObservableObject, Models.IRepository public class Repository : ObservableObject, Models.IRepository
{ {
public bool IsBare
{
get;
}
public string FullPath public string FullPath
{ {
get => _fullpath; get => _fullpath;
@ -448,6 +453,13 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _isAutoFetching, value); private set => SetProperty(ref _isAutoFetching, value);
} }
public Repository(bool isBare, string path, string gitDir)
{
IsBare = isBare;
FullPath = path;
GitDir = gitDir;
}
public void Open() public void Open()
{ {
var settingsFile = Path.Combine(_gitDir, "sourcegit.settings"); var settingsFile = Path.Combine(_gitDir, "sourcegit.settings");
@ -759,6 +771,19 @@ namespace SourceGit.ViewModels
} }
} }
public void MarkTagsDirtyManually()
{
if (_watcher == null)
{
Task.Run(RefreshTags);
Task.Run(RefreshCommits);
}
else
{
_watcher.MarkTagDirtyManually();
}
}
public void MarkWorkingCopyDirtyManually() public void MarkWorkingCopyDirtyManually()
{ {
if (_watcher == null) if (_watcher == null)
@ -995,6 +1020,9 @@ namespace SourceGit.ViewModels
public void RefreshWorkingCopyChanges() public void RefreshWorkingCopyChanges()
{ {
if (IsBare)
return;
var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result(); var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result();
if (_workingCopy == null) if (_workingCopy == null)
return; return;
@ -1010,6 +1038,9 @@ namespace SourceGit.ViewModels
public void RefreshStashes() public void RefreshStashes()
{ {
if (IsBare)
return;
var stashes = new Commands.QueryStashes(_fullpath).Result(); var stashes = new Commands.QueryStashes(_fullpath).Result();
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
@ -1044,6 +1075,9 @@ namespace SourceGit.ViewModels
} }
} }
if (IsBare)
return;
if (!CanCreatePopup()) if (!CanCreatePopup())
return; return;
@ -1416,73 +1450,72 @@ namespace SourceGit.ViewModels
if (branch.IsCurrent) if (branch.IsCurrent)
{ {
var discard = new MenuItem(); if (!IsBare)
discard.Header = App.Text("BranchCM.DiscardAll");
discard.Icon = App.CreateMenuIcon("Icons.Undo");
discard.Click += (_, e) =>
{ {
if (CanCreatePopup()) var discard = new MenuItem();
ShowPopup(new Discard(this)); discard.Header = App.Text("BranchCM.DiscardAll");
e.Handled = true; discard.Icon = App.CreateMenuIcon("Icons.Undo");
}; discard.Click += (_, e) =>
menu.Items.Add(discard);
menu.Items.Add(new MenuItem() { Header = "-" });
if (!string.IsNullOrEmpty(branch.Upstream))
{
var upstream = branch.Upstream.Substring(13);
var fastForward = new MenuItem();
fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream);
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0;
fastForward.Click += (_, e) =>
{ {
var b = _branches.Find(x => x.FriendlyName == upstream);
if (b == null)
return;
if (CanCreatePopup()) if (CanCreatePopup())
ShowAndStartPopup(new Merge(this, b, branch.Name)); ShowPopup(new Discard(this));
e.Handled = true; e.Handled = true;
}; };
var pull = new MenuItem(); menu.Items.Add(discard);
pull.Header = new Views.NameHighlightedTextBlock("BranchCM.Pull", upstream); menu.Items.Add(new MenuItem() { Header = "-" });
pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new Pull(this, null));
e.Handled = true;
};
menu.Items.Add(fastForward); if (!string.IsNullOrEmpty(branch.Upstream))
menu.Items.Add(pull); {
var upstream = branch.Upstream.Substring(13);
var fastForward = new MenuItem();
fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream);
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0;
fastForward.Click += (_, e) =>
{
var b = _branches.Find(x => x.FriendlyName == upstream);
if (b == null)
return;
if (CanCreatePopup())
ShowAndStartPopup(new Merge(this, b, branch.Name));
e.Handled = true;
};
var pull = new MenuItem();
pull.Header = new Views.NameHighlightedTextBlock("BranchCM.Pull", upstream);
pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new Pull(this, null));
e.Handled = true;
};
menu.Items.Add(fastForward);
menu.Items.Add(pull);
}
} }
menu.Items.Add(push); menu.Items.Add(push);
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
if (compareWithBranch != null)
{
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(compareWithBranch);
}
} }
else else
{ {
var checkout = new MenuItem(); if (!IsBare)
checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name);
checkout.Icon = App.CreateMenuIcon("Icons.Check");
checkout.Click += (_, e) =>
{ {
CheckoutBranch(branch); var checkout = new MenuItem();
e.Handled = true; checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name);
}; checkout.Icon = App.CreateMenuIcon("Icons.Check");
menu.Items.Add(checkout); checkout.Click += (_, e) =>
menu.Items.Add(new MenuItem() { Header = "-" }); {
CheckoutBranch(branch);
e.Handled = true;
};
menu.Items.Add(checkout);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var worktree = _worktrees.Find(x => x.Branch == branch.FullName); var worktree = _worktrees.Find(x => x.Branch == branch.FullName);
var upstream = _branches.Find(x => x.FullName == branch.Upstream); var upstream = _branches.Find(x => x.FullName == branch.Upstream);
@ -1517,28 +1550,44 @@ namespace SourceGit.ViewModels
menu.Items.Add(push); menu.Items.Add(push);
var merge = new MenuItem(); if (!IsBare)
merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, _currentBranch.Name);
merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.Click += (_, e) =>
{ {
if (CanCreatePopup()) var merge = new MenuItem();
ShowPopup(new Merge(this, branch, _currentBranch.Name)); merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, _currentBranch.Name);
e.Handled = true; merge.Icon = App.CreateMenuIcon("Icons.Merge");
}; merge.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new Merge(this, branch, _currentBranch.Name));
e.Handled = true;
};
var rebase = new MenuItem(); var rebase = new MenuItem();
rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", _currentBranch.Name, branch.Name); rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", _currentBranch.Name, branch.Name);
rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
rebase.Click += (_, e) => rebase.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new Rebase(this, _currentBranch, branch));
e.Handled = true;
};
menu.Items.Add(merge);
menu.Items.Add(rebase);
}
var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("BranchCM.CompareWithHead");
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
compareWithHead.Click += (_, _) =>
{ {
if (CanCreatePopup()) App.OpenDialog(new Views.BranchCompare()
ShowPopup(new Rebase(this, _currentBranch, branch)); {
e.Handled = true; DataContext = new BranchCompare(_fullpath, branch, _currentBranch)
});
}; };
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(merge); menu.Items.Add(compareWithHead);
menu.Items.Add(rebase);
if (_localChangesCount > 0) if (_localChangesCount > 0)
{ {
@ -1556,34 +1605,27 @@ namespace SourceGit.ViewModels
_histories.DetailContext = new RevisionCompare(_fullpath, target, null); _histories.DetailContext = new RevisionCompare(_fullpath, target, null);
} }
}; };
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(compareWithWorktree); menu.Items.Add(compareWithWorktree);
} }
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
if (compareWithBranch != null)
{
if (_localChangesCount == 0)
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(compareWithBranch);
}
} }
var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name); if (!IsBare)
if (detect.IsGitFlowBranch)
{ {
var finish = new MenuItem(); var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name);
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); if (detect.IsGitFlowBranch)
finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
finish.Click += (_, e) =>
{ {
if (CanCreatePopup()) var finish = new MenuItem();
ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix)); finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
e.Handled = true; finish.Icon = App.CreateMenuIcon("Icons.GitFlow");
}; finish.Click += (_, e) =>
menu.Items.Add(new MenuItem() { Header = "-" }); {
menu.Items.Add(finish); if (CanCreatePopup())
ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix));
e.Handled = true;
};
menu.Items.Add(new MenuItem() { Header = "-" });
menu.Items.Add(finish);
}
} }
var rename = new MenuItem(); var rename = new MenuItem();
@ -1635,25 +1677,28 @@ namespace SourceGit.ViewModels
menu.Items.Add(createTag); menu.Items.Add(createTag);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
var remoteBranches = new List<Models.Branch>(); if (!IsBare)
foreach (var b in _branches)
{ {
if (!b.IsLocal) var remoteBranches = new List<Models.Branch>();
remoteBranches.Add(b); foreach (var b in _branches)
}
if (remoteBranches.Count > 0)
{
var tracking = new MenuItem();
tracking.Header = App.Text("BranchCM.Tracking");
tracking.Icon = App.CreateMenuIcon("Icons.Track");
tracking.Click += (_, e) =>
{ {
if (CanCreatePopup()) if (!b.IsLocal)
ShowPopup(new SetUpstream(this, branch, remoteBranches)); remoteBranches.Add(b);
e.Handled = true; }
};
menu.Items.Add(tracking); if (remoteBranches.Count > 0)
{
var tracking = new MenuItem();
tracking.Header = App.Text("BranchCM.Tracking");
tracking.Icon = App.CreateMenuIcon("Icons.Track");
tracking.Click += (_, e) =>
{
if (CanCreatePopup())
ShowPopup(new SetUpstream(this, branch, remoteBranches));
e.Handled = true;
};
menu.Items.Add(tracking);
}
} }
var archive = new MenuItem(); var archive = new MenuItem();
@ -1813,7 +1858,18 @@ namespace SourceGit.ViewModels
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
} }
var hasCompare = false; var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("BranchCM.CompareWithHead");
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
compareWithHead.Click += (_, _) =>
{
App.OpenDialog(new Views.BranchCompare()
{
DataContext = new BranchCompare(_fullpath, branch, _currentBranch)
});
};
menu.Items.Add(compareWithHead);
if (_localChangesCount > 0) if (_localChangesCount > 0)
{ {
var compareWithWorktree = new MenuItem(); var compareWithWorktree = new MenuItem();
@ -1831,18 +1887,8 @@ namespace SourceGit.ViewModels
} }
}; };
menu.Items.Add(compareWithWorktree); menu.Items.Add(compareWithWorktree);
hasCompare = true;
} }
menu.Items.Add(new MenuItem() { Header = "-" });
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
if (compareWithBranch != null)
{
menu.Items.Add(compareWithBranch);
hasCompare = true;
}
if (hasCompare)
menu.Items.Add(new MenuItem() { Header = "-" });
var delete = new MenuItem(); var delete = new MenuItem();
delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", name); delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", name);
@ -2078,39 +2124,6 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
private MenuItem CreateMenuItemToCompareBranches(Models.Branch branch)
{
if (_branches.Count == 1)
return null;
var compare = new MenuItem();
compare.Header = App.Text("BranchCM.CompareWithBranch");
compare.Icon = App.CreateMenuIcon("Icons.Compare");
foreach (var b in _branches)
{
if (b.FullName != branch.FullName)
{
var dup = b;
var target = new MenuItem();
target.Header = b.FriendlyName;
target.Icon = App.CreateMenuIcon(b.IsCurrent ? "Icons.Check" : "Icons.Branch");
target.Click += (_, e) =>
{
App.OpenDialog(new Views.BranchCompare()
{
DataContext = new BranchCompare(_fullpath, branch, dup)
});
e.Handled = true;
};
compare.Items.Add(target);
}
}
return compare;
}
private LauncherPage GetOwnerPage() private LauncherPage GetOwnerPage()
{ {
var launcher = App.GetLauncer(); var launcher = App.GetLauncer();

View file

@ -34,7 +34,7 @@ namespace SourceGit.ViewModels
watch.Start(); watch.Start();
var rootDir = new DirectoryInfo(RootDir); var rootDir = new DirectoryInfo(RootDir);
var founded = new List<string>(); var founded = new List<FoundRepository>();
GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions() GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions()
{ {
AttributesToSkip = FileAttributes.Hidden | FileAttributes.System, AttributesToSkip = FileAttributes.Hidden | FileAttributes.System,
@ -47,16 +47,16 @@ namespace SourceGit.ViewModels
foreach (var f in founded) foreach (var f in founded)
{ {
var parent = new DirectoryInfo(f).Parent!.FullName.Replace("\\", "/"); var parent = new DirectoryInfo(f.Path).Parent!.FullName.Replace("\\", "/");
if (parent.Equals(normalizedRoot, StringComparison.Ordinal)) if (parent.Equals(normalizedRoot, StringComparison.Ordinal))
{ {
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false); Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, null, false);
} }
else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal)) else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal))
{ {
var relative = parent.Substring(normalizedRoot.Length).TrimStart('/'); var relative = parent.Substring(normalizedRoot.Length).TrimStart('/');
var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative); var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative);
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false); Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, group, false);
} }
} }
@ -85,7 +85,7 @@ namespace SourceGit.ViewModels
} }
} }
private void GetUnmanagedRepositories(DirectoryInfo dir, List<string> outs, EnumerationOptions opts, int depth = 0) private void GetUnmanagedRepositories(DirectoryInfo dir, List<FoundRepository> outs, EnumerationOptions opts, int depth = 0)
{ {
var subdirs = dir.GetDirectories("*", opts); var subdirs = dir.GetDirectories("*", opts);
foreach (var subdir in subdirs) foreach (var subdir in subdirs)
@ -111,12 +111,19 @@ namespace SourceGit.ViewModels
{ {
var normalized = test.StdOut.Trim().Replace("\\", "/"); var normalized = test.StdOut.Trim().Replace("\\", "/");
if (!_managed.Contains(normalized)) if (!_managed.Contains(normalized))
outs.Add(normalized); outs.Add(new FoundRepository(normalized, false));
} }
continue; continue;
} }
var isBare = new Commands.IsBareRepository(subdir.FullName).Result();
if (isBare)
{
outs.Add(new FoundRepository(normalizedSelf, true));
continue;
}
if (depth < 5) if (depth < 5)
GetUnmanagedRepositories(subdir, outs, opts, depth + 1); GetUnmanagedRepositories(subdir, outs, opts, depth + 1);
} }
@ -161,6 +168,12 @@ namespace SourceGit.ViewModels
return added; return added;
} }
private record FoundRepository(string path, bool isBare)
{
public string Path { get; set; } = path;
public bool IsBare { get; set; } = isBare;
}
private HashSet<string> _managed = new HashSet<string>(); private HashSet<string> _managed = new HashSet<string>();
} }
} }

View file

@ -76,14 +76,11 @@ namespace SourceGit.ViewModels
} }
else else
{ {
if (IncludeUntracked) succ = new Commands.Stash(_repo.FullPath).Push(Message, IncludeUntracked, KeepIndex);
AddUntracked(_changes);
succ = StashWithChanges(_changes);
} }
} }
else else
{ {
AddUntracked(_changes);
succ = StashWithChanges(_changes); succ = StashWithChanges(_changes);
} }
@ -97,40 +94,6 @@ namespace SourceGit.ViewModels
}); });
} }
private void AddUntracked(List<Models.Change> changes)
{
var toBeAdded = new List<Models.Change>();
foreach (var c in changes)
{
if (c.WorkTree == Models.ChangeState.Added || c.WorkTree == Models.ChangeState.Untracked)
toBeAdded.Add(c);
}
if (toBeAdded.Count == 0)
return;
if (Native.OS.GitVersion >= Models.GitVersions.ADD_WITH_PATHSPECFILE)
{
var paths = new List<string>();
foreach (var c in toBeAdded)
paths.Add(c.Path);
var tmpFile = Path.GetTempFileName();
File.WriteAllLines(tmpFile, paths);
new Commands.Add(_repo.FullPath, tmpFile).Exec();
File.Delete(tmpFile);
}
else
{
for (int i = 0; i < toBeAdded.Count; i += 10)
{
var count = Math.Min(10, toBeAdded.Count - i);
var step = toBeAdded.GetRange(i, count);
new Commands.Add(_repo.FullPath, step).Exec();
}
}
}
private bool StashWithChanges(List<Models.Change> changes) private bool StashWithChanges(List<Models.Change> changes)
{ {
if (changes.Count == 0) if (changes.Count == 0)

View file

@ -57,8 +57,25 @@ namespace SourceGit.ViewModels
{ {
Task.Run(() => Task.Run(() =>
{ {
var changes = new Commands.QueryStashChanges(_repo.FullPath, value.SHA).Result(); var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
Dispatcher.UIThread.Invoke(() => Changes = changes); var untracked = new HashSet<string>();
if (value.HasUntracked)
{
var untrackedChanges = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result();
foreach (var c in untrackedChanges)
{
untracked.Add(c.Path);
changes.Add(c);
}
}
changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
Dispatcher.UIThread.Invoke(() =>
{
Changes = changes;
_untrackedChanges = untracked;
});
}); });
} }
} }
@ -84,8 +101,10 @@ namespace SourceGit.ViewModels
{ {
if (value == null) if (value == null)
DiffContext = null; DiffContext = null;
else if (_untrackedChanges.Contains(value.Path))
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption("4b825dc642cb6eb9a060e54bf8d69288fbee4904", _selectedStash.Parents[2], value), _diffContext);
else else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption($"{_selectedStash.SHA}^", _selectedStash.SHA, value), _diffContext); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, value), _diffContext);
} }
} }
} }
@ -254,6 +273,7 @@ namespace SourceGit.ViewModels
private List<Models.Stash> _visibleStashes = new List<Models.Stash>(); private List<Models.Stash> _visibleStashes = new List<Models.Stash>();
private string _searchFilter = string.Empty; private string _searchFilter = string.Empty;
private Models.Stash _selectedStash = null; private Models.Stash _selectedStash = null;
private HashSet<string> _untrackedChanges = new HashSet<string>();
private List<Models.Change> _changes = null; private List<Models.Change> _changes = null;
private Models.Change _selectedChange = null; private Models.Change _selectedChange = null;
private DiffContext _diffContext = null; private DiffContext _diffContext = null;

View file

@ -83,6 +83,37 @@ namespace SourceGit.ViewModels
} }
} }
public void OpenOrInitRepository(string path, RepositoryNode parent, bool bMoveExistedNode)
{
if (!Directory.Exists(path))
{
if (File.Exists(path))
path = Path.GetDirectoryName(path);
else
return;
}
var isBare = new Commands.IsBareRepository(path).Result();
var repoRoot = path;
if (!isBare)
{
var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd();
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
{
InitRepository(path, parent, test.StdErr);
return;
}
repoRoot = test.StdOut.Trim();
}
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode);
Refresh();
var launcher = App.GetLauncer();
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
}
public void InitRepository(string path, RepositoryNode parent, string reason) public void InitRepository(string path, RepositoryNode parent, string reason)
{ {
if (!Preferences.Instance.IsGitConfigured()) if (!Preferences.Instance.IsGitConfigured())

View file

@ -19,14 +19,14 @@
<v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Author}"/> <v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Author}"/>
<StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical"> <StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical">
<TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Author}"/> <TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Author}"/>
<DockPanel Margin="0,10,0,8" ClipToBounds="True"> <Grid Margin="0,10,0,8" ColumnDefinitions="Auto,*" ClipToBounds="True">
<SelectableTextBlock Text="{Binding Author.Name}" Margin="2,0,8,0"/> <v:EnhancedSelectableTextBlock Grid.Column="0" Text="{Binding Author.Name}" Margin="2,0,8,0"/>
<SelectableTextBlock Text="{Binding Author.Email}" ToolTip.Tip="{Binding Author.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/> <v:EnhancedSelectableTextBlock Grid.Column="1" Text="{Binding Author.Email}" ToolTip.Tip="{Binding Author.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/>
</DockPanel> </Grid>
<SelectableTextBlock Text="{Binding AuthorTimeStr}" <v:EnhancedSelectableTextBlock Text="{Binding AuthorTimeStr}"
Margin="2,0,0,0" Margin="2,0,0,0"
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
Foreground="{DynamicResource Brush.FG2}"/> Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
@ -35,14 +35,14 @@
<v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Committer}"/> <v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Committer}"/>
<StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical"> <StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical">
<TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Committer}"/> <TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Committer}"/>
<DockPanel Margin="0,10,0,8" ClipToBounds="True"> <Grid Margin="0,10,0,8" ColumnDefinitions="Auto,*" ClipToBounds="True">
<SelectableTextBlock Text="{Binding Committer.Name}" Margin="2,0,8,0"/> <v:EnhancedSelectableTextBlock Grid.Column="0" Text="{Binding Committer.Name}" Margin="2,0,8,0"/>
<SelectableTextBlock Text="{Binding Committer.Email}" ToolTip.Tip="{Binding Committer.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/> <v:EnhancedSelectableTextBlock Grid.Column="1" Text="{Binding Committer.Email}" ToolTip.Tip="{Binding Committer.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/>
</DockPanel> </Grid>
<SelectableTextBlock Text="{Binding CommitterTimeStr}" <v:EnhancedSelectableTextBlock Text="{Binding CommitterTimeStr}"
Margin="2,0,0,0" Margin="2,0,0,0"
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
Foreground="{DynamicResource Brush.FG2}"/> Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</UniformGrid> </UniformGrid>

View file

@ -18,8 +18,8 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="32"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
@ -67,27 +67,31 @@
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="2" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
Text="{DynamicResource Text.CreateBranch.LocalChanges}"/> Text="{DynamicResource Text.CreateBranch.LocalChanges}"
<WrapPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center"> IsVisible="{Binding !IsBareRepository}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}" <Border Grid.Row="2" Grid.Column="1" MinHeight="32" IsVisible="{Binding !IsBareRepository}">
x:Name="RadioDoNothing" <WrapPanel Orientation="Horizontal" VerticalAlignment="Center">
GroupName="LocalChanges" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
Margin="0,0,8,0" x:Name="RadioDoNothing"
IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/> GroupName="LocalChanges"
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" Margin="0,0,8,0"
x:Name="RadioStashAndReply" IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/>
GroupName="LocalChanges" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
Margin="0,0,8,0" x:Name="RadioStashAndReply"
IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/> GroupName="LocalChanges"
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}" Margin="0,0,8,0"
x:Name="RadioDiscard" IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/>
GroupName="LocalChanges" <RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/> x:Name="RadioDiscard"
</WrapPanel> GroupName="LocalChanges"
IsCheckedChanged="OnLocalChangeActionIsCheckedChanged"/>
</WrapPanel>
</Border>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.Checkout}" Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"/> IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -0,0 +1,20 @@
using System;
using Avalonia;
using Avalonia.Controls;
namespace SourceGit.Views
{
public class EnhancedSelectableTextBlock : SelectableTextBlock
{
protected override Type StyleKeyOverride => typeof(SelectableTextBlock);
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == TextProperty)
UpdateLayout();
}
}
}

View file

@ -45,7 +45,7 @@
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}" FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
Margin="0,0,0,8"/> Margin="0,0,0,8"/>
<Grid RowDefinitions="20,20,20,20,20,20,20" ColumnDefinitions="150,*"> <Grid RowDefinitions="20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+P, macOS=⌘+\,}"/> <TextBlock Grid.Row="0" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+P, macOS=⌘+\,}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.OpenPreferences}"/> <TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.OpenPreferences}"/>
@ -66,6 +66,9 @@
<TextBlock Grid.Row="6" Grid.Column="0" Classes="primary bold" Text="ESC"/> <TextBlock Grid.Row="6" Grid.Column="0" Classes="primary bold" Text="ESC"/>
<TextBlock Grid.Row="6" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.CancelPopup}" /> <TextBlock Grid.Row="6" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.CancelPopup}" />
<TextBlock Grid.Row="7" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Q, macOS=⌘+Q}"/>
<TextBlock Grid.Row="7" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Quit}" />
</Grid> </Grid>
<TextBlock Text="{DynamicResource Text.Hotkeys.Repo}" <TextBlock Text="{DynamicResource Text.Hotkeys.Repo}"

View file

@ -62,6 +62,11 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Info}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Info}"/>
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="{DynamicResource Text.Quit}" Command="{x:Static s:App.QuitCommand}" InputGesture="Ctrl+Q">
<MenuItem.Icon>
<Path Width="14" Height="14" Data="{StaticResource Icons.Quit}"/>
</MenuItem.Icon>
</MenuItem>
</MenuFlyout> </MenuFlyout>
</Button.Flyout> </Button.Flyout>
<Path Width="12" Height="12" Data="{StaticResource Icons.Menu}"/> <Path Width="12" Height="12" Data="{StaticResource Icons.Menu}"/>

View file

@ -146,6 +146,12 @@ namespace SourceGit.Views
return; return;
} }
if (e.Key == Key.Q) {
App.Quit(0);
e.Handled = true;
return;
}
if ((OperatingSystem.IsMacOS() && e.KeyModifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Right) || if ((OperatingSystem.IsMacOS() && e.KeyModifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Right) ||
(!OperatingSystem.IsMacOS() && !e.KeyModifiers.HasFlag(KeyModifiers.Shift) && e.Key == Key.Tab)) (!OperatingSystem.IsMacOS() && !e.KeyModifiers.HasFlag(KeyModifiers.Shift) && e.Key == Key.Tab))
{ {

View file

@ -40,7 +40,7 @@
<!-- Page Switcher for Right Panel --> <!-- Page Switcher for Right Panel -->
<Border Grid.Row="0" Margin="8,0,4,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="6"> <Border Grid.Row="0" Margin="8,0,4,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="6">
<Border CornerRadius="6" ClipToBounds="True"> <Border CornerRadius="6" ClipToBounds="True">
<ListBox Background="Transparent" SelectedIndex="{Binding SelectedViewIndex, Mode=TwoWay}"> <ListBox Background="Transparent" SelectedIndex="{Binding SelectedViewIndex, Mode=TwoWay}" SelectionMode="AlwaysSelected">
<ListBox.Styles> <ListBox.Styles>
<Style Selector="Path.icon"> <Style Selector="Path.icon">
<Setter Property="Width" Value="12"/> <Setter Property="Width" Value="12"/>
@ -128,7 +128,7 @@
</Grid> </Grid>
</ListBoxItem> </ListBoxItem>
<ListBoxItem> <ListBoxItem IsVisible="{Binding !IsBare}">
<Grid Classes="view_mode" ColumnDefinitions="Auto,*,Auto"> <Grid Classes="view_mode" ColumnDefinitions="Auto,*,Auto">
<Path Grid.Column="0" Classes="icon" Data="{StaticResource Icons.Changes}"/> <Path Grid.Column="0" Classes="icon" Data="{StaticResource Icons.Changes}"/>
<TextBlock Grid.Column="1" Classes="header" Text="{DynamicResource Text.WorkingCopy}"/> <TextBlock Grid.Column="1" Classes="header" Text="{DynamicResource Text.WorkingCopy}"/>
@ -143,7 +143,7 @@
</Grid> </Grid>
</ListBoxItem> </ListBoxItem>
<ListBoxItem> <ListBoxItem IsVisible="{Binding !IsBare}">
<Grid Classes="view_mode" ColumnDefinitions="Auto,*,Auto"> <Grid Classes="view_mode" ColumnDefinitions="Auto,*,Auto">
<Path Grid.Column="0" Classes="icon" Data="{StaticResource Icons.Stashes}"/> <Path Grid.Column="0" Classes="icon" Data="{StaticResource Icons.Stashes}"/>
<TextBlock Grid.Column="1" Classes="header" Text="{DynamicResource Text.Stashes}"/> <TextBlock Grid.Column="1" Classes="header" Text="{DynamicResource Text.Stashes}"/>
@ -313,7 +313,7 @@
</ListBox.Styles> </ListBox.Styles>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate DataType="m:Submodule"> <DataTemplate DataType="m:Submodule">
<Grid ColumnDefinitions="Auto,*,8"> <Grid ColumnDefinitions="Auto,*,8,8">
<Path Grid.Column="0" Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/> <Path Grid.Column="0" Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
<TextBlock Grid.Column="1" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/> <TextBlock Grid.Column="1" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
<Path Grid.Column="2" <Path Grid.Column="2"

View file

@ -13,7 +13,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Click="OpenWithExternalTools" ToolTip.Tip="{DynamicResource Text.Repository.OpenWithExternalTools}"> <Button Classes="icon_button" Width="32" Click="OpenWithExternalTools" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.Repository.OpenWithExternalTools}">
<Path Width="13" Height="13" Data="{StaticResource Icons.OpenWith}"/> <Path Width="13" Height="13" Data="{StaticResource Icons.OpenWith}"/>
</Button> </Button>
@ -42,7 +42,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Fetch}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Fetch}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Pull" HotKey="{OnPlatform Ctrl+Shift+Down, macOS=⌘+Shift+Down}"> <Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="Pull" IsVisible="{Binding !IsBare}" IsEnabled="{Binding !IsBare}" HotKey="{OnPlatform Ctrl+Shift+Down, macOS=⌘+Shift+Down}">
<ToolTip.Tip> <ToolTip.Tip>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Pull}"/> <TextBlock Text="{DynamicResource Text.Pull}"/>
@ -64,7 +64,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Push}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Push}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="StashAll"> <Button Classes="icon_button" Width="32" Margin="16,0,0,0" Click="StashAll" IsVisible="{Binding !IsBare}">
<ToolTip.Tip> <ToolTip.Tip>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Stash}"/> <TextBlock Text="{DynamicResource Text.Stash}"/>
@ -75,7 +75,7 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Stashes.Add}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Stashes.Add}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="16,0,0,0" Command="{Binding ApplyPatch}" ToolTip.Tip="{DynamicResource Text.Apply}"> <Button Classes="icon_button" Width="32" Margin="16,0,0,0" Command="{Binding ApplyPatch}" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.Apply}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Diff}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Diff}"/>
</Button> </Button>
@ -88,11 +88,11 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch.Add}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Branch.Add}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitFlowMenu" ToolTip.Tip="{DynamicResource Text.GitFlow}"> <Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitFlowMenu" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.GitFlow}">
<Path Width="14" Height="14" Data="{StaticResource Icons.GitFlow}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.GitFlow}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitLFSMenu" ToolTip.Tip="{DynamicResource Text.GitLFS}"> <Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenGitLFSMenu" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.GitLFS}">
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
</Button> </Button>

View file

@ -59,6 +59,12 @@ namespace SourceGit.Views
var launcher = this.FindAncestorOfType<Launcher>(); var launcher = this.FindAncestorOfType<Launcher>();
if (launcher is not null && DataContext is ViewModels.Repository repo) if (launcher is not null && DataContext is ViewModels.Repository repo)
{ {
if (repo.IsBare)
{
App.RaiseException(repo.FullPath, "Can't run `git pull` in bare repository!");
return;
}
var startDirectly = launcher.HasKeyModifier(KeyModifiers.Control); var startDirectly = launcher.HasKeyModifier(KeyModifiers.Control);
launcher.ClearKeyModifier(); launcher.ClearKeyModifier();
repo.Pull(startDirectly); repo.Pull(startDirectly);

View file

@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
@ -197,7 +196,7 @@ namespace SourceGit.Views
{ {
foreach (var item in items) foreach (var item in items)
{ {
OpenOrInitRepository(item.Path.LocalPath); ViewModels.Welcome.Instance.OpenOrInitRepository(item.Path.LocalPath, null, true);
break; break;
} }
} }
@ -261,7 +260,7 @@ namespace SourceGit.Views
{ {
foreach (var item in items) foreach (var item in items)
{ {
OpenOrInitRepository(item.Path.LocalPath, to); ViewModels.Welcome.Instance.OpenOrInitRepository(item.Path.LocalPath, to, true);
break; break;
} }
} }
@ -290,37 +289,6 @@ namespace SourceGit.Views
} }
} }
private void OpenOrInitRepository(string path, ViewModels.RepositoryNode parent = null)
{
if (!Directory.Exists(path))
{
if (File.Exists(path))
path = Path.GetDirectoryName(path);
else
return;
}
var isBare = new Commands.IsBareRepository(path).Result();
if (isBare)
{
App.RaiseException(string.Empty, $"'{path}' is a bare repository, which is not supported by SourceGit!");
return;
}
var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd();
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
{
ViewModels.Welcome.Instance.InitRepository(path, parent, test.StdErr);
return;
}
var node = ViewModels.Preferences.Instance.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), parent, true);
ViewModels.Welcome.Instance.Refresh();
var launcher = this.FindAncestorOfType<Launcher>()?.DataContext as ViewModels.Launcher;
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
}
private bool _pressedTreeNode = false; private bool _pressedTreeNode = false;
private Point _pressedTreeNodePosition = new Point(); private Point _pressedTreeNodePosition = new Point();
private bool _startDragTreeNode = false; private bool _startDragTreeNode = false;

View file

@ -4,7 +4,6 @@ using System.IO;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.VisualTree;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -36,7 +35,7 @@ namespace SourceGit.Views
{ {
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options); var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1) if (selected.Count == 1)
OpenOrInitRepository(selected[0].Path.LocalPath); ViewModels.Welcome.Instance.OpenOrInitRepository(selected[0].Path.LocalPath, null, false);
} }
catch (Exception exception) catch (Exception exception)
{ {
@ -45,30 +44,6 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void OpenOrInitRepository(string path, ViewModels.RepositoryNode parent = null)
{
if (!Directory.Exists(path))
{
if (File.Exists(path))
path = Path.GetDirectoryName(path);
else
return;
}
var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd();
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
{
ViewModels.Welcome.Instance.InitRepository(path, parent, test.StdErr);
return;
}
var node = ViewModels.Preferences.Instance.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), parent, false);
ViewModels.Welcome.Instance.Refresh();
var launcher = this.FindAncestorOfType<Launcher>()?.DataContext as ViewModels.Launcher;
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
}
} }
} }