diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d4117364..bcb32580 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,14 +19,25 @@ jobs:
os: macos-latest
runtime: osx-arm64
- name : Linux
- os: ubuntu-20.04
+ os: ubuntu-latest
runtime: linux-x64
+ container: ubuntu:20.04
- name : Linux (arm64)
- os: ubuntu-20.04
+ os: ubuntu-latest
runtime: linux-arm64
+ container: ubuntu:20.04
name: Build ${{ matrix.name }}
runs-on: ${{ matrix.os }}
+ container: ${{ matrix.container || '' }}
steps:
+ - name: Install common CLI tools
+ if: ${{ startsWith(matrix.runtime, 'linux-') }}
+ run: |
+ export DEBIAN_FRONTEND=noninteractive
+ ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
+ apt-get update
+ apt-get install -y sudo
+ sudo apt-get install -y curl wget git unzip zip libicu66 tzdata clang
- name: Checkout sources
uses: actions/checkout@v4
- name: Setup .NET
@@ -47,7 +58,7 @@ jobs:
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
sudo apt-get update
- sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
+ sudo apt-get install -y llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
- name: Build
run: dotnet build -c Release
- name: Publish
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 074c9544..2dfc97fd 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -9,10 +9,10 @@ on:
jobs:
windows:
name: Package Windows
- runs-on: ubuntu-latest
+ runs-on: windows-2019
strategy:
matrix:
- runtime: [win-x64, win-arm64]
+ runtime: [ win-x64, win-arm64 ]
steps:
- name: Checkout sources
uses: actions/checkout@v4
@@ -22,6 +22,7 @@ jobs:
name: sourcegit.${{ matrix.runtime }}
path: build/SourceGit
- name: Package
+ shell: bash
env:
VERSION: ${{ inputs.version }}
RUNTIME: ${{ matrix.runtime }}
@@ -69,6 +70,7 @@ jobs:
linux:
name: Package Linux
runs-on: ubuntu-latest
+ container: ubuntu:20.04
strategy:
matrix:
runtime: [linux-x64, linux-arm64]
@@ -77,9 +79,10 @@ jobs:
uses: actions/checkout@v4
- name: Download package dependencies
run: |
- sudo add-apt-repository universe
- sudo apt-get update
- sudo apt-get install desktop-file-utils rpm libfuse2
+ export DEBIAN_FRONTEND=noninteractive
+ ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
+ apt-get update
+ apt-get install -y curl wget git dpkg-dev fakeroot tzdata zip unzip desktop-file-utils rpm libfuse2 file build-essential binutils
- name: Download build
uses: actions/download-artifact@v4
with:
@@ -89,6 +92,7 @@ jobs:
env:
VERSION: ${{ inputs.version }}
RUNTIME: ${{ matrix.runtime }}
+ APPIMAGE_EXTRACT_AND_RUN: 1
run: |
mkdir build/SourceGit
tar -xf "build/sourcegit.${{ matrix.runtime }}.tar" -C build/SourceGit
diff --git a/README.md b/README.md
index dae76783..4086a641 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@
## Translation Status
-[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
+[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
> [!NOTE]
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
diff --git a/SourceGit.sln b/SourceGit.sln
index cf761abd..624322f8 100644
--- a/SourceGit.sln
+++ b/SourceGit.sln
@@ -60,6 +60,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DEBIAN", "DEBIAN", "{F101849D-BDB7-40D4-A516-751150C3CCFC}"
ProjectSection(SolutionItems) = preProject
build\resources\deb\DEBIAN\control = build\resources\deb\DEBIAN\control
+ build\resources\deb\DEBIAN\preinst = build\resources\deb\DEBIAN\preinst
+ build\resources\deb\DEBIAN\prerm = build\resources\deb\DEBIAN\prerm
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rpm", "rpm", "{9BA0B044-0CC9-46F8-B551-204F149BF45D}"
diff --git a/TRANSLATION.md b/TRANSLATION.md
index 716ddd3a..a5abbbba 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -1,4 +1,4 @@
-### de_DE.axaml: 99.21%
+### de_DE.axaml: 99.08%
@@ -9,21 +9,22 @@
- Text.Diff.First
- Text.Diff.Last
- Text.Preferences.AI.Streaming
+- Text.Preferences.Appearance.EditorTabWidth
- Text.StashCM.SaveAsPatch
-### es_ES.axaml: 99.87%
+### es_ES.axaml: 100.00%
Missing Keys
-- Text.StashCM.SaveAsPatch
+
-### fr_FR.axaml: 91.80%
+### fr_FR.axaml: 91.68%
@@ -56,6 +57,7 @@
- Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets
- Text.Preferences.AI.Streaming
+- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.Appearance.FontSize
- Text.Preferences.Appearance.FontSize.Default
- Text.Preferences.Appearance.FontSize.Editor
@@ -94,17 +96,17 @@
-### it_IT.axaml: 100.00%
+### it_IT.axaml: 99.87%
Missing Keys
-
+- Text.Preferences.Appearance.EditorTabWidth
-### pt_BR.axaml: 91.53%
+### pt_BR.axaml: 91.41%
@@ -148,6 +150,7 @@
- Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets
- Text.Preferences.AI.Streaming
+- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.DateFormat
- Text.Preferences.General.ShowChildren
- Text.Preferences.Git.SSLVerify
@@ -177,19 +180,13 @@
-### ru_RU.axaml: 99.07%
+### ru_RU.axaml: 100.00%
Missing Keys
-- Text.BranchCM.CustomAction
-- Text.BranchUpstreamInvalid
-- Text.Configure.CustomAction.Scope.Branch
-- Text.Diff.First
-- Text.Diff.Last
-- Text.Preferences.AI.Streaming
-- Text.StashCM.SaveAsPatch
+
diff --git a/VERSION b/VERSION
index a241ab9b..a75bd422 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2025.07
\ No newline at end of file
+2025.08
\ No newline at end of file
diff --git a/build/resources/deb/DEBIAN/preinst b/build/resources/deb/DEBIAN/preinst
new file mode 100755
index 00000000..a93f8090
--- /dev/null
+++ b/build/resources/deb/DEBIAN/preinst
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+# summary of how this script can be called:
+# * `install'
+# * `install'
+# * `upgrade'
+# * `abort-upgrade'
+# for details, see http://www.debian.org/doc/debian-policy/
+
+case "$1" in
+ install|upgrade)
+ # Check if SourceGit is running and stop it
+ if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then
+ echo "Stopping running SourceGit instance..."
+ pkill -f '/opt/sourcegit/sourcegit' || true
+ # Give the process a moment to terminate
+ sleep 1
+ fi
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/build/resources/deb/DEBIAN/prerm b/build/resources/deb/DEBIAN/prerm
new file mode 100755
index 00000000..c2c9e4f0
--- /dev/null
+++ b/build/resources/deb/DEBIAN/prerm
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+set -e
+
+# summary of how this script can be called:
+# * `remove'
+# * `upgrade'
+# * `failed-upgrade'
+# * `remove' `in-favour'
+# * `deconfigure' `in-favour'
+# `removing'
+#
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then
+ echo "Stopping running SourceGit instance..."
+ pkill -f '/opt/sourcegit/sourcegit' || true
+ # Give the process a moment to terminate
+ sleep 1
+ fi
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/build/scripts/package.windows.sh b/build/scripts/package.windows.sh
index 6bd3879b..1a8f99c1 100755
--- a/build/scripts/package.windows.sh
+++ b/build/scripts/package.windows.sh
@@ -9,4 +9,8 @@ cd build
rm -rf SourceGit/*.pdb
-zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit
+if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then
+ powershell -Command "Compress-Archive -Path SourceGit\\* -DestinationPath \"sourcegit_$VERSION.$RUNTIME.zip\" -Force"
+else
+ zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit
+fi
diff --git a/src/App.axaml.cs b/src/App.axaml.cs
index 95b396de..25e32323 100644
--- a/src/App.axaml.cs
+++ b/src/App.axaml.cs
@@ -445,10 +445,14 @@ namespace SourceGit
var file = args[1];
if (!File.Exists(file))
+ {
desktop.Shutdown(-1);
- else
- desktop.MainWindow = new Views.StandaloneCommitMessageEditor(file);
+ return true;
+ }
+ var editor = new Views.StandaloneCommitMessageEditor();
+ editor.SetFile(file);
+ desktop.MainWindow = editor;
return true;
}
@@ -461,7 +465,9 @@ namespace SourceGit
var args = desktop.Args;
if (args?.Length > 0)
{
- desktop.MainWindow = new Views.Askpass(args[0]);
+ var askpass = new Views.Askpass();
+ askpass.TxtDescription.Text = args[0];
+ desktop.MainWindow = askpass;
return true;
}
diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs
index da971e58..8ae6350f 100644
--- a/src/Commands/Diff.cs
+++ b/src/Commands/Diff.cs
@@ -68,6 +68,18 @@ namespace SourceGit.Commands
return;
}
+ if (line.StartsWith("deleted file mode ", StringComparison.Ordinal))
+ {
+ _result.OldMode = line.Substring(18);
+ return;
+ }
+
+ if (line.StartsWith("new file mode ", StringComparison.Ordinal))
+ {
+ _result.NewMode = line.Substring(14);
+ return;
+ }
+
if (_result.IsBinary)
return;
diff --git a/src/Commands/IsCommitSHA.cs b/src/Commands/IsCommitSHA.cs
new file mode 100644
index 00000000..1b0c50e3
--- /dev/null
+++ b/src/Commands/IsCommitSHA.cs
@@ -0,0 +1,17 @@
+namespace SourceGit.Commands
+{
+ public class IsCommitSHA : Command
+ {
+ public IsCommitSHA(string repo, string hash)
+ {
+ WorkingDirectory = repo;
+ Args = $"cat-file -t {hash}";
+ }
+
+ public bool Result()
+ {
+ var rs = ReadToEnd();
+ return rs.IsSuccess && rs.StdOut.Trim().Equals("commit");
+ }
+ }
+}
diff --git a/src/Commands/Pull.cs b/src/Commands/Pull.cs
index a4efa4b6..35a6289a 100644
--- a/src/Commands/Pull.cs
+++ b/src/Commands/Pull.cs
@@ -11,10 +11,11 @@ namespace SourceGit.Commands
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
- Args = "pull --verbose --progress --tags ";
+ Args = "pull --verbose --progress ";
if (useRebase)
- Args += "--rebase ";
+ Args += "--rebase=true ";
+
if (noTags)
Args += "--no-tags ";
diff --git a/src/Commands/QueryCommitsWithFullMessage.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs
similarity index 86%
rename from src/Commands/QueryCommitsWithFullMessage.cs
rename to src/Commands/QueryCommitsForInteractiveRebase.cs
index c15cdbe1..232d86e5 100644
--- a/src/Commands/QueryCommitsWithFullMessage.cs
+++ b/src/Commands/QueryCommitsForInteractiveRebase.cs
@@ -3,18 +3,18 @@ using System.Collections.Generic;
namespace SourceGit.Commands
{
- public class QueryCommitsWithFullMessage : Command
+ public class QueryCommitsForInteractiveRebase : Command
{
- public QueryCommitsWithFullMessage(string repo, string args)
+ public QueryCommitsForInteractiveRebase(string repo, string on)
{
_boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----";
WorkingDirectory = repo;
Context = repo;
- Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}";
+ Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
}
- public List Result()
+ public List Result()
{
var rs = ReadToEnd();
if (!rs.IsSuccess)
@@ -29,7 +29,7 @@ namespace SourceGit.Commands
switch (nextPartIdx)
{
case 0:
- _current = new Models.CommitWithMessage();
+ _current = new Models.InteractiveCommit();
_current.Commit.SHA = line;
_commits.Add(_current);
break;
@@ -52,7 +52,7 @@ namespace SourceGit.Commands
_current.Commit.CommitterTime = ulong.Parse(line);
break;
default:
- var boundary = rs.StdOut.IndexOf(_boundary, end + 1);
+ var boundary = rs.StdOut.IndexOf(_boundary, end + 1, StringComparison.Ordinal);
if (boundary > end)
{
_current.Message = rs.StdOut.Substring(start, boundary - start - 1);
@@ -88,8 +88,8 @@ namespace SourceGit.Commands
_current.Commit.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
}
- private List _commits = new List();
- private Models.CommitWithMessage _current = null;
+ private List _commits = [];
+ private Models.InteractiveCommit _current = null;
private string _boundary = "";
}
}
diff --git a/src/Commands/QueryRevisionByRefName.cs b/src/Commands/QueryRevisionByRefName.cs
new file mode 100644
index 00000000..7fb4ecfa
--- /dev/null
+++ b/src/Commands/QueryRevisionByRefName.cs
@@ -0,0 +1,21 @@
+namespace SourceGit.Commands
+{
+ public class QueryRevisionByRefName : Command
+ {
+ public QueryRevisionByRefName(string repo, string refname)
+ {
+ WorkingDirectory = repo;
+ Context = repo;
+ Args = $"rev-parse {refname}";
+ }
+
+ public string Result()
+ {
+ var rs = ReadToEnd();
+ if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut))
+ return rs.StdOut.Trim();
+
+ return null;
+ }
+ }
+}
diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs
index f015130a..5c48b0c0 100644
--- a/src/Models/Commit.cs
+++ b/src/Models/Commit.cs
@@ -112,9 +112,9 @@ namespace SourceGit.Models
}
}
- public class CommitWithMessage
+ public class CommitFullMessage
{
- public Commit Commit { get; set; } = new Commit();
- public string Message { get; set; } = "";
+ public string Message { get; set; } = string.Empty;
+ public List Links { get; set; } = [];
}
}
diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs
index e0ae82e0..88992e10 100644
--- a/src/Models/DiffResult.cs
+++ b/src/Models/DiffResult.cs
@@ -681,6 +681,18 @@ namespace SourceGit.Models
public TextDiff TextDiff { get; set; } = null;
public LFSDiff LFSDiff { get; set; } = null;
- public string FileModeChange => string.IsNullOrEmpty(OldMode) ? string.Empty : $"{OldMode} → {NewMode}";
+ public string FileModeChange
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(OldMode) && string.IsNullOrEmpty(NewMode))
+ return string.Empty;
+
+ var oldDisplay = string.IsNullOrEmpty(OldMode) ? "0" : OldMode;
+ var newDisplay = string.IsNullOrEmpty(NewMode) ? "0" : NewMode;
+
+ return $"{oldDisplay} → {newDisplay}";
+ }
+ }
}
}
diff --git a/src/Models/InteractiveRebase.cs b/src/Models/InteractiveRebase.cs
index 0980587a..691aadeb 100644
--- a/src/Models/InteractiveRebase.cs
+++ b/src/Models/InteractiveRebase.cs
@@ -12,6 +12,12 @@ namespace SourceGit.Models
Drop,
}
+ public class InteractiveCommit
+ {
+ public Commit Commit { get; set; } = new Commit();
+ public string Message { get; set; } = string.Empty;
+ }
+
public class InteractiveRebaseJob
{
public string SHA { get; set; } = string.Empty;
diff --git a/src/Models/RevisionFile.cs b/src/Models/RevisionFile.cs
index f1f5265f..8cc1be2a 100644
--- a/src/Models/RevisionFile.cs
+++ b/src/Models/RevisionFile.cs
@@ -29,6 +29,6 @@ namespace SourceGit.Models
public class RevisionSubmodule
{
public Commit Commit { get; set; } = null;
- public string FullMessage { get; set; } = string.Empty;
+ public CommitFullMessage FullMessage { get; set; } = null;
}
}
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 5208a269..5df3ca71 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -464,6 +464,7 @@
Enable Streaming
APPEARANCE
Default Font
+ Editor Tab Width
Font Size
Default
Editor
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index bf635321..4073f512 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -24,17 +24,17 @@
RE-GENERAR
Usar OpenAI para generar mensaje de commit
APLICAR CÓMO MENSAJE DE COMMIT
- Aplicar Patch
+ Aplicar Parche
Error
- Genera errores y se niega a aplicar el patch
+ Genera errores y se niega a aplicar el parche
Error Todo
Similar a 'error', pero muestra más
- Archivo Patch:
+ Archivo del Parche:
Seleccionar archivo .patch para aplicar
Ignorar cambios de espacios en blanco
Sin Advertencia
Desactiva la advertencia de espacios en blanco al final
- Aplicar Patch
+ Aplicar Parche
Advertencia
Genera advertencias para algunos de estos errores, pero aplica
Espacios en Blanco:
@@ -126,7 +126,7 @@
Reset ${0}$ hasta Aquí
Revertir Commit
Reescribir
- Guardar como Patch...
+ Guardar como Parche...
Squash en Parent
Squash Commits Hijos hasta Aquí
CAMBIOS
@@ -259,7 +259,7 @@
Siguiente Diferencia
SIN CAMBIOS O SOLO CAMBIOS DE EOL
Diferencia Anterior
- Guardar como Patch
+ Guardar como Parche
Mostrar símbolos ocultos
Diferencia Lado a Lado
SUBMÓDULO
@@ -300,7 +300,7 @@
Descartar Cambios en Línea(s) Seleccionada(s)
Abrir Herramienta de Merge Externa
Resolver usando ${0}$
- Guardar Como Patch...
+ Guardar como Parche...
Stage
Stage {0} archivos
Stage Cambios en Línea(s) Seleccionada(s)
@@ -468,6 +468,7 @@
Activar Transmisión
APARIENCIA
Fuente por defecto
+ Ancho de la Pestaña del Editor
Tamaño de fuente
Por defecto
Editor
@@ -638,7 +639,7 @@
Ejecutando. Por favor espera...
GUARDAR
Guardar Como...
- ¡El patch se ha guardado exitosamente!
+ ¡El parche se ha guardado exitosamente!
Escanear Repositorios
Directorio Raíz:
Buscar Actualizaciones...
@@ -672,6 +673,7 @@
Aplicar
Eliminar
Pop
+ Guardar como Parche...
Eliminar Stash
Eliminar:
Stashes
diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml
index 4468650b..b15a769b 100644
--- a/src/Resources/Locales/ru_RU.axaml
+++ b/src/Resources/Locales/ru_RU.axaml
@@ -20,21 +20,21 @@
Имя целевого каталога по умолчанию. (необязательно)
Отслеживание ветки:
Отслеживание внешней ветки
- OpenAI Ассистент
+ Помощник OpenAI
ПЕРЕСОЗДАТЬ
Использовать OpenAI для создания сообщения о ревизии
ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ
Исправить
Ошибка
- Выдает ошибки и отказывается применять исправление
+ Выдает ошибки и отказывается применять заплатку
Все ошибки
Аналогично «ошибке», но показывает больше
- Файл исправлений:
+ Файл заплатки:
Выберите файл .patch для применения
Игнорировать изменения пробелов
Нет предупреждений
Отключить предупреждения о пробелах в конце
- Применить исправление
+ Применить заплатку
Предупреждать
Выдавать предупреждения о нескольких таких ошибках, но применять
Пробел:
@@ -58,6 +58,7 @@
Сравнить с ГОЛОВОЙ (HEAD)
Сравнить с рабочим каталогом
Копировать имя ветки
+ Изменить действие
Удалить ${0}$...
Удалить выбранные {0} ветки
Отклонить все изменения.
@@ -73,6 +74,7 @@
Переименовать ${0}$...
Отслеживать ветку...
Сравнение веток
+ Недопустимая основная ветка!
Байты
ОТМЕНА
Сбросить эту ревизию
@@ -105,7 +107,7 @@
Локальное имя:
Имя репозитория. (необязательно).
Родительский каталог:
- Инициализировать и обновить подмодуль
+ Создать и обновить подмодуль
Адрес репозитория:
ЗАКРЫТЬ
Редактор
@@ -119,7 +121,7 @@
Пользовательское действие
Интерактивное перемещение (rebase -i) ${0}$ сюда
Влить в ${0}$
- Влить ветки...
+ Влить ...
Переместить ${0}$ сюда
Сбросить ${0}$ сюда
Отменить ревизию
@@ -137,7 +139,7 @@
АВТОР
ИЗМЕНЁННЫЙ
ДОЧЕРНИЙ
- РЕВИЗОР(ИСПОЛНИТЕЛЬ)
+ РЕВИЗОР (ИСПОЛНИТЕЛЬ)
Найти все ветки с этой ревизией
ВЕТКИ С ЭТОЙ РЕВИЗИЕЙ
Отображаются только первые 100 изменений. Смотрите все изменения на вкладке ИЗМЕНЕНИЯ.
@@ -158,6 +160,7 @@
Исполняемый файл:
Имя:
Диапазон:
+ Ветка
Ревизия
Репозиторий
Ждать для выполения выхода
@@ -250,13 +253,15 @@
СТАРЫЙ
Копировать
Режим файла изменён
+ Первое различие
Игнорировать изменение пробелов
+ Последнее различие
Показывать скрытые символы
ИЗМЕНЕНИЕ ОБЪЕКТА LFS
Следующее различие
НИКАКИХ ИЗМЕНЕНИЙ ИЛИ МЕНЯЕТСЯ ТОЛЬКО EOL
Предыдущее различие
- Сохранить как исправление
+ Сохранить как заплатку
Различие бок о бок
ПОДМОДУЛЬ
НОВЫЙ
@@ -286,7 +291,7 @@
Быстрая перемотка вперёд (без проверки)
Извлечь
Извлечь все внешние репозитории
- Разрешить опцию '--force'
+ Разрешить опцию (--force)
Извлечь без меток
Внешний репозиторий:
Извлечь внешние изменения
@@ -296,7 +301,7 @@
Отменить изменения в выбранной(ых) строке(ах)
Открыть расширенный инструмент слияния
Взять версию ${0}$
- Сохранить как patch-файл...
+ Сохранить как файл заплатки...
Подготовить
Подготовленные {0} файлы
Подготовленные изменения в выбранной(ых) строке(ах)
@@ -320,7 +325,7 @@
Цель:
Исправление:
Префикс исправлений:
- Инициализировать Git-поток
+ Создать Git-поток
Держать ветку
Производственная ветка:
Выпуск:
@@ -403,7 +408,7 @@
Подготовить
Снять из подготовленных
Отклонить
- Инициализировать репозиторий
+ Создать репозиторий
Путь:
Выполняется частичный перенос ревизий (cherry-pick).
Обрабтка ревизии.
@@ -460,10 +465,12 @@
Модель
Имя:
Сервер
+ Разрешить потоковую передачу
ВИД
Шрифт по умолчанию
Размер шрифта
По умолчанию
+ Редактировать ширину вкладки
Редактор
Моноширный шрифт
В текстовом редакторе используется только моноширный шрифт
@@ -488,7 +495,7 @@
Каталог клонирования по умолчанию
Электроная почта пользователя
Общая электроная почта пользователя git
- Разрешить '--prune' при скачивании
+ Разрешить (--prune) при скачивании
Путь установки
Разрешить верификацию HTTP SSL
Имя пользователя
@@ -555,7 +562,7 @@
Открыть в браузере
Удалить
Подтвердить удаление рабочего каталога
- Включить опцию --force
+ Включить опцию (--force)
Цель:
Переименовать ветку
Новое имя:
@@ -578,7 +585,7 @@
Скрыть в графе ревизии
Фильтр в графе ревизии
ОТФИЛЬТРОВАНО:
- Включить опцию --first-parent
+ Включить опцию (--first-parent)
РАСПОЛОЖЕНИЕ
Горизонтально
Вертикально
@@ -633,7 +640,7 @@
Запуск. Подождите пожалуйста...
СОХРАНИТЬ
Сохранить как...
- Исправление успешно сохранено!
+ Заплатка успешно сохранена!
Сканирование репозиторий
Корневой каталог:
Копировать SHA
@@ -667,6 +674,7 @@
Принять
Отбросить
Применить
+ Сохранить как заплатку...
Отбросить тайник
Отбросить:
Отложенные
@@ -674,7 +682,7 @@
ОТЛОЖЕННЫЕ
Статистика
РЕВИЗИИ
- РЕВИЗОРЫ(ИСПОЛНИТЕЛИ)
+ РЕВИЗОРЫ (ИСПОЛНИТЕЛИ)
МЕСЯЦ
НЕДЕЛЯ
РЕВИЗИИ:
@@ -697,10 +705,10 @@
Сетевой адрес:
Обновление подмодулей
Все подмодули
- Инициализировать по необходимости
+ Создавать по необходимости
Рекурсивно
Подмодуль:
- Использовать опцию '--remote'
+ Использовать опцию (--remote)
Предупреждение
Приветствие
Создать группу
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 0e8b9f7d..72b434f9 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -467,6 +467,7 @@
启用流式输出
外观配置
缺省字体
+ 编辑器制表符宽度
字体大小
默认
代码编辑器
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index f4cfad08..bc9991f6 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -467,6 +467,7 @@
啟用串流輸出
外觀設定
預設字型
+ 編輯器制表符寬度
字型大小
預設
程式碼
diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml
index 9b43d8af..38321356 100644
--- a/src/Resources/Styles.axaml
+++ b/src/Resources/Styles.axaml
@@ -1299,6 +1299,8 @@
+
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
+
+
-
+
diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs
index e3140191..b8c09b35 100644
--- a/src/Views/Launcher.axaml.cs
+++ b/src/Views/Launcher.axaml.cs
@@ -112,8 +112,19 @@ namespace SourceGit.Views
// We should clear all unhandled key modifiers.
_unhandledModifiers = KeyModifiers.None;
+ // Check for AltGr (which is detected as Ctrl+Alt)
+ bool isAltGr = e.KeyModifiers.HasFlag(KeyModifiers.Control) &&
+ e.KeyModifiers.HasFlag(KeyModifiers.Alt);
+
+ // Skip hotkey processing if AltGr is pressed
+ if (isAltGr)
+ {
+ base.OnKeyDown(e);
+ return;
+ }
+
// Ctrl+Shift+P opens preference dialog (macOS use hotkeys in system menu bar)
- if (!OperatingSystem.IsMacOS() && e.KeyModifiers == (KeyModifiers.Control | KeyModifiers.Shift) && e.Key == Key.P)
+ if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: (KeyModifiers.Control | KeyModifiers.Shift), Key: Key.P })
{
App.OpenDialog(new Preferences());
e.Handled = true;
@@ -243,13 +254,13 @@ namespace SourceGit.Views
{
_unhandledModifiers = e.KeyModifiers;
- if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && (e.Key == Key.LeftAlt || e.Key == Key.RightAlt))
+ if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && e.Key is Key.LeftAlt or Key.RightAlt)
_unhandledModifiers |= KeyModifiers.Alt;
- if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl))
+ if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && e.Key is Key.LeftCtrl or Key.RightCtrl)
_unhandledModifiers |= KeyModifiers.Control;
- if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && (e.Key == Key.LeftShift || e.Key == Key.RightShift))
+ if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && e.Key is Key.LeftShift or Key.RightShift)
_unhandledModifiers |= KeyModifiers.Shift;
}
}
diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml
index 3bdd150a..12679e50 100644
--- a/src/Views/Preferences.axaml
+++ b/src/Views/Preferences.axaml
@@ -148,7 +148,7 @@
-
+
+ Minimum="10" Maximum="18" Increment="0.5"
+ Height="28"
+ Padding="4"
+ BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
+ CornerRadius="3"
+ Value="{Binding DefaultFontSize, Mode=TwoWay}">
@@ -218,10 +218,23 @@
+
+
+
+
+
-
@@ -232,16 +245,16 @@
-
-
-
@@ -63,7 +64,7 @@
-
+
diff --git a/src/Views/RevisionFileContentViewer.axaml.cs b/src/Views/RevisionFileContentViewer.axaml.cs
index c74f2db2..16f4fc83 100644
--- a/src/Views/RevisionFileContentViewer.axaml.cs
+++ b/src/Views/RevisionFileContentViewer.axaml.cs
@@ -15,6 +15,15 @@ namespace SourceGit.Views
{
public class RevisionTextFileView : TextEditor
{
+ public static readonly StyledProperty TabWidthProperty =
+ AvaloniaProperty.Register(nameof(TabWidth), 4);
+
+ public int TabWidth
+ {
+ get => GetValue(TabWidthProperty);
+ set => SetValue(TabWidthProperty, value);
+ }
+
protected override Type StyleKeyOverride => typeof(TextEditor);
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
@@ -22,13 +31,16 @@ namespace SourceGit.Views
IsReadOnly = true;
ShowLineNumbers = true;
WordWrap = false;
+
+ Options.IndentationSize = TabWidth;
+ Options.EnableHyperlinks = false;
+ Options.EnableEmailHyperlinks = false;
+
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
TextArea.LeftMargins[0].Margin = new Thickness(8, 0);
TextArea.TextView.Margin = new Thickness(4, 0);
- TextArea.TextView.Options.EnableHyperlinks = false;
- TextArea.TextView.Options.EnableEmailHyperlinks = false;
}
protected override void OnLoaded(RoutedEventArgs e)
@@ -69,6 +81,16 @@ namespace SourceGit.Views
}
}
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == TabWidthProperty)
+ {
+ Options.IndentationSize = TabWidth;
+ }
+ }
+
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
{
var selected = SelectedText;
diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml
index 3d5cff38..6847b14b 100644
--- a/src/Views/RevisionFiles.axaml
+++ b/src/Views/RevisionFiles.axaml
@@ -44,7 +44,7 @@
+ IsOpen="{Binding RevisionFileSearchSuggestion, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
0)
{
SearchSuggestionBox.Focus(NavigationMethod.Tab);
SearchSuggestionBox.SelectedIndex = 0;
@@ -33,12 +33,7 @@ namespace SourceGit.Views
}
else if (e.Key == Key.Escape)
{
- if (vm.IsRevisionFileSearchSuggestionOpen)
- {
- vm.RevisionFileSearchSuggestion.Clear();
- vm.IsRevisionFileSearchSuggestionOpen = false;
- }
-
+ vm.CancelRevisionFileSuggestions();
e.Handled = true;
}
}
@@ -57,7 +52,7 @@ namespace SourceGit.Views
if (e.Key == Key.Escape)
{
- vm.RevisionFileSearchSuggestion.Clear();
+ vm.CancelRevisionFileSuggestions();
e.Handled = true;
}
else if (e.Key == Key.Enter && SearchSuggestionBox.SelectedItem is string content)
diff --git a/src/Views/StandaloneCommitMessageEditor.axaml.cs b/src/Views/StandaloneCommitMessageEditor.axaml.cs
index 6833fb33..8a49ee74 100644
--- a/src/Views/StandaloneCommitMessageEditor.axaml.cs
+++ b/src/Views/StandaloneCommitMessageEditor.axaml.cs
@@ -9,18 +9,14 @@ namespace SourceGit.Views
{
public StandaloneCommitMessageEditor()
{
- _file = string.Empty;
- DataContext = this;
InitializeComponent();
}
- public StandaloneCommitMessageEditor(string file)
+ public void SetFile(string file)
{
_file = file;
- DataContext = this;
- InitializeComponent();
- var content = File.ReadAllText(file).ReplaceLineEndings("\n");
+ var content = File.ReadAllText(file).ReplaceLineEndings("\n").Trim();
var firstLineEnd = content.IndexOf('\n');
if (firstLineEnd == -1)
{
@@ -29,7 +25,7 @@ namespace SourceGit.Views
else
{
Editor.SubjectEditor.Text = content.Substring(0, firstLineEnd);
- Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1);
+ Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1).Trim();
}
}
@@ -41,12 +37,16 @@ namespace SourceGit.Views
private void SaveAndClose(object _1, RoutedEventArgs _2)
{
- File.WriteAllText(_file, Editor.Text);
- _exitCode = 0;
+ if (!string.IsNullOrEmpty(_file))
+ {
+ File.WriteAllText(_file, Editor.Text);
+ _exitCode = 0;
+ }
+
Close();
}
- private readonly string _file;
+ private string _file = string.Empty;
private int _exitCode = -1;
}
}
diff --git a/src/Views/TextDiffView.axaml b/src/Views/TextDiffView.axaml
index 3ea7af14..7ea6b44b 100644
--- a/src/Views/TextDiffView.axaml
+++ b/src/Views/TextDiffView.axaml
@@ -27,6 +27,7 @@
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
+ TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@@ -59,6 +60,7 @@
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
+ TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="False"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@@ -81,6 +83,7 @@
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
+ TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="False"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs
index dccbb9b2..925c7622 100644
--- a/src/Views/TextDiffView.axaml.cs
+++ b/src/Views/TextDiffView.axaml.cs
@@ -60,7 +60,7 @@ namespace SourceGit.Views
public class ThemedTextDiffPresenter : TextEditor
{
- public class VerticalSeperatorMargin : AbstractMargin
+ public class VerticalSeparatorMargin : AbstractMargin
{
public override void Render(DrawingContext context)
{
@@ -475,6 +475,15 @@ namespace SourceGit.Views
set => SetValue(ShowHiddenSymbolsProperty, value);
}
+ public static readonly StyledProperty TabWidthProperty =
+ AvaloniaProperty.Register(nameof(TabWidth), 4);
+
+ public int TabWidth
+ {
+ get => GetValue(TabWidthProperty);
+ set => SetValue(TabWidthProperty, value);
+ }
+
public static readonly StyledProperty EnableChunkSelectionProperty =
AvaloniaProperty.Register(nameof(EnableChunkSelection));
@@ -519,12 +528,13 @@ namespace SourceGit.Views
ShowLineNumbers = false;
BorderThickness = new Thickness(0);
+ Options.IndentationSize = TabWidth;
+ Options.EnableHyperlinks = false;
+ Options.EnableEmailHyperlinks = false;
+
_lineStyleTransformer = new LineStyleTransformer(this);
TextArea.TextView.Margin = new Thickness(2, 0);
- TextArea.TextView.Options.EnableHyperlinks = false;
- TextArea.TextView.Options.EnableEmailHyperlinks = false;
-
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
}
@@ -734,10 +744,14 @@ namespace SourceGit.Views
}
else if (change.Property == ShowHiddenSymbolsProperty)
{
- var val = change.NewValue is true;
+ var val = ShowHiddenSymbols;
Options.ShowTabs = val;
Options.ShowSpaces = val;
}
+ else if (change.Property == TabWidthProperty)
+ {
+ Options.IndentationSize = TabWidth;
+ }
else if (change.Property == FileNameProperty)
{
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
@@ -1007,8 +1021,8 @@ namespace SourceGit.Views
if (startPosition.Location > endPosition.Location)
(startPosition, endPosition) = (endPosition, startPosition);
- var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1);
- var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1);
+ var startIdx = startPosition.Line - 1;
+ var endIdx = endPosition.Line - 1;
if (startIdx == endIdx)
{
@@ -1025,25 +1039,35 @@ namespace SourceGit.Views
}
var builder = new StringBuilder();
- for (var i = startIdx; i <= endIdx; i++)
+ for (var i = startIdx; i <= endIdx && i <= lines.Count - 1; i++)
{
var line = lines[i];
if (line.Type == Models.TextDiffLineType.Indicator ||
line.Type == Models.TextDiffLineType.None)
continue;
+ // The first selected line (partial selection)
if (i == startIdx && startPosition.Column > 1)
{
builder.AppendLine(line.Content.Substring(startPosition.Column - 1));
continue;
}
- if (i == endIdx && endPosition.Column < line.Content.Length)
+ // The selection range is larger than original source.
+ if (i == lines.Count - 1 && i < endIdx)
{
- builder.AppendLine(line.Content.Substring(0, endPosition.Column));
- continue;
+ builder.Append(line.Content);
+ break;
}
+ // For the last line (selection range is within original source)
+ if (i == endIdx)
+ {
+ builder.Append(endPosition.Column - 1 < line.Content.Length ? line.Content.Substring(0, endPosition.Column - 1) : line.Content);
+ break;
+ }
+
+ // Other lines.
builder.AppendLine(line.Content);
}
@@ -1061,9 +1085,9 @@ namespace SourceGit.Views
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
{
TextArea.LeftMargins.Add(new LineNumberMargin(false, true));
- TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
+ TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
TextArea.LeftMargins.Add(new LineNumberMargin(false, false));
- TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
+ TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
}
@@ -1262,7 +1286,7 @@ namespace SourceGit.Views
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
{
TextArea.LeftMargins.Add(new LineNumberMargin(true, false));
- TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
+ TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
}
diff --git a/src/Views/WorkingCopy.axaml b/src/Views/WorkingCopy.axaml
index ebf26a96..e5728df2 100644
--- a/src/Views/WorkingCopy.axaml
+++ b/src/Views/WorkingCopy.axaml
@@ -211,7 +211,12 @@
-
+
@@ -225,18 +230,15 @@
FontSize="11"
VerticalAlignment="Center"
UseGraphColor="False"/>
-
+
-
-
-
-
-
-
-
-
@@ -397,7 +399,8 @@
Width="0" Height="0"
Background="Transparent"
Command="{Binding CommitWithAutoStage}"
- HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"/>
+ HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
+ IsEnabled="{Binding !IsCommitting}"/>