diff --git a/.editorconfig b/.editorconfig
index dedc5722..56725e7b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -100,7 +100,7 @@ dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
-dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
@@ -206,6 +206,9 @@ dotnet_diagnostic.CA1854.severity = warning
#CA2211:Non-constant fields should not be visible
dotnet_diagnostic.CA2211.severity = error
+# IDE0005: remove used namespace using
+dotnet_diagnostic.IDE0005.severity = error
+
# Wrapping preferences
csharp_wrap_before_ternary_opsigns = false
@@ -292,3 +295,12 @@ indent_size = 2
end_of_line = lf
[*.{cmd,bat}]
end_of_line = crlf
+
+# Package manifests
+[{*.spec,control}]
+end_of_line = lf
+
+# YAML files
+[*.{yml,yaml}]
+indent_size = 2
+end_of_line = lf
diff --git a/.gitattributes b/.gitattributes
index 69139978..bd1dfea9 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,78 +1,14 @@
-# Auto detect text files and perform LF normalization
-# https://www.davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
* text=auto
-
-#
-# The above will handle all files NOT found below
-#
-
-# Documents
-*.bibtex text diff=bibtex
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
*.md text
-*.tex text diff=tex
-*.adoc text
-*.textile text
-*.mustache text
-*.csv text
-*.tab text
-*.tsv text
-*.txt text
-*.sql text
-
-# Graphics
*.png binary
-*.jpg binary
-*.jpeg binary
-*.gif binary
-*.tif binary
-*.tiff binary
*.ico binary
-# SVG treated as an asset (binary) by default.
-*.svg text
-# If you want to treat it as binary,
-# use the following line instead.
-# *.svg binary
-*.eps binary
-
-# Scripts
-*.bash text eol=lf
-*.fish text eol=lf
*.sh text eol=lf
-# These are explicitly windows files and should use crlf
+*.spec text eol=lf
+control text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
-
-# Serialisation
*.json text
-*.toml text
-*.xml text
-*.yaml text
-*.yml text
-
-# Archives
-*.7z binary
-*.gz binary
-*.tar binary
-*.tgz binary
-*.zip binary
-
-# Text files where line endings should be preserved
-*.patch -text
-
-#
-# Exclude files from exporting
-#
.gitattributes export-ignore
-.gitignore export-ignore
\ No newline at end of file
+.gitignore export-ignore
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ad62efb6..12792cf6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,20 +19,31 @@ 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
uses: actions/setup-dotnet@v4
with:
- dotnet-version: 8.0.x
+ dotnet-version: 9.0.x
- name: Configure arm64 packages
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
@@ -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
- name: Build
run: dotnet build -c Release
- name: Publish
diff --git a/.github/workflows/localization-check.yml b/.github/workflows/localization-check.yml
new file mode 100644
index 00000000..8dcd61c8
--- /dev/null
+++ b/.github/workflows/localization-check.yml
@@ -0,0 +1,41 @@
+name: Localization Check
+on:
+ push:
+ branches: [ develop ]
+ paths:
+ - 'src/Resources/Locales/**'
+ workflow_dispatch:
+ workflow_call:
+
+jobs:
+ localization-check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+
+ - name: Install dependencies
+ run: npm install fs-extra@11.2.0 path@0.12.7 xml2js@0.6.2
+
+ - name: Run localization check
+ run: node build/scripts/localization-check.js
+
+ - name: Commit changes
+ run: |
+ git config --global user.name 'github-actions[bot]'
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
+ if [ -n "$(git status --porcelain)" ]; then
+ git add TRANSLATION.md src/Resources/Locales/*.axaml
+ git commit -m 'doc: Update translation status and sort locale files'
+ git push
+ else
+ echo "No changes to commit"
+ fi
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 53affe3d..2dfc97fd 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -3,16 +3,16 @@ on:
workflow_call:
inputs:
version:
- description: Source Git package version
+ description: SourceGit package version
required: true
type: string
jobs:
- windows-portable:
- name: Package portable Windows app
- runs-on: ubuntu-latest
+ windows:
+ name: Package Windows
+ 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,10 +22,11 @@ jobs:
name: sourcegit.${{ matrix.runtime }}
path: build/SourceGit
- name: Package
+ shell: bash
env:
VERSION: ${{ inputs.version }}
RUNTIME: ${{ matrix.runtime }}
- run: ./build/scripts/package.windows-portable.sh
+ run: ./build/scripts/package.windows.sh
- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
@@ -36,7 +37,7 @@ jobs:
with:
name: sourcegit.${{ matrix.runtime }}
osx-app:
- name: Package OSX app
+ name: Package macOS
runs-on: macos-latest
strategy:
matrix:
@@ -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/.github/workflows/release.yml b/.github/workflows/release.yml
index c19103e3..e61e608b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -38,7 +38,7 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
VERSION: ${{ needs.version.outputs.version }}
- run: gh release create "$TAG" -t "Release $VERSION" --notes-from-tag
+ run: gh release create "$TAG" -t "$VERSION" --notes-from-tag
- name: Download artifacts
uses: actions/download-artifact@v4
with:
diff --git a/.gitignore b/.gitignore
index 0b5677c5..e686a534 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,425 +1,13 @@
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
+.vscode/
+.idea/
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.tlog
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio 6 auto-generated project file (contains which files were open etc.)
-*.vbp
-
-# Visual Studio 6 workspace and project file (working project files containing files to include in project)
-*.dsw
-*.dsp
-
-# Visual Studio 6 technical files
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Nuke Build - Uncomment if you are using it
-.nuke/temp
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# Visual Studio History (VSHistory) files
-.vshistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-
-# Fody - auto-generated XML schema
-FodyWeavers.xsd
-
-# VS Code files for those working on multiple tools
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
+*.sln.docstates
+*.user
+*.suo
*.code-workspace
-# Local History for Visual Studio Code
-.history/
-
-# Windows Installer files from build outputs
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# JetBrains Rider
-*.sln.iml
-
-### Linux ###
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-### macOS ###
-# General
.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
@@ -428,175 +16,18 @@ Icon
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-### macOS Patch ###
-# iCloud generated files
-*.icloud
-
-### Rider ###
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-.idea/
-
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# AWS User-specific
-.idea/**/aws.xml
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn. Uncomment if using
-# auto-import.
-# .idea/artifacts
-# .idea/compiler.xml
-# .idea/jarRepositories.xml
-# .idea/modules.xml
-# .idea/*.iml
-# .idea/modules
-# *.iml
-# *.ipr
-
-# CMake
-cmake-build-*/
-
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
-# File-based project format
-*.iws
-
-# IntelliJ
-out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# SonarLint plugin
-.idea/sonarlint/
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
-### VisualStudioCode ###
-!.vscode/*.code-snippets
-
-# Local History for Visual Studio Code
-
-# Built Visual Studio Code Extensions
-*.vsix
-
-### VisualStudioCode Patch ###
-# Ignore all local history of files
-.history
-.ionide
-
-### Windows ###
-# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
-# Dump file
-*.stackdump
-
-# Folder config file
-[Dd]esktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-
-# Windows shortcuts
-*.lnk
-
-### Specifics ###
-
-# Specials
-*.zip
-archives
+bin/
+obj/
+# ignore ci node files
+node_modules/
+package.json
package-lock.json
-*.private.env.json
-**/**/[Dd]ata/*.json
-**/**/[Dd]ata/*.csv
-# SpecFlow
-*.feature.cs
-
-# Azurite
-*azurite*.json
-
-# Build Folders
-[Pp]ublish
-[Oo]utput
-[Ss]cripts
-[Tt]ests/[Rr]esults
-
-# LibraryManager
-**/lib
-
-# BuildBundlerMinifier
-*.min.*
-*.map
-
-# Sass Output
-**/css
-
-# SQLite files
-*.db
-*.sqlite3
-*.sqlite
-*.db-journal
-*.sqlite3-journal
-*.sqlite-journal
-*.db-shm
-*.db-wal
-
-# SourceGit output files
build/resources/
build/SourceGit/
build/SourceGit.app/
@@ -605,3 +36,6 @@ build/*.tar.gz
build/*.deb
build/*.rpm
build/*.AppImage
+SourceGit.app/
+build.command
+src/Properties/launchSettings.json
diff --git a/LICENSE b/LICENSE
index dceab2d8..442ce085 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2024 sourcegit
+Copyright (c) 2025 sourcegit
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index 170e7bd6..f9ba3072 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,26 @@
-# SourceGit
+# SourceGit - Opensource Git GUI client.
-Opensource Git GUI client.
+[](https://github.com/sourcegit-scm/sourcegit/stargazers)
+[](https://github.com/sourcegit-scm/sourcegit/forks)
+[](LICENSE)
+[](https://github.com/sourcegit-scm/sourcegit/releases/latest)
+[](https://github.com/sourcegit-scm/sourcegit/releases)
## Highlights
* Supports Windows/macOS/Linux
* Opensource/Free
* Fast
-* English/Français/Deutsch/Português/简体中文/繁體中文
+* Deutsch/English/Español/Français/Italiano/Português/Русский/Українська/简体中文/繁體中文/日本語/தமிழ் (Tamil)
* Built-in light/dark themes
* Customize theme
* Visual commit graph
* Supports SSH access with each remote
* GIT commands with GUI
* Clone/Fetch/Pull/Push...
- * Merge/Rebase/Reset/Revert/Amend/Cherry-pick...
- * Amend/Reword
- * Interactive rebase (Basic)
+ * Merge/Rebase/Reset/Revert/Cherry-pick...
+ * Amend/Reword/Squash
+ * Interactive rebase
* Branches
* Remotes
* Tags
@@ -31,31 +35,40 @@ Opensource Git GUI client.
* Revision Diffs
* Branch Diff
* Image Diff - Side-By-Side/Swipe/Blend
+* Git command logs
+* Search commits
* GitFlow
* Git LFS
+* Bisect
* Issue Link
* Workspace
+* Custom Action
* Using AI to generate commit message (C# port of [anjerodev/commitollama](https://github.com/anjerodev/commitollama))
> [!WARNING]
> **Linux** only tested on **Debian 12** on both **X11** & **Wayland**.
+## Translation Status
+
+You can find the current translation status in [TRANSLATION.md](https://github.com/sourcegit-scm/sourcegit/blob/develop/TRANSLATION.md)
+
## How to Use
-**To use this tool, you need to install Git(>=2.23.0) first.**
+**To use this tool, you need to install Git(>=2.25.1) first.**
-You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [Github Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
+You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [GitHub Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs.
| OS | PATH |
|---------|-----------------------------------------------------|
-| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` |
+| Windows | `%APPDATA%\SourceGit` |
| Linux | `${HOME}/.config/SourceGit` or `${HOME}/.sourcegit` |
| macOS | `${HOME}/Library/Application Support/SourceGit` |
> [!TIP]
-> You can open the app data dir from the main menu.
+> * You can open this data storage directory from the main menu `Open Data Storage Directory`.
+> * You can create a `data` folder next to the `SourceGit` executable to force this app to store data (user settings, downloaded avatars and crash logs) into it (Portable-Mode). Only works on Windows.
For **Windows** users:
@@ -66,59 +79,91 @@ For **Windows** users:
```
> [!NOTE]
> `winget` will install this software as a commandline tool. You need run `SourceGit` from console or `Win+R` at the first time. Then you can add it to the taskbar.
-* You can install the latest stable by `scoope` with follow commands:
+* You can install the latest stable by `scoop` with follow commands:
```shell
scoop bucket add extras
scoop install sourcegit
```
-* Portable versions can be found in [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest)
+* Pre-built binaries can be found in [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest)
For **macOS** users:
-* Download `sourcegit_x.y.osx-x64.zip` or `sourcegit_x.y.osx-arm64.zip` from Releases. `x64` for Intel and `arm64` for Apple Silicon.
-* Move `SourceGit.app` to `Applications` folder.
-* Make sure your mac trusts all software from anywhere. For more information, search `spctl --master-disable`.
+* Thanks [@ybeapps](https://github.com/ybeapps) for making `SourceGit` available on `Homebrew`. You can simply install it with following command:
+ ```shell
+ brew tap ybeapps/homebrew-sourcegit
+ brew install --cask --no-quarantine sourcegit
+ ```
+* If you want to install `SourceGit.app` from GitHub Release manually, you need run following command to make sure it works:
+ ```shell
+ sudo xattr -cr /Applications/SourceGit.app
+ ```
* Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your mac.
-* You may need to run `sudo xattr -cr /Applications/SourceGit.app` to make sure the software works.
+* You can run `echo $PATH > ~/Library/Application\ Support/SourceGit/PATH` to generate a custom PATH env file to introduce `PATH` env to SourceGit.
For **Linux** users:
-* `xdg-open` must be installed to support open native file manager.
-* Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your linux.
+* Thanks [@aikawayataro](https://github.com/aikawayataro) for providing `rpm` and `deb` repositories, hosted on [Codeberg](https://codeberg.org/yataro/-/packages).
+
+ `deb` how to:
+ ```shell
+ 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, 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 install sourcegit
+ ```
+
+ `rpm` how to:
+ ```shell
+ curl https://codeberg.org/api/packages/yataro/rpm.repo | sed -e 's/gpgcheck=1/gpgcheck=0/' > sourcegit.repo
+
+ # Fedora 41 and newer
+ sudo dnf config-manager addrepo --from-repofile=./sourcegit.repo
+ # Fedora 40 and earlier
+ sudo dnf config-manager --add-repo ./sourcegit.repo
+
+ sudo dnf install sourcegit
+ ```
+
+ If your distribution isn't using `dnf`, please refer to the documentation of your distribution on how to add an `rpm` repository.
+* `AppImage` files can be found on [AppImage hub](https://appimage.github.io/SourceGit/), `xdg-open` (`xdg-utils`) must be installed to support open native file manager.
+* Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your Linux.
* Maybe you need to set environment variable `AVALONIA_SCREEN_SCALE_FACTORS`. See https://github.com/AvaloniaUI/Avalonia/wiki/Configuring-X11-per-monitor-DPI.
+* If you can NOT type accented characters, such as `ê`, `ó`, try to set the environment variable `AVALONIA_IM_MODULE` to `none`.
## OpenAI
-This software supports using OpenAI or other AI service that has an OpenAI comaptible HTTP API to generate commit message. You need configurate the service in `Preference` window.
+This software supports using OpenAI or other AI service that has an OpenAI compatible HTTP API to generate commit message. You need configurate the service in `Preference` window.
For `OpenAI`:
-* `Server` must be `https://api.openai.com/v1/chat/completions`
+* `Server` must be `https://api.openai.com/v1`
For other AI service:
-* The `Server` should fill in a URL equivalent to OpenAI's `https://api.openai.com/v1/chat/completions`
+* The `Server` should fill in a URL equivalent to OpenAI's `https://api.openai.com/v1`. For example, when using `Ollama`, it should be `http://localhost:11434/v1` instead of `http://localhost:11434/api/generate`
* The `API Key` is optional that depends on the service
## External Tools
This app supports open repository in external tools listed in the table below.
-| Tool | Windows | macOS | Linux | KEY IN `external_editors.json` |
-|-------------------------------|---------|-------|-------|--------------------------------|
-| Visual Studio Code | YES | YES | YES | VSCODE |
-| Visual Studio Code - Insiders | YES | YES | YES | VSCODE_INSIDERS |
-| VSCodium | YES | YES | YES | VSCODIUM |
-| JetBrains Fleet | YES | YES | YES | FLEET |
-| Sublime Text | YES | YES | YES | SUBLIME_TEXT |
+| Tool | Windows | macOS | Linux |
+|-------------------------------|---------|-------|-------|
+| Visual Studio Code | YES | YES | YES |
+| Visual Studio Code - Insiders | YES | YES | YES |
+| VSCodium | YES | YES | YES |
+| Fleet | YES | YES | YES |
+| Sublime Text | YES | YES | YES |
+| Zed | NO | YES | YES |
+| Visual Studio | YES | NO | NO |
> [!NOTE]
> This app will try to find those tools based on some pre-defined or expected locations automatically. If you are using one portable version of these tools, it will not be detected by this app.
-> To solve this problem you can add a file named `external_editors.json` in app data dir and provide the path directly. For example:
+> To solve this problem you can add a file named `external_editors.json` in app data storage directory and provide the path directly. For example:
```json
{
"tools": {
- "VSCODE": "D:\\VSCode\\Code.exe"
+ "Visual Studio Code": "D:\\VSCode\\Code.exe"
}
}
```
@@ -144,6 +189,19 @@ This app supports open repository in external tools listed in the table below.
Everyone is welcome to submit a PR. Please make sure your PR is based on the latest `develop` branch and the target branch of PR is `develop`.
+In short, here are the commands to get started once [.NET tools are installed](https://dotnet.microsoft.com/en-us/download):
+
+```sh
+dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
+dotnet restore
+dotnet build
+dotnet run --project src/SourceGit.csproj
+```
+
Thanks to all the people who contribute.
-[](https://github.com/sourcegit-scm/sourcegit/graphs/contributors)
+[](https://github.com/sourcegit-scm/sourcegit/graphs/contributors)
+
+## Third-Party Components
+
+For detailed license information, see [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
diff --git a/SourceGit.sln b/SourceGit.sln
index 06bd75b3..624322f8 100644
--- a/SourceGit.sln
+++ b/SourceGit.sln
@@ -13,9 +13,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{F45A
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{67B6D05F-A000-40BA-ADB4-C9065F880D7B}"
ProjectSection(SolutionItems) = preProject
+ .github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\ci.yml = .github\workflows\ci.yml
.github\workflows\package.yml = .github\workflows\package.yml
.github\workflows\release.yml = .github\workflows\release.yml
+ .github\workflows\localization-check.yml = .github\workflows\localization-check.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{49A7C2D6-558C-4FAA-8F5D-EEE81497AED7}"
@@ -41,11 +43,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_common", "_common", "{04FD
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "usr", "usr", "{76639799-54BC-45E8-BD90-F45F63ACD11D}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bin", "bin", "{2E27E952-846B-4D75-A426-D22151277864}"
- ProjectSection(SolutionItems) = preProject
- build\resources\_common\usr\bin\sourcegit = build\resources\_common\usr\bin\sourcegit
- EndProjectSection
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "share", "share", "{A3ABAA7C-EE14-4448-B466-6E69C1347E7D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "applications", "{2AF28D3B-14A8-46A8-B828-157FAAB1B06F}"
@@ -63,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}"
@@ -80,9 +79,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "appimage", "appimage", "{5D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{C54D4001-9940-477C-A0B6-E795ED0A3209}"
ProjectSection(SolutionItems) = preProject
+ build\scripts\localization-check.js = build\scripts\localization-check.js
build\scripts\package.linux.sh = build\scripts\package.linux.sh
build\scripts\package.osx-app.sh = build\scripts\package.osx-app.sh
- build\scripts\package.windows-portable.sh = build\scripts\package.windows-portable.sh
+ build\scripts\package.windows.sh = build\scripts\package.windows.sh
EndProjectSection
EndProject
Global
@@ -106,7 +106,6 @@ Global
{ABC98884-F023-4EF4-A9C9-5DE9452BE955} = {FD384607-ED99-47B7-AF31-FB245841BC92}
{04FD74B1-FBDB-496E-A48F-3D59D71FF952} = {FD384607-ED99-47B7-AF31-FB245841BC92}
{76639799-54BC-45E8-BD90-F45F63ACD11D} = {04FD74B1-FBDB-496E-A48F-3D59D71FF952}
- {2E27E952-846B-4D75-A426-D22151277864} = {76639799-54BC-45E8-BD90-F45F63ACD11D}
{A3ABAA7C-EE14-4448-B466-6E69C1347E7D} = {76639799-54BC-45E8-BD90-F45F63ACD11D}
{2AF28D3B-14A8-46A8-B828-157FAAB1B06F} = {A3ABAA7C-EE14-4448-B466-6E69C1347E7D}
{7166EC6C-17F5-4B5E-B38E-1E53C81EACF6} = {A3ABAA7C-EE14-4448-B466-6E69C1347E7D}
diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md
new file mode 100644
index 00000000..2338263c
--- /dev/null
+++ b/THIRD-PARTY-LICENSES.md
@@ -0,0 +1,86 @@
+# Third-Party Licenses
+
+This project incorporates components from the following third parties:
+
+## Packages
+
+### AvaloniaUI
+
+- **Source**: https://github.com/AvaloniaUI/Avalonia
+- **Version**: 11.2.5
+- **License**: MIT License
+- **License Link**: https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md
+
+### AvaloniaEdit
+
+- **Source**: https://github.com/AvaloniaUI/AvaloniaEdit
+- **Version**: 11.2.0
+- **License**: MIT License
+- **License Link**: https://github.com/AvaloniaUI/AvaloniaEdit/blob/master/LICENSE
+
+### LiveChartsCore.SkiaSharpView.Avalonia
+
+- **Source**: https://github.com/beto-rodriguez/LiveCharts2
+- **Version**: 2.0.0-rc5.4
+- **License**: MIT License
+- **License Link**: https://github.com/beto-rodriguez/LiveCharts2/blob/master/LICENSE
+
+### TextMateSharp
+
+- **Source**: https://github.com/danipen/TextMateSharp
+- **Version**: 1.0.66
+- **License**: MIT License
+- **License Link**: https://github.com/danipen/TextMateSharp/blob/master/LICENSE.md
+
+### OpenAI .NET SDK
+
+- **Source**: https://github.com/openai/openai-dotnet
+- **Version**: 2.2.0-beta2
+- **License**: MIT License
+- **License Link**: https://github.com/openai/openai-dotnet/blob/main/LICENSE
+
+### Azure.AI.OpenAI
+
+- **Source**: https://github.com/Azure/azure-sdk-for-net
+- **Version**: 2.2.0-beta2
+- **License**: MIT License
+- **License Link**: https://github.com/Azure/azure-sdk-for-net/blob/main/LICENSE.txt
+
+## Fonts
+
+### JetBrainsMono
+
+- **Source**: https://github.com/JetBrains/JetBrainsMono
+- **Commit**: v2.304
+- **License**: SIL Open Font License, Version 1.1
+- **License Link**: https://github.com/JetBrains/JetBrainsMono/blob/v2.304/OFL.txt
+
+## Grammar Files
+
+### haxe-TmLanguage
+
+- **Source**: https://github.com/vshaxe/haxe-TmLanguage
+- **Commit**: ddad8b4c6d0781ac20be0481174ec1be772c5da5
+- **License**: MIT License
+- **License Link**: https://github.com/vshaxe/haxe-TmLanguage/blob/ddad8b4c6d0781ac20be0481174ec1be772c5da5/LICENSE.md
+
+### coc-toml
+
+- **Source**: https://github.com/kkiyama117/coc-toml
+- **Commit**: aac3e0c65955c03314b2733041b19f903b7cc447
+- **License**: MIT License
+- **License Link**: https://github.com/kkiyama117/coc-toml/blob/aac3e0c65955c03314b2733041b19f903b7cc447/LICENSE
+
+### eclipse-buildship
+
+- **Source**: https://github.com/eclipse/buildship
+- **Commit**: 6bb773e7692f913dec27105129ebe388de34e68b
+- **License**: Eclipse Public License 1.0
+- **License Link**: https://github.com/eclipse-buildship/buildship/blob/6bb773e7692f913dec27105129ebe388de34e68b/README.md
+
+### vscode-jsp-lang
+
+- **Source**: https://github.com/samuel-weinhardt/vscode-jsp-lang
+- **Commit**: 0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355
+- **License**: MIT License
+- **License Link**: https://github.com/samuel-weinhardt/vscode-jsp-lang/blob/0e89ecdb13650dbbe5a1e85b47b2e1530bf2f355/LICENSE
diff --git a/TRANSLATION.md b/TRANSLATION.md
new file mode 100644
index 00000000..051440f0
--- /dev/null
+++ b/TRANSLATION.md
@@ -0,0 +1,511 @@
+# Translation Status
+
+This document shows the translation status of each locale file in the repository.
+
+## Details
+
+### 
+
+### 
+
+
+Missing keys in de_DE.axaml
+
+- Text.Avatar.Load
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitDetail.Changes.Count
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Pull.RecurseSubmodules
+- Text.Repository.ClearStashes
+- Text.Repository.ShowSubmodulesAsTree
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+### 
+
+
+Missing keys in fr_FR.axaml
+
+- Text.Avatar.Load
+- Text.Bisect
+- Text.Bisect.Abort
+- Text.Bisect.Bad
+- Text.Bisect.Detecting
+- Text.Bisect.Good
+- Text.Bisect.Skip
+- Text.Bisect.WaitingForRange
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitter
+- Text.CommitCM.CopySubject
+- Text.CommitDetail.Changes.Count
+- Text.CommitMessageTextBox.SubjectCount
+- Text.Configure.Git.PreferredMergeMode
+- Text.ConfirmEmptyCommit.Continue
+- Text.ConfirmEmptyCommit.NoLocalChanges
+- Text.ConfirmEmptyCommit.StageAllThenCommit
+- Text.ConfirmEmptyCommit.WithLocalChanges
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Preferences.Git.IgnoreCRAtEOLInDiff
+- Text.Pull.RecurseSubmodules
+- Text.Repository.BranchSort
+- Text.Repository.BranchSort.ByCommitterDate
+- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
+- Text.Repository.Search.ByContent
+- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.ViewLogs
+- Text.Repository.Visit
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.ViewLogs
+- Text.ViewLogs.Clear
+- Text.ViewLogs.CopyLog
+- Text.ViewLogs.Delete
+- Text.WorkingCopy.ConfirmCommitWithFilter
+- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
+- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
+- Text.WorkingCopy.Conflicts.UseMine
+- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+
+Missing keys in it_IT.axaml
+
+- Text.Avatar.Load
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitDetail.Changes.Count
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Pull.RecurseSubmodules
+- Text.Repository.ClearStashes
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+
+Missing keys in ja_JP.axaml
+
+- Text.Avatar.Load
+- Text.Bisect
+- Text.Bisect.Abort
+- Text.Bisect.Bad
+- Text.Bisect.Detecting
+- Text.Bisect.Good
+- Text.Bisect.Skip
+- Text.Bisect.WaitingForRange
+- Text.BranchCM.CompareWithCurrent
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitter
+- Text.CommitCM.CopySubject
+- Text.CommitDetail.Changes.Count
+- Text.CommitMessageTextBox.SubjectCount
+- Text.Configure.Git.PreferredMergeMode
+- Text.ConfirmEmptyCommit.Continue
+- Text.ConfirmEmptyCommit.NoLocalChanges
+- Text.ConfirmEmptyCommit.StageAllThenCommit
+- Text.ConfirmEmptyCommit.WithLocalChanges
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Preferences.Git.IgnoreCRAtEOLInDiff
+- Text.Pull.RecurseSubmodules
+- Text.Repository.BranchSort
+- Text.Repository.BranchSort.ByCommitterDate
+- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
+- Text.Repository.FilterCommits
+- Text.Repository.Search.ByContent
+- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.ViewLogs
+- Text.Repository.Visit
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.ViewLogs
+- Text.ViewLogs.Clear
+- Text.ViewLogs.CopyLog
+- Text.ViewLogs.Delete
+- Text.WorkingCopy.ConfirmCommitWithFilter
+- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
+- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
+- Text.WorkingCopy.Conflicts.UseMine
+- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+
+Missing keys in pt_BR.axaml
+
+- Text.AIAssistant.Regen
+- Text.AIAssistant.Use
+- Text.ApplyStash
+- Text.ApplyStash.DropAfterApply
+- Text.ApplyStash.RestoreIndex
+- Text.ApplyStash.Stash
+- Text.Avatar.Load
+- Text.Bisect
+- Text.Bisect.Abort
+- Text.Bisect.Bad
+- Text.Bisect.Detecting
+- Text.Bisect.Good
+- Text.Bisect.Skip
+- Text.Bisect.WaitingForRange
+- Text.BranchCM.CustomAction
+- Text.BranchCM.MergeMultiBranches
+- Text.BranchCM.ResetToSelectedCommit
+- Text.BranchUpstreamInvalid
+- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.Clone.RecurseSubmodules
+- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitter
+- Text.CommitCM.CopySubject
+- Text.CommitCM.Merge
+- Text.CommitCM.MergeMultiple
+- Text.CommitDetail.Changes.Count
+- Text.CommitDetail.Files.Search
+- Text.CommitDetail.Info.Children
+- Text.CommitMessageTextBox.SubjectCount
+- Text.Configure.CustomAction.Scope.Branch
+- Text.Configure.CustomAction.WaitForExit
+- Text.Configure.Git.PreferredMergeMode
+- Text.Configure.IssueTracker.AddSampleGiteeIssue
+- Text.Configure.IssueTracker.AddSampleGiteePullRequest
+- Text.ConfirmEmptyCommit.Continue
+- Text.ConfirmEmptyCommit.NoLocalChanges
+- Text.ConfirmEmptyCommit.StageAllThenCommit
+- Text.ConfirmEmptyCommit.WithLocalChanges
+- Text.CopyFullPath
+- Text.CreateBranch.Name.WarnSpace
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.DeleteRepositoryNode.Path
+- Text.DeleteRepositoryNode.TipForGroup
+- Text.DeleteRepositoryNode.TipForRepository
+- Text.Diff.First
+- Text.Diff.Last
+- Text.Diff.Submodule.Deleted
+- Text.Diff.UseBlockNavigation
+- Text.Fetch.Force
+- Text.FileCM.ResolveUsing
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.Clone
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.InProgress.CherryPick.Head
+- Text.InProgress.Merge.Operating
+- Text.InProgress.Rebase.StoppedAt
+- Text.InProgress.Revert.Head
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Merge.Source
+- Text.MergeMultiple
+- Text.MergeMultiple.CommitChanges
+- Text.MergeMultiple.Strategy
+- Text.MergeMultiple.Targets
+- Text.Preferences.AI.Streaming
+- Text.Preferences.Appearance.EditorTabWidth
+- Text.Preferences.General.DateFormat
+- Text.Preferences.General.ShowChildren
+- Text.Preferences.General.ShowTagsInGraph
+- Text.Preferences.Git.IgnoreCRAtEOLInDiff
+- Text.Preferences.Git.SSLVerify
+- Text.Pull.RecurseSubmodules
+- Text.Repository.BranchSort
+- Text.Repository.BranchSort.ByCommitterDate
+- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
+- Text.Repository.FilterCommits
+- Text.Repository.HistoriesLayout
+- Text.Repository.HistoriesLayout.Horizontal
+- Text.Repository.HistoriesLayout.Vertical
+- Text.Repository.HistoriesOrder
+- Text.Repository.Notifications.Clear
+- Text.Repository.OnlyHighlightCurrentBranchInHistories
+- Text.Repository.Search.ByContent
+- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.Skip
+- Text.Repository.Tags.OrderByCreatorDate
+- Text.Repository.Tags.OrderByName
+- Text.Repository.Tags.Sort
+- Text.Repository.UseRelativeTimeInHistories
+- Text.Repository.ViewLogs
+- Text.Repository.Visit
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.SetUpstream
+- Text.SetUpstream.Local
+- Text.SetUpstream.Unset
+- Text.SetUpstream.Upstream
+- Text.SHALinkCM.NavigateTo
+- Text.Stash.AutoRestore
+- Text.Stash.AutoRestore.Tip
+- Text.StashCM.SaveAsPatch
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.ViewLogs
+- Text.ViewLogs.Clear
+- Text.ViewLogs.CopyLog
+- Text.ViewLogs.Delete
+- Text.WorkingCopy.CommitToEdit
+- Text.WorkingCopy.ConfirmCommitWithFilter
+- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
+- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
+- Text.WorkingCopy.Conflicts.UseMine
+- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
+- Text.WorkingCopy.SignOff
+
+
+
+### 
+
+
+Missing keys in ru_RU.axaml
+
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+
+
+
+### 
+
+
+Missing keys in ta_IN.axaml
+
+- Text.Avatar.Load
+- Text.Bisect
+- Text.Bisect.Abort
+- Text.Bisect.Bad
+- Text.Bisect.Detecting
+- Text.Bisect.Good
+- Text.Bisect.Skip
+- Text.Bisect.WaitingForRange
+- Text.BranchCM.CompareWithCurrent
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitter
+- Text.CommitCM.CopySubject
+- Text.CommitDetail.Changes.Count
+- Text.CommitMessageTextBox.SubjectCount
+- Text.Configure.Git.PreferredMergeMode
+- Text.ConfirmEmptyCommit.Continue
+- Text.ConfirmEmptyCommit.NoLocalChanges
+- Text.ConfirmEmptyCommit.StageAllThenCommit
+- Text.ConfirmEmptyCommit.WithLocalChanges
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Preferences.Git.IgnoreCRAtEOLInDiff
+- Text.Pull.RecurseSubmodules
+- Text.Repository.BranchSort
+- Text.Repository.BranchSort.ByCommitterDate
+- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
+- Text.Repository.Search.ByContent
+- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.ViewLogs
+- Text.Repository.Visit
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.UpdateSubmodules.Target
+- Text.ViewLogs
+- Text.ViewLogs.Clear
+- Text.ViewLogs.CopyLog
+- Text.ViewLogs.Delete
+- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
+- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
+- Text.WorkingCopy.Conflicts.UseMine
+- Text.WorkingCopy.Conflicts.UseTheirs
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+
+Missing keys in uk_UA.axaml
+
+- Text.Avatar.Load
+- Text.Bisect
+- Text.Bisect.Abort
+- Text.Bisect.Bad
+- Text.Bisect.Detecting
+- Text.Bisect.Good
+- Text.Bisect.Skip
+- Text.Bisect.WaitingForRange
+- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitter
+- Text.CommitCM.CopySubject
+- Text.CommitDetail.Changes.Count
+- Text.CommitMessageTextBox.SubjectCount
+- Text.ConfigureWorkspace.Name
+- Text.CreateBranch.OverwriteExisting
+- Text.DeinitSubmodule
+- Text.DeinitSubmodule.Force
+- Text.DeinitSubmodule.Path
+- Text.Diff.Submodule.Deleted
+- Text.GitFlow.FinishWithPush
+- Text.GitFlow.FinishWithSquash
+- Text.Hotkeys.Global.SwitchWorkspace
+- Text.Hotkeys.Global.SwitchTab
+- Text.Hotkeys.TextEditor.OpenExternalMergeTool
+- Text.Launcher.Workspaces
+- Text.Launcher.Pages
+- Text.Preferences.Git.IgnoreCRAtEOLInDiff
+- Text.Pull.RecurseSubmodules
+- Text.Repository.BranchSort
+- Text.Repository.BranchSort.ByCommitterDate
+- Text.Repository.BranchSort.ByName
+- Text.Repository.ClearStashes
+- Text.Repository.Search.ByContent
+- Text.Repository.ShowSubmodulesAsTree
+- Text.Repository.ViewLogs
+- Text.Repository.Visit
+- Text.ResetWithoutCheckout
+- Text.ResetWithoutCheckout.MoveTo
+- Text.ResetWithoutCheckout.Target
+- Text.Submodule.Deinit
+- Text.Submodule.Status
+- Text.Submodule.Status.Modified
+- Text.Submodule.Status.NotInited
+- Text.Submodule.Status.RevisionChanged
+- Text.Submodule.Status.Unmerged
+- Text.Submodule.URL
+- Text.ViewLogs
+- Text.ViewLogs.Clear
+- Text.ViewLogs.CopyLog
+- Text.ViewLogs.Delete
+- Text.WorkingCopy.ResetAuthor
+
+
+
+### 
+
+### 
\ No newline at end of file
diff --git a/VERSION b/VERSION
index 353e4ac4..d3e094ba 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.30.1
\ No newline at end of file
+2025.22
\ No newline at end of file
diff --git a/build/README.md b/build/README.md
new file mode 100644
index 00000000..17305edf
--- /dev/null
+++ b/build/README.md
@@ -0,0 +1,15 @@
+# build
+
+> [!WARNING]
+> The files under the `build` folder is used for `Github Action` only, **NOT** for end users.
+
+## How to build this project manually
+
+1. Make sure [.NET SDK 9](https://dotnet.microsoft.com/en-us/download) is installed on your machine.
+2. Clone this project
+3. Run the follow command under the project root dir
+```sh
+dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj
+```
+> [!NOTE]
+> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replace the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
diff --git a/build/resources/_common/applications/sourcegit.desktop b/build/resources/_common/applications/sourcegit.desktop
index ff7ef135..bcf9c813 100644
--- a/build/resources/_common/applications/sourcegit.desktop
+++ b/build/resources/_common/applications/sourcegit.desktop
@@ -1,5 +1,5 @@
[Desktop Entry]
-Name=Source Git
+Name=SourceGit
Comment=Open-source & Free Git GUI Client
Exec=/opt/sourcegit/sourcegit
Icon=/usr/share/icons/sourcegit.png
diff --git a/build/resources/app/App.plist b/build/resources/app/App.plist
index a9852019..ba6f40a2 100644
--- a/build/resources/app/App.plist
+++ b/build/resources/app/App.plist
@@ -12,11 +12,6 @@
SOURCE_GIT_VERSION.0
LSMinimumSystemVersion
11.0
- LSEnvironment
-
- PATH
- /opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
-
CFBundleExecutable
SourceGit
CFBundleInfoDictionaryVersion
diff --git a/build/resources/deb/DEBIAN/control b/build/resources/deb/DEBIAN/control
index 7cfed330..71786b43 100755
--- a/build/resources/deb/DEBIAN/control
+++ b/build/resources/deb/DEBIAN/control
@@ -1,7 +1,8 @@
Package: sourcegit
-Version: 8.23
+Version: 2025.10
Priority: optional
-Depends: libx11-6, libice6, libsm6
+Depends: libx11-6, libice6, libsm6, libicu | libicu76 | libicu74 | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52, xdg-utils
Architecture: amd64
+Installed-Size: 60440
Maintainer: longshuang@msn.cn
Description: Open-source & Free Git GUI Client
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/resources/rpm/SPECS/build.spec b/build/resources/rpm/SPECS/build.spec
index 289cbe39..2a684837 100644
--- a/build/resources/rpm/SPECS/build.spec
+++ b/build/resources/rpm/SPECS/build.spec
@@ -5,8 +5,10 @@ Summary: Open-source & Free Git Gui Client
License: MIT
URL: https://sourcegit-scm.github.io/
Source: https://github.com/sourcegit-scm/sourcegit/archive/refs/tags/v%_version.tar.gz
-Requires: libX11
-Requires: libSM
+Requires: libX11.so.6()(%{__isa_bits}bit)
+Requires: libSM.so.6()(%{__isa_bits}bit)
+Requires: libicu
+Requires: xdg-utils
%define _build_id_links none
diff --git a/build/scripts/localization-check.js b/build/scripts/localization-check.js
new file mode 100644
index 00000000..8d636b5b
--- /dev/null
+++ b/build/scripts/localization-check.js
@@ -0,0 +1,83 @@
+const fs = require('fs-extra');
+const path = require('path');
+const xml2js = require('xml2js');
+
+const repoRoot = path.join(__dirname, '../../');
+const localesDir = path.join(repoRoot, 'src/Resources/Locales');
+const enUSFile = path.join(localesDir, 'en_US.axaml');
+const outputFile = path.join(repoRoot, 'TRANSLATION.md');
+
+const parser = new xml2js.Parser();
+
+async function parseXml(filePath) {
+ const data = await fs.readFile(filePath);
+ return parser.parseStringPromise(data);
+}
+
+async function filterAndSortTranslations(localeData, enUSKeys, enUSData) {
+ const strings = localeData.ResourceDictionary['x:String'];
+ // Remove keys that don't exist in English file
+ const filtered = strings.filter(item => enUSKeys.has(item.$['x:Key']));
+
+ // Sort based on the key order in English file
+ const enUSKeysArray = enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key']);
+ filtered.sort((a, b) => {
+ const aIndex = enUSKeysArray.indexOf(a.$['x:Key']);
+ const bIndex = enUSKeysArray.indexOf(b.$['x:Key']);
+ return aIndex - bIndex;
+ });
+
+ return filtered;
+}
+
+async function calculateTranslationRate() {
+ const enUSData = await parseXml(enUSFile);
+ const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key']));
+ const files = (await fs.readdir(localesDir)).filter(file => file !== 'en_US.axaml' && file.endsWith('.axaml'));
+
+ const lines = [];
+
+ lines.push('# Translation Status');
+ lines.push('This document shows the translation status of each locale file in the repository.');
+ lines.push(`## Details`);
+ lines.push(`### `);
+
+ for (const file of files) {
+ const locale = file.replace('.axaml', '').replace('_', '__');
+ const filePath = path.join(localesDir, file);
+ const localeData = await parseXml(filePath);
+ const localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key']));
+ const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(key));
+
+ // Sort and clean up extra translations
+ const sortedAndCleaned = await filterAndSortTranslations(localeData, enUSKeys, enUSData);
+ localeData.ResourceDictionary['x:String'] = sortedAndCleaned;
+
+ // Save the updated file
+ const builder = new xml2js.Builder({
+ headless: true,
+ renderOpts: { pretty: true, indent: ' ' }
+ });
+ let xmlStr = builder.buildObject(localeData);
+
+ // Add an empty line before the first x:String
+ xmlStr = xmlStr.replace(' 0) {
+ const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100;
+ const badgeColor = progress >= 75 ? 'yellow' : 'red';
+
+ lines.push(`### }%25-${badgeColor})`);
+ lines.push(`\nMissing keys in ${file}
\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n `)
+ } else {
+ lines.push(`### `);
+ }
+ }
+
+ const content = lines.join('\n\n');
+ console.log(content);
+ await fs.writeFile(outputFile, content, 'utf8');
+}
+
+calculateTranslationRate().catch(err => console.error(err));
diff --git a/build/scripts/package.linux.sh b/build/scripts/package.linux.sh
index 5eceffd6..1b4adbdc 100755
--- a/build/scripts/package.linux.sh
+++ b/build/scripts/package.linux.sh
@@ -1,16 +1,9 @@
-#!/bin/bash
+#!/usr/bin/env bash
set -e
-
-if [ -z "$VERSION" ]; then
- echo "Provide the version as environment variable VERSION"
- exit 1
-fi
-
-if [ -z "$RUNTIME" ]; then
- echo "Provide the runtime as environment variable RUNTIME"
- exit 1
-fi
+set -o
+set -u
+set pipefail
arch=
appimage_arch=
@@ -33,7 +26,7 @@ APPIMAGETOOL_URL=https://github.com/AppImage/appimagetool/releases/download/cont
cd build
-if [ ! -f "appimagetool" ]; then
+if [[ ! -f "appimagetool" ]]; then
curl -o appimagetool -L "$APPIMAGETOOL_URL"
chmod +x appimagetool
fi
@@ -63,8 +56,15 @@ cp -f SourceGit/* resources/deb/opt/sourcegit
ln -rsf resources/deb/opt/sourcegit/sourcegit resources/deb/usr/bin
cp -r resources/_common/applications resources/deb/usr/share
cp -r resources/_common/icons resources/deb/usr/share
-sed -i -e "s/^Version:.*/Version: $VERSION/" -e "s/^Architecture:.*/Architecture: $arch/" resources/deb/DEBIAN/control
-dpkg-deb --root-owner-group --build resources/deb "sourcegit_$VERSION-1_$arch.deb"
+# Calculate installed size in KB
+installed_size=$(du -sk resources/deb | cut -f1)
+# Update the control file
+sed -i -e "s/^Version:.*/Version: $VERSION/" \
+ -e "s/^Architecture:.*/Architecture: $arch/" \
+ -e "s/^Installed-Size:.*/Installed-Size: $installed_size/" \
+ resources/deb/DEBIAN/control
+# Build deb package with gzip compression
+dpkg-deb -Zgzip --root-owner-group --build resources/deb "sourcegit_$VERSION-1_$arch.deb"
rpmbuild -bb --target="$target" resources/rpm/SPECS/build.spec --define "_topdir $(pwd)/resources/rpm" --define "_version $VERSION"
mv "resources/rpm/RPMS/$target/sourcegit-$VERSION-1.$target.rpm" ./
diff --git a/build/scripts/package.osx-app.sh b/build/scripts/package.osx-app.sh
index 5d908956..2d43e24a 100755
--- a/build/scripts/package.osx-app.sh
+++ b/build/scripts/package.osx-app.sh
@@ -1,16 +1,9 @@
-#!/bin/bash
+#!/usr/bin/env bash
set -e
-
-if [ -z "$VERSION" ]; then
- echo "Provide the version as environment variable VERSION"
- exit 1
-fi
-
-if [ -z "$RUNTIME" ]; then
- echo "Provide the runtime as environment variable RUNTIME"
- exit 1
-fi
+set -o
+set -u
+set pipefail
cd build
diff --git a/build/scripts/package.windows-portable.sh b/build/scripts/package.windows-portable.sh
deleted file mode 100755
index cc5ee1bd..00000000
--- a/build/scripts/package.windows-portable.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [ -z "$VERSION" ]; then
- echo "Provide the version as environment variable VERSION"
- exit 1
-fi
-
-if [ -z "$RUNTIME" ]; then
- echo "Provide the runtime as environment variable RUNTIME"
- exit 1
-fi
-
-cd build
-
-rm -rf SourceGit/*.pdb
-
-zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit
diff --git a/build/scripts/package.windows.sh b/build/scripts/package.windows.sh
new file mode 100755
index 00000000..c22a9d35
--- /dev/null
+++ b/build/scripts/package.windows.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+set -e
+set -o
+set -u
+set pipefail
+
+cd build
+
+rm -rf SourceGit/*.pdb
+
+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/global.json b/global.json
index b5b37b60..a27a2b82 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "8.0.0",
+ "version": "9.0.0",
"rollForward": "latestMajor",
"allowPrerelease": false
}
diff --git a/screenshots/theme_dark.png b/screenshots/theme_dark.png
index 5954be00..85e18481 100644
Binary files a/screenshots/theme_dark.png and b/screenshots/theme_dark.png differ
diff --git a/screenshots/theme_light.png b/screenshots/theme_light.png
index cc68ccb3..2e8cf6fc 100644
Binary files a/screenshots/theme_light.png and b/screenshots/theme_light.png differ
diff --git a/src/App.Commands.cs b/src/App.Commands.cs
index 8a485029..22e9fb51 100644
--- a/src/App.Commands.cs
+++ b/src/App.Commands.cs
@@ -25,12 +25,34 @@ namespace SourceGit
private Action