mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-10-31 13:03:20 -07:00
Merge branch 'release/v8.32'
This commit is contained in:
commit
6099d54c7b
75 changed files with 1476 additions and 1907 deletions
66
.gitattributes
vendored
66
.gitattributes
vendored
|
@ -1,78 +1,12 @@
|
|||
# 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
|
||||
*.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
|
588
.gitignore
vendored
588
.gitignore
vendored
|
@ -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,14 @@ 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
|
||||
bin/
|
||||
obj/
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
### Specifics ###
|
||||
|
||||
# Specials
|
||||
*.zip
|
||||
archives
|
||||
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 +32,4 @@ build/*.tar.gz
|
|||
build/*.deb
|
||||
build/*.rpm
|
||||
build/*.AppImage
|
||||
SourceGit.app/
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.31
|
||||
8.32
|
15
build/README.md
Normal file
15
build/README.md
Normal file
|
@ -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 8](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 replece the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
|
|
@ -12,11 +12,6 @@
|
|||
<string>SOURCE_GIT_VERSION.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0</string>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||
</dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>SourceGit</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
|
|
@ -516,27 +516,24 @@ namespace SourceGit
|
|||
|
||||
private bool TryLaunchedAsAskpass(IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var launchAsAskpass = Environment.GetEnvironmentVariable("SOURCEGIT_LAUNCH_AS_ASKPASS");
|
||||
if (launchAsAskpass is not "TRUE")
|
||||
return false;
|
||||
|
||||
var args = desktop.Args;
|
||||
if (args == null || args.Length != 1)
|
||||
return false;
|
||||
if (args?.Length > 0)
|
||||
{
|
||||
desktop.MainWindow = new Views.Askpass(args[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
var param = args[0];
|
||||
if (Directory.Exists(param))
|
||||
return false;
|
||||
|
||||
if (!param.StartsWith("enter passphrase", StringComparison.OrdinalIgnoreCase) &&
|
||||
!param.Contains(" password", StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
desktop.MainWindow = new Views.Askpass(param);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void TryLaunchedAsNormal(IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
Native.OS.SetupEnternalTools();
|
||||
Models.AvatarManager.Instance.Start();
|
||||
Models.AutoFetchManager.Instance.Start();
|
||||
|
||||
string startupRepo = null;
|
||||
if (desktop.Args != null && desktop.Args.Length == 1 && Directory.Exists(desktop.Args[0]))
|
||||
|
|
|
@ -40,59 +40,7 @@ namespace SourceGit.Commands
|
|||
|
||||
public bool Exec()
|
||||
{
|
||||
var start = new ProcessStartInfo();
|
||||
start.FileName = Native.OS.GitExecutable;
|
||||
start.Arguments = "--no-pager -c core.quotepath=off ";
|
||||
start.UseShellExecute = false;
|
||||
start.CreateNoWindow = true;
|
||||
start.RedirectStandardOutput = true;
|
||||
start.RedirectStandardError = true;
|
||||
start.StandardOutputEncoding = Encoding.UTF8;
|
||||
start.StandardErrorEncoding = Encoding.UTF8;
|
||||
|
||||
// Force using this app as SSH askpass program
|
||||
var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName;
|
||||
if (!OperatingSystem.IsLinux())
|
||||
start.Environment.Add("DISPLAY", "required");
|
||||
start.Environment.Add("SSH_ASKPASS", selfExecFile); // Can not use parameter here, because it invoked by SSH with `exec`
|
||||
start.Environment.Add("SSH_ASKPASS_REQUIRE", "prefer");
|
||||
|
||||
// If an SSH private key was provided, sets the environment.
|
||||
if (!string.IsNullOrEmpty(SSHKey))
|
||||
{
|
||||
start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o StrictHostKeyChecking=accept-new -i '{SSHKey}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o StrictHostKeyChecking=accept-new");
|
||||
start.Arguments += "-c credential.helper=manager ";
|
||||
}
|
||||
|
||||
// Force using en_US.UTF-8 locale to avoid GCM crash
|
||||
if (OperatingSystem.IsLinux())
|
||||
start.Environment.Add("LANG", "en_US.UTF-8");
|
||||
|
||||
// Force using this app as git editor.
|
||||
switch (Editor)
|
||||
{
|
||||
case EditorType.CoreEditor:
|
||||
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --core-editor\" ";
|
||||
break;
|
||||
case EditorType.RebaseEditor:
|
||||
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --rebase-message-editor\" -c sequence.editor=\"\\\"{selfExecFile}\\\" --rebase-todo-editor\" -c rebase.abbreviateCommands=true ";
|
||||
break;
|
||||
default:
|
||||
start.Arguments += "-c core.editor=true ";
|
||||
break;
|
||||
}
|
||||
|
||||
// Append command args
|
||||
start.Arguments += Args;
|
||||
|
||||
// Working directory
|
||||
if (!string.IsNullOrEmpty(WorkingDirectory))
|
||||
start.WorkingDirectory = WorkingDirectory;
|
||||
|
||||
var start = CreateGitStartInfo();
|
||||
var errs = new List<string>();
|
||||
var proc = new Process() { StartInfo = start };
|
||||
var isCancelled = false;
|
||||
|
@ -178,28 +126,15 @@ namespace SourceGit.Commands
|
|||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ReadToEndResult ReadToEnd()
|
||||
{
|
||||
var start = new ProcessStartInfo();
|
||||
start.FileName = Native.OS.GitExecutable;
|
||||
start.Arguments = "--no-pager -c core.quotepath=off " + Args;
|
||||
start.UseShellExecute = false;
|
||||
start.CreateNoWindow = true;
|
||||
start.RedirectStandardOutput = true;
|
||||
start.RedirectStandardError = true;
|
||||
start.StandardOutputEncoding = Encoding.UTF8;
|
||||
start.StandardErrorEncoding = Encoding.UTF8;
|
||||
|
||||
if (!string.IsNullOrEmpty(WorkingDirectory))
|
||||
start.WorkingDirectory = WorkingDirectory;
|
||||
|
||||
var start = CreateGitStartInfo();
|
||||
var proc = new Process() { StartInfo = start };
|
||||
|
||||
try
|
||||
{
|
||||
proc.Start();
|
||||
|
@ -227,7 +162,68 @@ namespace SourceGit.Commands
|
|||
return rs;
|
||||
}
|
||||
|
||||
protected virtual void OnReadline(string line) { }
|
||||
protected virtual void OnReadline(string line)
|
||||
{
|
||||
// Implemented by derived class
|
||||
}
|
||||
|
||||
private ProcessStartInfo CreateGitStartInfo()
|
||||
{
|
||||
var start = new ProcessStartInfo();
|
||||
start.FileName = Native.OS.GitExecutable;
|
||||
start.Arguments = "--no-pager -c core.quotepath=off -c credential.helper=manager ";
|
||||
start.UseShellExecute = false;
|
||||
start.CreateNoWindow = true;
|
||||
start.RedirectStandardOutput = true;
|
||||
start.RedirectStandardError = true;
|
||||
start.StandardOutputEncoding = Encoding.UTF8;
|
||||
start.StandardErrorEncoding = Encoding.UTF8;
|
||||
|
||||
// Force using this app as SSH askpass program
|
||||
var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName;
|
||||
if (!OperatingSystem.IsLinux())
|
||||
start.Environment.Add("DISPLAY", "required");
|
||||
start.Environment.Add("SSH_ASKPASS", selfExecFile); // Can not use parameter here, because it invoked by SSH with `exec`
|
||||
start.Environment.Add("SSH_ASKPASS_REQUIRE", "prefer");
|
||||
start.Environment.Add("SOURCEGIT_LAUNCH_AS_ASKPASS", "TRUE");
|
||||
|
||||
// If an SSH private key was provided, sets the environment.
|
||||
if (!string.IsNullOrEmpty(SSHKey))
|
||||
start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o StrictHostKeyChecking=accept-new -i '{SSHKey}'");
|
||||
else
|
||||
start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o StrictHostKeyChecking=accept-new");
|
||||
|
||||
// Force using en_US.UTF-8 locale to avoid GCM crash
|
||||
if (OperatingSystem.IsLinux())
|
||||
start.Environment.Add("LANG", "en_US.UTF-8");
|
||||
|
||||
// Fix sometimes `LSEnvironment` not working on macOS
|
||||
if (OperatingSystem.IsMacOS())
|
||||
start.Environment.Add("PATH", "/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin");
|
||||
|
||||
// Force using this app as git editor.
|
||||
switch (Editor)
|
||||
{
|
||||
case EditorType.CoreEditor:
|
||||
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --core-editor\" ";
|
||||
break;
|
||||
case EditorType.RebaseEditor:
|
||||
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --rebase-message-editor\" -c sequence.editor=\"\\\"{selfExecFile}\\\" --rebase-todo-editor\" -c rebase.abbreviateCommands=true ";
|
||||
break;
|
||||
default:
|
||||
start.Arguments += "-c core.editor=true ";
|
||||
break;
|
||||
}
|
||||
|
||||
// Append command args
|
||||
start.Arguments += Args;
|
||||
|
||||
// Working directory
|
||||
if (!string.IsNullOrEmpty(WorkingDirectory))
|
||||
start.WorkingDirectory = WorkingDirectory;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"\d+%")]
|
||||
private static partial Regex REG_PROGRESS();
|
||||
|
|
|
@ -22,8 +22,6 @@ namespace SourceGit.Commands
|
|||
Args += "--force ";
|
||||
|
||||
Args += remote;
|
||||
|
||||
Models.AutoFetchManager.Instance.MarkFetched(repo);
|
||||
}
|
||||
|
||||
public Fetch(string repo, string remote, string localBranch, string remoteBranch, Action<string> outputHandler)
|
||||
|
|
|
@ -19,29 +19,35 @@ namespace SourceGit.Commands
|
|||
|
||||
public List<Models.Branch> Result()
|
||||
{
|
||||
Exec();
|
||||
var branches = new List<Models.Branch>();
|
||||
var rs = ReadToEnd();
|
||||
if (!rs.IsSuccess)
|
||||
return branches;
|
||||
|
||||
foreach (var b in _needQueryTrackStatus)
|
||||
b.TrackStatus = new QueryTrackStatus(WorkingDirectory, b.Name, b.Upstream).Result();
|
||||
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var b = ParseLine(line);
|
||||
if (b != null)
|
||||
branches.Add(b);
|
||||
}
|
||||
|
||||
return _branches;
|
||||
return branches;
|
||||
}
|
||||
|
||||
protected override void OnReadline(string line)
|
||||
private Models.Branch ParseLine(string line)
|
||||
{
|
||||
var parts = line.Split('$');
|
||||
if (parts.Length != 5)
|
||||
return;
|
||||
return null;
|
||||
|
||||
var branch = new Models.Branch();
|
||||
var refName = parts[0];
|
||||
if (refName.EndsWith("/HEAD", StringComparison.Ordinal))
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (refName.StartsWith(PREFIX_DETACHED_AT, StringComparison.Ordinal) || refName.StartsWith(PREFIX_DETACHED_FROM, StringComparison.Ordinal))
|
||||
{
|
||||
branch.IsDetachedHead = true;
|
||||
}
|
||||
branch.IsDetachedHead = refName.StartsWith(PREFIX_DETACHED_AT, StringComparison.Ordinal) ||
|
||||
refName.StartsWith(PREFIX_DETACHED_FROM, StringComparison.Ordinal);
|
||||
|
||||
if (refName.StartsWith(PREFIX_LOCAL, StringComparison.Ordinal))
|
||||
{
|
||||
|
@ -53,7 +59,7 @@ namespace SourceGit.Commands
|
|||
var name = refName.Substring(PREFIX_REMOTE.Length);
|
||||
var shortNameIdx = name.IndexOf('/', StringComparison.Ordinal);
|
||||
if (shortNameIdx < 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
branch.Remote = name.Substring(0, shortNameIdx);
|
||||
branch.Name = name.Substring(branch.Remote.Length + 1);
|
||||
|
@ -71,14 +77,11 @@ namespace SourceGit.Commands
|
|||
branch.Upstream = parts[3];
|
||||
|
||||
if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal))
|
||||
_needQueryTrackStatus.Add(branch);
|
||||
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
|
||||
else
|
||||
branch.TrackStatus = new Models.BranchTrackStatus();
|
||||
|
||||
_branches.Add(branch);
|
||||
return branch;
|
||||
}
|
||||
|
||||
private readonly List<Models.Branch> _branches = new List<Models.Branch>();
|
||||
private List<Models.Branch> _needQueryTrackStatus = new List<Models.Branch>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,21 +14,23 @@ namespace SourceGit.Commands
|
|||
_findFirstMerged = needFindHead;
|
||||
}
|
||||
|
||||
public QueryCommits(string repo, string filter, Models.CommitSearchMethod method)
|
||||
public QueryCommits(string repo, string filter, Models.CommitSearchMethod method, bool onlyCurrentBranch)
|
||||
{
|
||||
string search;
|
||||
string search = onlyCurrentBranch ? string.Empty : "--branches --remotes ";
|
||||
|
||||
if (method == Models.CommitSearchMethod.ByUser)
|
||||
{
|
||||
search = $"-i --author=\"{filter}\" --committer=\"{filter}\"";
|
||||
search += $"-i --author=\"{filter}\" --committer=\"{filter}\"";
|
||||
}
|
||||
else if (method == Models.CommitSearchMethod.ByFile)
|
||||
{
|
||||
search = $"-- \"{filter}\"";
|
||||
search += $"-- \"{filter}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var argsBuilder = new StringBuilder();
|
||||
argsBuilder.Append(search);
|
||||
|
||||
var words = filter.Split(new[] { ' ', '\t', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var word in words)
|
||||
{
|
||||
|
@ -36,12 +38,13 @@ namespace SourceGit.Commands
|
|||
argsBuilder.Append($"--grep=\"{escaped}\" ");
|
||||
}
|
||||
argsBuilder.Append("--all-match -i");
|
||||
|
||||
search = argsBuilder.ToString();
|
||||
}
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"log -1000 --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%s --branches --remotes " + search;
|
||||
Args = $"log -1000 --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%s " + search;
|
||||
_findFirstMerged = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,31 +14,43 @@ namespace SourceGit.Commands
|
|||
|
||||
public List<Models.Tag> Result()
|
||||
{
|
||||
Exec();
|
||||
return _loaded;
|
||||
var tags = new List<Models.Tag>();
|
||||
var rs = ReadToEnd();
|
||||
if (!rs.IsSuccess)
|
||||
return tags;
|
||||
|
||||
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var tag = ParseLine(line);
|
||||
if (tag != null)
|
||||
tags.Add(tag);
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
protected override void OnReadline(string line)
|
||||
private Models.Tag ParseLine(string line)
|
||||
{
|
||||
var subs = line.Split('$', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (subs.Length == 2)
|
||||
{
|
||||
_loaded.Add(new Models.Tag()
|
||||
return new Models.Tag()
|
||||
{
|
||||
Name = subs[0].Substring(10),
|
||||
SHA = subs[1],
|
||||
});
|
||||
};
|
||||
}
|
||||
else if (subs.Length == 3)
|
||||
{
|
||||
_loaded.Add(new Models.Tag()
|
||||
return new Models.Tag()
|
||||
{
|
||||
Name = subs[0].Substring(10),
|
||||
SHA = subs[2],
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Models.Tag> _loaded = new List<Models.Tag>();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,35 @@ namespace SourceGit.Commands
|
|||
{
|
||||
public Statistics(string repo)
|
||||
{
|
||||
_statistics = new Models.Statistics();
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"log --date-order --branches --remotes --since=\"{_statistics.Since()}\" --pretty=format:\"%ct$%an\"";
|
||||
Args = $"log --date-order --branches --remotes -40000 --pretty=format:\"%ct$%aN\"";
|
||||
}
|
||||
|
||||
public Models.Statistics Result()
|
||||
{
|
||||
Exec();
|
||||
_statistics.Complete();
|
||||
return _statistics;
|
||||
var statistics = new Models.Statistics();
|
||||
var rs = ReadToEnd();
|
||||
if (!rs.IsSuccess)
|
||||
return statistics;
|
||||
|
||||
var start = 0;
|
||||
var end = rs.StdOut.IndexOf('\n', start);
|
||||
while (end > 0)
|
||||
{
|
||||
ParseLine(statistics, rs.StdOut.Substring(start, end - start));
|
||||
start = end + 1;
|
||||
end = rs.StdOut.IndexOf('\n', start);
|
||||
}
|
||||
|
||||
if (start < rs.StdOut.Length)
|
||||
ParseLine(statistics, rs.StdOut.Substring(start));
|
||||
|
||||
statistics.Complete();
|
||||
return statistics;
|
||||
}
|
||||
|
||||
protected override void OnReadline(string line)
|
||||
private void ParseLine(Models.Statistics statistics, string line)
|
||||
{
|
||||
var dateEndIdx = line.IndexOf('$', StringComparison.Ordinal);
|
||||
if (dateEndIdx == -1)
|
||||
|
@ -28,9 +42,7 @@ namespace SourceGit.Commands
|
|||
|
||||
var dateStr = line.Substring(0, dateEndIdx);
|
||||
if (double.TryParse(dateStr, out var date))
|
||||
_statistics.AddCommit(line.Substring(dateEndIdx + 1), date);
|
||||
statistics.AddCommit(line.Substring(dateEndIdx + 1), date);
|
||||
}
|
||||
|
||||
private readonly Models.Statistics _statistics = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace SourceGit.Converters
|
|||
public static readonly FuncValueConverter<IList, string> ToCount =
|
||||
new FuncValueConverter<IList, string>(v => v == null ? " (0)" : $" ({v.Count})");
|
||||
|
||||
public static readonly FuncValueConverter<IList, bool> IsNullOrEmpty =
|
||||
new FuncValueConverter<IList, bool>(v => v == null || v.Count == 0);
|
||||
|
||||
public static readonly FuncValueConverter<IList, bool> IsNotNullOrEmpty =
|
||||
new FuncValueConverter<IList, bool>(v => v != null && v.Count > 0);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SourceGit.Converters
|
|||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
return v;
|
||||
|
||||
|
||||
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length;
|
||||
if (v.StartsWith(home, StringComparison.Ordinal))
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class AutoFetchManager
|
||||
{
|
||||
public static AutoFetchManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new AutoFetchManager();
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public class Job
|
||||
{
|
||||
public string IndexLockFile = string.Empty;
|
||||
public Commands.Fetch Cmd = null;
|
||||
public DateTime NextRunTimepoint = DateTime.MinValue;
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public int Interval
|
||||
{
|
||||
get => _interval;
|
||||
set
|
||||
{
|
||||
_interval = Math.Max(1, value);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var job in _jobs)
|
||||
job.Value.NextRunTimepoint = DateTime.Now.AddMinutes(_interval * 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AutoFetchManager _instance = null;
|
||||
private Dictionary<string, Job> _jobs = new Dictionary<string, Job>();
|
||||
private object _lock = new object();
|
||||
private int _interval = 10;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!IsEnabled)
|
||||
{
|
||||
Thread.Sleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
var uptodate = new List<Job>();
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var job in _jobs)
|
||||
{
|
||||
if (job.Value.NextRunTimepoint.Subtract(now).TotalSeconds <= 0)
|
||||
uptodate.Add(job.Value);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var job in uptodate)
|
||||
{
|
||||
if (!File.Exists(job.IndexLockFile))
|
||||
{
|
||||
job.Cmd.Exec();
|
||||
job.NextRunTimepoint = DateTime.Now.AddMinutes(Convert.ToDouble(Interval));
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
|
||||
// ReSharper disable once FunctionNeverReturns
|
||||
});
|
||||
}
|
||||
|
||||
public void AddRepository(string repo, string gitDir)
|
||||
{
|
||||
var job = new Job
|
||||
{
|
||||
IndexLockFile = Path.Combine(gitDir, "index.lock"),
|
||||
Cmd = new Commands.Fetch(repo, "--all", true, false, null) { RaiseError = false },
|
||||
NextRunTimepoint = DateTime.Now.AddMinutes(Convert.ToDouble(Interval)),
|
||||
};
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_jobs[repo] = job;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRepository(string repo)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_jobs.Remove(repo);
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkFetched(string repo)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_jobs.TryGetValue(repo, out var value))
|
||||
value.NextRunTimepoint = DateTime.Now.AddMinutes(Interval * 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,85 +8,27 @@ namespace SourceGit.Models
|
|||
{
|
||||
public class CommitGraph
|
||||
{
|
||||
public class Path
|
||||
public static List<Pen> Pens { get; } = [];
|
||||
|
||||
public static void SetDefaultPens(double thickness = 2)
|
||||
{
|
||||
public List<Point> Points = new List<Point>();
|
||||
public int Color = 0;
|
||||
SetPens(s_defaultPenColors, thickness);
|
||||
}
|
||||
|
||||
public class PathHelper
|
||||
public static void SetPens(List<Color> colors, double thickness)
|
||||
{
|
||||
public string Next;
|
||||
public bool IsMerged;
|
||||
public double LastX;
|
||||
public double LastY;
|
||||
public double EndY;
|
||||
public Path Path;
|
||||
Pens.Clear();
|
||||
|
||||
public PathHelper(string next, bool isMerged, int color, Point start)
|
||||
{
|
||||
Next = next;
|
||||
IsMerged = isMerged;
|
||||
LastX = start.X;
|
||||
LastY = start.Y;
|
||||
EndY = LastY;
|
||||
foreach (var c in colors)
|
||||
Pens.Add(new Pen(c.ToUInt32(), thickness));
|
||||
|
||||
Path = new Path();
|
||||
Path.Color = color;
|
||||
Path.Points.Add(start);
|
||||
}
|
||||
s_penCount = colors.Count;
|
||||
}
|
||||
|
||||
public PathHelper(string next, bool isMerged, int color, Point start, Point to)
|
||||
{
|
||||
Next = next;
|
||||
IsMerged = isMerged;
|
||||
LastX = to.X;
|
||||
LastY = to.Y;
|
||||
EndY = LastY;
|
||||
|
||||
Path = new Path();
|
||||
Path.Color = color;
|
||||
Path.Points.Add(start);
|
||||
Path.Points.Add(to);
|
||||
}
|
||||
|
||||
public void Add(double x, double y, double halfHeight, bool isEnd = false)
|
||||
{
|
||||
if (x > LastX)
|
||||
{
|
||||
Add(new Point(LastX, LastY));
|
||||
Add(new Point(x, y - halfHeight));
|
||||
if (isEnd)
|
||||
Add(new Point(x, y));
|
||||
}
|
||||
else if (x < LastX)
|
||||
{
|
||||
var testY = LastY + halfHeight;
|
||||
if (y > testY)
|
||||
Add(new Point(LastX, testY));
|
||||
|
||||
if (!isEnd)
|
||||
y += halfHeight;
|
||||
|
||||
Add(new Point(x, y));
|
||||
}
|
||||
else if (isEnd)
|
||||
{
|
||||
Add(new Point(x, y));
|
||||
}
|
||||
|
||||
LastX = x;
|
||||
LastY = y;
|
||||
}
|
||||
|
||||
private void Add(Point p)
|
||||
{
|
||||
if (EndY < p.Y)
|
||||
{
|
||||
Path.Points.Add(p);
|
||||
EndY = p.Y;
|
||||
}
|
||||
}
|
||||
public class Path(int color)
|
||||
{
|
||||
public List<Point> Points { get; } = [];
|
||||
public int Color { get; } = color;
|
||||
}
|
||||
|
||||
public class Link
|
||||
|
@ -111,82 +53,57 @@ namespace SourceGit.Models
|
|||
public int Color;
|
||||
}
|
||||
|
||||
public List<Path> Paths { get; set; } = new List<Path>();
|
||||
public List<Link> Links { get; set; } = new List<Link>();
|
||||
public List<Dot> Dots { get; set; } = new List<Dot>();
|
||||
|
||||
public static List<Pen> Pens
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new List<Pen>();
|
||||
|
||||
public static void SetDefaultPens(double thickness = 2)
|
||||
{
|
||||
SetPens(_defaultPenColors, thickness);
|
||||
}
|
||||
|
||||
public static void SetPens(List<Color> colors, double thickness)
|
||||
{
|
||||
Pens.Clear();
|
||||
|
||||
foreach (var c in colors)
|
||||
Pens.Add(new Pen(c.ToUInt32(), thickness));
|
||||
|
||||
_penCount = colors.Count;
|
||||
}
|
||||
public List<Path> Paths { get; } = [];
|
||||
public List<Link> Links { get; } = [];
|
||||
public List<Dot> Dots { get; } = [];
|
||||
|
||||
public static CommitGraph Parse(List<Commit> commits, bool firstParentOnlyEnabled)
|
||||
{
|
||||
double UNIT_WIDTH = 12;
|
||||
double HALF_WIDTH = 6;
|
||||
double UNIT_HEIGHT = 28;
|
||||
double HALF_HEIGHT = 14;
|
||||
double H_MARGIN = 2;
|
||||
const double unitWidth = 12;
|
||||
const double halfWidth = 6;
|
||||
const double unitHeight = 28;
|
||||
const double halfHeight = 14;
|
||||
|
||||
var temp = new CommitGraph();
|
||||
var unsolved = new List<PathHelper>();
|
||||
var mapUnsolved = new Dictionary<string, PathHelper>();
|
||||
var ended = new List<PathHelper>();
|
||||
var offsetY = -HALF_HEIGHT;
|
||||
var offsetY = -halfHeight;
|
||||
var colorIdx = 0;
|
||||
|
||||
foreach (var commit in commits)
|
||||
{
|
||||
var major = null as PathHelper;
|
||||
var isMerged = commit.IsMerged;
|
||||
var oldCount = unsolved.Count;
|
||||
|
||||
// Update current y offset
|
||||
offsetY += UNIT_HEIGHT;
|
||||
offsetY += unitHeight;
|
||||
|
||||
// Find first curves that links to this commit and marks others that links to this commit ended.
|
||||
double offsetX = H_MARGIN - HALF_WIDTH;
|
||||
var offsetX = 4 - halfWidth;
|
||||
var maxOffsetOld = unsolved.Count > 0 ? unsolved[^1].LastX : offsetX + unitWidth;
|
||||
foreach (var l in unsolved)
|
||||
{
|
||||
if (l.Next == commit.SHA)
|
||||
if (l.Next.Equals(commit.SHA, StringComparison.Ordinal))
|
||||
{
|
||||
if (major == null)
|
||||
{
|
||||
offsetX += UNIT_WIDTH;
|
||||
offsetX += unitWidth;
|
||||
major = l;
|
||||
|
||||
if (commit.Parents.Count > 0)
|
||||
{
|
||||
major.Next = commit.Parents[0];
|
||||
if (!mapUnsolved.ContainsKey(major.Next))
|
||||
mapUnsolved.Add(major.Next, major);
|
||||
major.Goto(offsetX, offsetY, halfHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
major.Next = "ENDED";
|
||||
major.End(offsetX, offsetY, halfHeight);
|
||||
ended.Add(l);
|
||||
}
|
||||
|
||||
major.Add(offsetX, offsetY, HALF_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.End(major.LastX, offsetY, halfHeight);
|
||||
ended.Add(l);
|
||||
}
|
||||
|
||||
|
@ -195,17 +112,20 @@ namespace SourceGit.Models
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!mapUnsolved.ContainsKey(l.Next))
|
||||
mapUnsolved.Add(l.Next, l);
|
||||
offsetX += UNIT_WIDTH;
|
||||
l.Add(offsetX, offsetY, HALF_HEIGHT);
|
||||
offsetX += unitWidth;
|
||||
l.Pass(offsetX, offsetY, halfHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove ended curves from unsolved
|
||||
foreach (var l in ended)
|
||||
unsolved.Remove(l);
|
||||
ended.Clear();
|
||||
|
||||
// Create new curve for branch head
|
||||
if (major == null)
|
||||
{
|
||||
offsetX += UNIT_WIDTH;
|
||||
offsetX += unitWidth;
|
||||
|
||||
if (commit.Parents.Count > 0)
|
||||
{
|
||||
|
@ -214,18 +134,13 @@ namespace SourceGit.Models
|
|||
temp.Paths.Add(major.Path);
|
||||
}
|
||||
|
||||
colorIdx = (colorIdx + 1) % _penCount;
|
||||
colorIdx = (colorIdx + 1) % s_penCount;
|
||||
}
|
||||
|
||||
// Calculate link position of this commit.
|
||||
Point position = new Point(offsetX, offsetY);
|
||||
int dotColor = 0;
|
||||
if (major != null)
|
||||
{
|
||||
position = new Point(major.LastX, offsetY);
|
||||
dotColor = major.Path.Color;
|
||||
}
|
||||
Dot anchor = new Dot() { Center = position, Color = dotColor };
|
||||
var position = new Point(major?.LastX ?? offsetX, offsetY);
|
||||
var dotColor = major?.Path.Color ?? 0;
|
||||
var anchor = new Dot() { Center = position, Color = dotColor };
|
||||
if (commit.IsCurrentHead)
|
||||
anchor.Type = DotType.Head;
|
||||
else if (commit.Parents.Count > 1)
|
||||
|
@ -239,69 +154,176 @@ namespace SourceGit.Models
|
|||
{
|
||||
for (int j = 1; j < commit.Parents.Count; j++)
|
||||
{
|
||||
var parent = commit.Parents[j];
|
||||
if (mapUnsolved.TryGetValue(parent, out var value))
|
||||
var parentHash = commit.Parents[j];
|
||||
var parent = unsolved.Find(x => x.Next.Equals(parentHash, StringComparison.Ordinal));
|
||||
if (parent != null)
|
||||
{
|
||||
// Try to change the merge state of linked graph
|
||||
var l = value;
|
||||
if (isMerged)
|
||||
l.IsMerged = true;
|
||||
parent.IsMerged = true;
|
||||
|
||||
var link = new Link();
|
||||
link.Start = position;
|
||||
link.End = new Point(l.LastX, offsetY + HALF_HEIGHT);
|
||||
link.Control = new Point(link.End.X, link.Start.Y);
|
||||
link.Color = l.Path.Color;
|
||||
|
||||
temp.Links.Add(link);
|
||||
temp.Links.Add(new Link
|
||||
{
|
||||
Start = position,
|
||||
End = new Point(parent.LastX, offsetY + halfHeight),
|
||||
Control = new Point(parent.LastX, position.Y),
|
||||
Color = parent.Path.Color
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetX += UNIT_WIDTH;
|
||||
offsetX += unitWidth;
|
||||
|
||||
// Create new curve for parent commit that not includes before
|
||||
var l = new PathHelper(parent, isMerged, colorIdx, position, new Point(offsetX, position.Y + HALF_HEIGHT));
|
||||
var l = new PathHelper(parentHash, isMerged, colorIdx, position, new Point(offsetX, position.Y + halfHeight));
|
||||
unsolved.Add(l);
|
||||
temp.Paths.Add(l.Path);
|
||||
colorIdx = (colorIdx + 1) % _penCount;
|
||||
colorIdx = (colorIdx + 1) % s_penCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove ended curves from unsolved
|
||||
foreach (var l in ended)
|
||||
{
|
||||
l.Add(position.X, position.Y, HALF_HEIGHT, true);
|
||||
unsolved.Remove(l);
|
||||
}
|
||||
|
||||
// Margins & merge state (used by Views.Histories).
|
||||
commit.IsMerged = isMerged;
|
||||
commit.Margin = new Thickness(Math.Max(offsetX + HALF_WIDTH, oldCount * UNIT_WIDTH + H_MARGIN) + H_MARGIN, 0, 0, 0);
|
||||
|
||||
// Clean up
|
||||
ended.Clear();
|
||||
mapUnsolved.Clear();
|
||||
commit.Margin = new Thickness(Math.Max(offsetX, maxOffsetOld) + halfWidth + 2, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Deal with curves haven't ended yet.
|
||||
for (int i = 0; i < unsolved.Count; i++)
|
||||
for (var i = 0; i < unsolved.Count; i++)
|
||||
{
|
||||
var path = unsolved[i];
|
||||
var endY = (commits.Count - 0.5) * UNIT_HEIGHT;
|
||||
var endY = (commits.Count - 0.5) * unitHeight;
|
||||
|
||||
if (path.Path.Points.Count == 1 && Math.Abs(path.Path.Points[0].Y - endY) < 0.0001)
|
||||
continue;
|
||||
|
||||
path.Add((i + 0.5) * UNIT_WIDTH + H_MARGIN, endY + HALF_HEIGHT, HALF_HEIGHT, true);
|
||||
path.End((i + 0.5) * unitWidth + 4, endY + halfHeight, halfHeight);
|
||||
}
|
||||
unsolved.Clear();
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
private static int _penCount = 0;
|
||||
private static readonly List<Color> _defaultPenColors = [
|
||||
private class PathHelper
|
||||
{
|
||||
public Path Path { get; }
|
||||
public string Next { get; set; }
|
||||
public bool IsMerged { get; set; }
|
||||
public double LastX { get; private set; }
|
||||
|
||||
public PathHelper(string next, bool isMerged, int color, Point start)
|
||||
{
|
||||
Next = next;
|
||||
IsMerged = isMerged;
|
||||
LastX = start.X;
|
||||
_lastY = start.Y;
|
||||
|
||||
Path = new Path(color);
|
||||
Path.Points.Add(start);
|
||||
}
|
||||
|
||||
public PathHelper(string next, bool isMerged, int color, Point start, Point to)
|
||||
{
|
||||
Next = next;
|
||||
IsMerged = isMerged;
|
||||
LastX = to.X;
|
||||
_lastY = to.Y;
|
||||
|
||||
Path = new Path(color);
|
||||
Path.Points.Add(start);
|
||||
Path.Points.Add(to);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A path that just passed this row.
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="halfHeight"></param>
|
||||
public void Pass(double x, double y, double halfHeight)
|
||||
{
|
||||
if (x > LastX)
|
||||
{
|
||||
Add(LastX, _lastY);
|
||||
Add(x, y - halfHeight);
|
||||
}
|
||||
else if (x < LastX)
|
||||
{
|
||||
Add(LastX, y - halfHeight);
|
||||
y += halfHeight;
|
||||
Add(x, y);
|
||||
}
|
||||
|
||||
LastX = x;
|
||||
_lastY = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A path that has commit in this row but not ended
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="halfHeight"></param>
|
||||
public void Goto(double x, double y, double halfHeight)
|
||||
{
|
||||
if (x > LastX)
|
||||
{
|
||||
Add(LastX, _lastY);
|
||||
Add(x, y - halfHeight);
|
||||
}
|
||||
else if (x < LastX)
|
||||
{
|
||||
var minY = y - halfHeight;
|
||||
if (minY > _lastY)
|
||||
minY -= halfHeight;
|
||||
|
||||
Add(LastX, minY);
|
||||
Add(x, y);
|
||||
}
|
||||
|
||||
LastX = x;
|
||||
_lastY = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A path that has commit in this row and end.
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="halfHeight"></param>
|
||||
public void End(double x, double y, double halfHeight)
|
||||
{
|
||||
if (x > LastX)
|
||||
{
|
||||
Add(LastX, _lastY);
|
||||
Add(x, y - halfHeight);
|
||||
}
|
||||
else if (x < LastX)
|
||||
{
|
||||
Add(LastX, y - halfHeight);
|
||||
}
|
||||
|
||||
Add(x, y);
|
||||
|
||||
LastX = x;
|
||||
_lastY = y;
|
||||
}
|
||||
|
||||
private void Add(double x, double y)
|
||||
{
|
||||
if (_endY < y)
|
||||
{
|
||||
Path.Points.Add(new Point(x, y));
|
||||
_endY = y;
|
||||
}
|
||||
}
|
||||
|
||||
private double _lastY = 0;
|
||||
private double _endY = 0;
|
||||
}
|
||||
|
||||
private static int s_penCount = 0;
|
||||
private static readonly List<Color> s_defaultPenColors = [
|
||||
Colors.Orange,
|
||||
Colors.ForestGreen,
|
||||
Colors.Gold,
|
||||
|
|
16
src/Models/IRepository.cs
Normal file
16
src/Models/IRepository.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace SourceGit.Models
|
||||
{
|
||||
public interface IRepository
|
||||
{
|
||||
string FullPath { get; set; }
|
||||
string GitDir { get; set; }
|
||||
|
||||
void RefreshBranches();
|
||||
void RefreshWorktrees();
|
||||
void RefreshTags();
|
||||
void RefreshCommits();
|
||||
void RefreshSubmodules();
|
||||
void RefreshWorkingCopyChanges();
|
||||
void RefreshStashes();
|
||||
}
|
||||
}
|
|
@ -94,6 +94,18 @@ namespace SourceGit.Models
|
|||
set;
|
||||
} = new AvaloniaList<IssueTrackerRule>();
|
||||
|
||||
public bool EnableAutoFetch
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public int AutoFetchInterval
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = 10;
|
||||
|
||||
public void PushCommitMessage(string message)
|
||||
{
|
||||
var existIdx = CommitMessages.IndexOf(message);
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace SourceGit.Models
|
|||
[
|
||||
new ResetMode("Soft", "Keep all changes. Stage differences", "--soft", Brushes.Green),
|
||||
new ResetMode("Mixed", "Keep all changes. Unstage differences", "--mixed", Brushes.Orange),
|
||||
new ResetMode("Merge", "Reset while keeping unmerged changes", "--merge", Brushes.Purple),
|
||||
new ResetMode("Keep", "Reset while keeping local modifications", "--keep", Brushes.Purple),
|
||||
new ResetMode("Hard", "Discard all changes", "--hard", Brushes.Red),
|
||||
];
|
||||
|
||||
|
|
|
@ -1,122 +1,172 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using LiveChartsCore;
|
||||
using LiveChartsCore.Defaults;
|
||||
using LiveChartsCore.SkiaSharpView;
|
||||
using LiveChartsCore.SkiaSharpView.Painting;
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class StatisticsSample(string name)
|
||||
public enum StaticsticsMode
|
||||
{
|
||||
All,
|
||||
ThisMonth,
|
||||
ThisWeek,
|
||||
}
|
||||
|
||||
public class StaticsticsAuthor(string name, int count)
|
||||
{
|
||||
public string Name { get; set; } = name;
|
||||
public int Count { get; set; } = 0;
|
||||
public int Count { get; set; } = count;
|
||||
}
|
||||
|
||||
public class StaticsticsSample(DateTime time, int count)
|
||||
{
|
||||
public DateTime Time { get; set; } = time;
|
||||
public int Count { get; set; } = count;
|
||||
}
|
||||
|
||||
public class StatisticsReport
|
||||
{
|
||||
public static readonly string[] WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
|
||||
|
||||
public int Total { get; set; } = 0;
|
||||
public List<StatisticsSample> Samples { get; set; } = new List<StatisticsSample>();
|
||||
public List<StatisticsSample> ByAuthor { get; set; } = new List<StatisticsSample>();
|
||||
public List<StaticsticsAuthor> Authors { get; set; } = new List<StaticsticsAuthor>();
|
||||
public List<ISeries> Series { get; set; } = new List<ISeries>();
|
||||
public List<Axis> XAxes { get; set; } = new List<Axis>();
|
||||
public List<Axis> YAxes { get; set; } = new List<Axis>();
|
||||
|
||||
public void AddCommit(int index, string author)
|
||||
public StatisticsReport(StaticsticsMode mode, DateTime start)
|
||||
{
|
||||
Total++;
|
||||
Samples[index].Count++;
|
||||
_mode = mode;
|
||||
|
||||
if (_mapUsers.TryGetValue(author, out var value))
|
||||
YAxes = [new Axis()
|
||||
{
|
||||
value.Count++;
|
||||
TextSize = 10,
|
||||
MinLimit = 0,
|
||||
SeparatorsPaint = new SolidColorPaint(new SKColor(0x40808080)) { StrokeThickness = 1 }
|
||||
}];
|
||||
|
||||
if (mode == StaticsticsMode.ThisWeek)
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
_mapSamples.Add(start.AddDays(i), 0);
|
||||
|
||||
XAxes.Add(new DateTimeAxis(TimeSpan.FromDays(1), v => WEEKDAYS[(int)v.DayOfWeek]) { TextSize = 10 });
|
||||
}
|
||||
else if (mode == StaticsticsMode.ThisMonth)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var maxDays = DateTime.DaysInMonth(now.Year, now.Month);
|
||||
for (int i = 0; i < maxDays; i++)
|
||||
_mapSamples.Add(start.AddDays(i), 0);
|
||||
|
||||
XAxes.Add(new DateTimeAxis(TimeSpan.FromDays(1), v => $"{v:MM/dd}") { TextSize = 10 });
|
||||
}
|
||||
else
|
||||
{
|
||||
var sample = new StatisticsSample(author);
|
||||
sample.Count++;
|
||||
|
||||
_mapUsers.Add(author, sample);
|
||||
ByAuthor.Add(sample);
|
||||
XAxes.Add(new DateTimeAxis(TimeSpan.FromDays(30), v => $"{v:yyyy/MM}") { TextSize = 10 });
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCommit(DateTime time, string author)
|
||||
{
|
||||
Total++;
|
||||
|
||||
var normalized = DateTime.MinValue;
|
||||
if (_mode == StaticsticsMode.ThisWeek || _mode == StaticsticsMode.ThisMonth)
|
||||
normalized = time.Date;
|
||||
else
|
||||
normalized = new DateTime(time.Year, time.Month, 1).ToLocalTime();
|
||||
|
||||
if (_mapSamples.TryGetValue(normalized, out var vs))
|
||||
_mapSamples[normalized] = vs + 1;
|
||||
else
|
||||
_mapSamples.Add(normalized, 1);
|
||||
|
||||
if (_mapUsers.TryGetValue(author, out var vu))
|
||||
_mapUsers[author] = vu + 1;
|
||||
else
|
||||
_mapUsers.Add(author, 1);
|
||||
}
|
||||
|
||||
public void Complete()
|
||||
{
|
||||
ByAuthor.Sort((l, r) => r.Count - l.Count);
|
||||
var samples = new List<DateTimePoint>();
|
||||
foreach (var kv in _mapSamples)
|
||||
samples.Add(new DateTimePoint(kv.Key, kv.Value));
|
||||
|
||||
Series.Add(
|
||||
new ColumnSeries<DateTimePoint>()
|
||||
{
|
||||
Values = samples,
|
||||
Stroke = null,
|
||||
Fill = null,
|
||||
Padding = 1,
|
||||
}
|
||||
);
|
||||
|
||||
foreach (var kv in _mapUsers)
|
||||
Authors.Add(new StaticsticsAuthor(kv.Key, kv.Value));
|
||||
|
||||
Authors.Sort((l, r) => r.Count - l.Count);
|
||||
|
||||
_mapUsers.Clear();
|
||||
_mapSamples.Clear();
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, StatisticsSample> _mapUsers = new Dictionary<string, StatisticsSample>();
|
||||
public void ChangeColor(uint color)
|
||||
{
|
||||
if (Series is [ColumnSeries<DateTimePoint> series])
|
||||
series.Fill = new SolidColorPaint(new SKColor(color));
|
||||
}
|
||||
|
||||
private StaticsticsMode _mode = StaticsticsMode.All;
|
||||
private Dictionary<string, int> _mapUsers = new Dictionary<string, int>();
|
||||
private Dictionary<DateTime, int> _mapSamples = new Dictionary<DateTime, int>();
|
||||
}
|
||||
|
||||
public class Statistics
|
||||
{
|
||||
public StatisticsReport Year { get; set; } = new StatisticsReport();
|
||||
public StatisticsReport Month { get; set; } = new StatisticsReport();
|
||||
public StatisticsReport Week { get; set; } = new StatisticsReport();
|
||||
public StatisticsReport All { get; set; }
|
||||
public StatisticsReport Month { get; set; }
|
||||
public StatisticsReport Week { get; set; }
|
||||
|
||||
public Statistics()
|
||||
{
|
||||
_today = DateTime.Today;
|
||||
_thisWeekStart = _today.AddSeconds(-(int)_today.DayOfWeek * 3600 * 24 - _today.Hour * 3600 - _today.Minute * 60 - _today.Second);
|
||||
_thisWeekEnd = _thisWeekStart.AddDays(7);
|
||||
_today = DateTime.Now.ToLocalTime().Date;
|
||||
_thisWeekStart = _today.AddSeconds(-(int)_today.DayOfWeek * 3600 * 24);
|
||||
_thisMonthStart = _today.AddDays(1 - _today.Day);
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
Year.Samples.Add(new StatisticsSample(""));
|
||||
|
||||
var monthDays = DateTime.DaysInMonth(_today.Year, _today.Month);
|
||||
for (int i = 0; i < monthDays; i++)
|
||||
Month.Samples.Add(new StatisticsSample($"{i + 1}"));
|
||||
|
||||
string[] weekDayNames = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
|
||||
for (int i = 0; i < weekDayNames.Length; i++)
|
||||
Week.Samples.Add(new StatisticsSample(weekDayNames[i]));
|
||||
}
|
||||
|
||||
public string Since()
|
||||
{
|
||||
return _today.AddMonths(-11).ToString("yyyy-MM-01 00:00:00");
|
||||
All = new StatisticsReport(StaticsticsMode.All, DateTime.MinValue);
|
||||
Month = new StatisticsReport(StaticsticsMode.ThisMonth, _thisMonthStart);
|
||||
Week = new StatisticsReport(StaticsticsMode.ThisWeek, _thisWeekStart);
|
||||
}
|
||||
|
||||
public void AddCommit(string author, double timestamp)
|
||||
{
|
||||
var time = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime();
|
||||
if (time.CompareTo(_thisWeekStart) >= 0 && time.CompareTo(_thisWeekEnd) < 0)
|
||||
Week.AddCommit((int)time.DayOfWeek, author);
|
||||
if (time >= _thisWeekStart)
|
||||
Week.AddCommit(time, author);
|
||||
|
||||
if (time.Month == _today.Month)
|
||||
Month.AddCommit(time.Day - 1, author);
|
||||
if (time >= _thisMonthStart)
|
||||
Month.AddCommit(time, author);
|
||||
|
||||
Year.AddCommit(time.Month - 1, author);
|
||||
All.AddCommit(time, author);
|
||||
}
|
||||
|
||||
public void Complete()
|
||||
{
|
||||
Year.Complete();
|
||||
All.Complete();
|
||||
Month.Complete();
|
||||
Week.Complete();
|
||||
|
||||
// Year is start from 11 months ago from now.
|
||||
var thisYear = _today.Year;
|
||||
var start = _today.AddMonths(-11);
|
||||
if (start.Month == 1)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
Year.Samples[i].Name = $"{thisYear}/{i + 1:00}";
|
||||
}
|
||||
else
|
||||
{
|
||||
var lastYearIdx = start.Month - 1;
|
||||
var lastYearMonths = Year.Samples.GetRange(lastYearIdx, 12 - lastYearIdx);
|
||||
for (int i = 0; i < lastYearMonths.Count; i++)
|
||||
lastYearMonths[i].Name = $"{thisYear - 1}/{lastYearIdx + i + 1:00}";
|
||||
|
||||
var thisYearMonths = Year.Samples.GetRange(0, lastYearIdx);
|
||||
for (int i = 0; i < thisYearMonths.Count; i++)
|
||||
thisYearMonths[i].Name = $"{thisYear}/{i + 1:00}";
|
||||
|
||||
Year.Samples.Clear();
|
||||
Year.Samples.AddRange(lastYearMonths);
|
||||
Year.Samples.AddRange(thisYearMonths);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly DateTime _today;
|
||||
private readonly DateTime _thisMonthStart;
|
||||
private readonly DateTime _thisWeekStart;
|
||||
private readonly DateTime _thisWeekEnd;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace SourceGit.Models
|
|||
extension = ".sh";
|
||||
else if (extension == ".kt" || extension == ".kts")
|
||||
extension = ".kotlin";
|
||||
|
||||
|
||||
foreach (var grammar in s_extraGrammars)
|
||||
{
|
||||
if (grammar.Extension.Equals(extension, StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -87,7 +87,7 @@ namespace SourceGit.Models
|
|||
public ICollection<string> GetInjections(string scopeName) => _backend.GetInjections(scopeName);
|
||||
public IRawGrammar GetGrammar(string scopeName) => GrammarUtility.GetGrammar(scopeName, _backend);
|
||||
public string GetScope(string filename) => GrammarUtility.GetScope(filename, _backend);
|
||||
|
||||
|
||||
private readonly RegistryOptions _backend = new(defaultTheme);
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,8 @@ namespace SourceGit.Models
|
|||
{
|
||||
public static TextMate.Installation CreateForEditor(TextEditor editor)
|
||||
{
|
||||
return editor.InstallTextMate(Application.Current?.ActualThemeVariant == ThemeVariant.Dark ?
|
||||
new RegistryOptionsWrapper(ThemeName.DarkPlus) :
|
||||
return editor.InstallTextMate(Application.Current?.ActualThemeVariant == ThemeVariant.Dark ?
|
||||
new RegistryOptionsWrapper(ThemeName.DarkPlus) :
|
||||
new RegistryOptionsWrapper(ThemeName.LightPlus));
|
||||
}
|
||||
|
||||
|
|
|
@ -6,20 +6,6 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public interface IRepository
|
||||
{
|
||||
string FullPath { get; set; }
|
||||
string GitDir { get; set; }
|
||||
|
||||
void RefreshBranches();
|
||||
void RefreshWorktrees();
|
||||
void RefreshTags();
|
||||
void RefreshCommits();
|
||||
void RefreshSubmodules();
|
||||
void RefreshWorkingCopyChanges();
|
||||
void RefreshStashes();
|
||||
}
|
||||
|
||||
public class Watcher : IDisposable
|
||||
{
|
||||
public Watcher(IRepository repo)
|
||||
|
|
|
@ -201,9 +201,9 @@ namespace SourceGit.Native
|
|||
|
||||
private void FixWindowFrameOnWin10(Window w)
|
||||
{
|
||||
if (w.WindowState != WindowState.Normal)
|
||||
if (w.WindowState == WindowState.Maximized || w.WindowState == WindowState.FullScreen)
|
||||
w.SystemDecorations = SystemDecorations.Full;
|
||||
else
|
||||
else if (w.WindowState == WindowState.Normal)
|
||||
w.SystemDecorations = SystemDecorations.BorderOnly;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<StreamGeometry x:Key="Icons.Clean">M797 829a49 49 0 1049 49 49 49 0 00-49-49zm147-114A49 49 0 10992 764a49 49 0 00-49-49zM928 861a49 49 0 1049 49A49 49 0 00928 861zm-5-586L992 205 851 64l-71 71a67 67 0 00-94 0l235 235a67 67 0 000-94zm-853 128a32 32 0 00-32 50 1291 1291 0 0075 112L288 552c20 0 25 21 8 37l-93 86a1282 1282 0 00120 114l100-32c19-6 28 15 14 34l-40 55c26 19 53 36 82 53a89 89 0 00115-20 1391 1391 0 00256-485l-188-188s-306 224-595 198z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Clone">M1280 704c0 141-115 256-256 256H288C129 960 0 831 0 672c0-126 80-232 192-272A327 327 0 01192 384c0-177 143-320 320-320 119 0 222 64 277 160C820 204 857 192 896 192c106 0 192 86 192 192 0 24-5 48-13 69C1192 477 1280 580 1280 704zm-493-128H656V352c0-18-14-32-32-32h-96c-18 0-32 14-32 32v224h-131c-29 0-43 34-23 55l211 211c12 12 33 12 45 0l211-211c20-20 6-55-23-55z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Code">M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.ColorPicker">M128 854h768v86H128zM390 797c13 13 29 19 48 19s35-6 45-19l291-288c26-22 26-64 0-90L435 83l-61 61L426 192l-272 269c-22 22-22 64 0 90l237 246zm93-544 211 211-32 32H240l243-243zM707 694c0 48 38 86 86 86 48 0 86-38 86-86 0-22-10-45-26-61L794 576l-61 61c-13 13-26 35-26 58z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Commit">M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Compare">M645 448l64 64 220-221L704 64l-64 64 115 115H128v90h628zM375 576l-64-64-220 224L314 960l64-64-116-115H896v-90H262z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Conflict">M608 0q48 0 88 23t63 63 23 87v70h55q35 0 67 14t57 38 38 57 14 67V831q0 34-14 66t-38 57-57 38-67 13H426q-34 0-66-13t-57-38-38-57-14-66v-70h-56q-34 0-66-14t-57-38-38-57-13-67V174q0-47 23-87T109 23 196 0h412m175 244H426q-46 0-86 22T278 328t-26 85v348H608q47 0 86-22t63-62 25-85l1-348m-269 318q18 0 31 13t13 31-13 31-31 13-31-13-13-31 13-31 31-13m0-212q13 0 22 9t11 22v125q0 14-9 23t-22 10-23-7-11-22l-1-126q0-13 10-23t23-10z</StreamGeometry>
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
<x:String x:Key="Text.Close" xml:space="preserve">SCHLIESSEN</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Diesen Commit cherry-picken</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Mehrere cherry-picken</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Commit auschecken</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
|
||||
|
@ -128,6 +129,7 @@
|
|||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">VORGÄNGER</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Im Browser öffnen</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Commit-Nachricht</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Details</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Einstellungen</x:String>
|
||||
|
@ -137,6 +139,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email Adresse</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(n)</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Beispiel für Jira-Regel hinzufügen</x:String>
|
||||
|
@ -290,6 +294,7 @@
|
|||
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Sperren anzeigen</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">Keine gesperrten Dateien</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Sperre</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Zeige nur meine Sperren</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Sperren</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Entsperren</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Erzwinge entsperren</x:String>
|
||||
|
@ -410,9 +415,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Längenvorgabe für Commit-Nachrichten</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Auto-Fetch Intervall</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(n)</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Aktiviere Auto-CRLF</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Clone Standardordner</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">Benutzer Email</x:String>
|
||||
|
@ -430,6 +432,10 @@
|
|||
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">Installationspfad zum GPG Programm</x:String>
|
||||
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">Benutzer Signierungsschlüssel</x:String>
|
||||
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">GPG Benutzer Signierungsschlüssel</x:String>
|
||||
<x:String x:Key="Text.Preference.Integration" xml:space="preserve">EINBINDUNGEN</x:String>
|
||||
<x:String x:Key="Text.Preference.Shell" xml:space="preserve">SHELL/TERMINAL</x:String>
|
||||
<x:String x:Key="Text.Preference.Shell.Type" xml:space="preserve">Shell/Terminal</x:String>
|
||||
<x:String x:Key="Text.Preference.Shell.Path" xml:space="preserve">Pfad</x:String>
|
||||
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Remote löschen</x:String>
|
||||
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Ziel:</x:String>
|
||||
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Worktrees löschen</x:String>
|
||||
|
@ -486,6 +492,7 @@
|
|||
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Eindeutiger Name für diesen Branch</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABBRECHEN</x:String>
|
||||
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Änderungen automatisch von Remote fetchen...</x:String>
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC & Prune)</x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Alles löschen</x:String>
|
||||
|
@ -505,7 +512,6 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">REMOTE HINZUFÜGEN</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">KONFLIKTE BEHEBEN</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Commit suchen</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Suche über</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Dateiname</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
|
@ -546,6 +552,7 @@
|
|||
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Es sind momentan kein Updates verfügbar.</x:String>
|
||||
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>
|
||||
<x:String x:Key="Text.Squash.Into" xml:space="preserve">In:</x:String>
|
||||
<x:String x:Key="Text.SSHKey" xml:space="preserve">SSH privater Schlüssel:</x:String>
|
||||
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Pfad zum privaten SSH Schlüssel</x:String>
|
||||
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
|
||||
|
@ -567,9 +574,9 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MONAT</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">WOCHE</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">JAHR</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">AUTOREN: </x:String>
|
||||
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">ÜBERSICHT</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULE</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Submodul hinzufügen</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Relativen Pfad kopieren</x:String>
|
||||
|
@ -616,7 +623,6 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT & PUSH</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/Historie</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">STRG + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">KONFLIKTE ERKANNT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">DATEI KONFLIKTE GELÖST</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String>
|
||||
|
|
|
@ -136,6 +136,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(s)</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Add Sample Jira Rule</x:String>
|
||||
|
@ -289,6 +291,7 @@
|
|||
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Show Locks</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No Locked Files</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Lock</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Show only my locks</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Locks</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Unlock</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Force Unlock</x:String>
|
||||
|
@ -324,6 +327,7 @@
|
|||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit staged changes</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit and push staged changes</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Stage all changes and commit</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">Discard selected changes</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Dashboard mode (Default)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Force to reload this repository</x:String>
|
||||
|
@ -409,9 +413,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Auto Fetch Interval</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(s)</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Default Clone Dir</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">User Email</x:String>
|
||||
|
@ -489,6 +490,7 @@
|
|||
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String>
|
||||
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching changes from remotes...</x:String>
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC & Prune)</x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
|
||||
|
@ -508,11 +510,11 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">RESOLVE</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Search By</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">File</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Message</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">Author & Committer</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Current Branch</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Show Tags as Tree</x:String>
|
||||
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistics</x:String>
|
||||
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMODULES</x:String>
|
||||
|
@ -571,9 +573,9 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MONTH</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">WEEK</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">YEAR</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">AUTHORS: </x:String>
|
||||
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">OVERVIEW</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULES</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Add Submodule</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copy Relative Path</x:String>
|
||||
|
@ -620,7 +622,8 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT & PUSH</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/Histories</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Trigger click event</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Stage all changes and commit</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUDE UNTRACKED FILES</x:String>
|
||||
|
|
|
@ -2,178 +2,181 @@
|
|||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceInclude Source="avares://SourceGit/Resources/Locales/en_US.axaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<x:String x:Key="Text.About" xml:space="preserve">A propos</x:String>
|
||||
<x:String x:Key="Text.About.Menu" xml:space="preserve">A propos de SourceGit</x:String>
|
||||
|
||||
<x:String x:Key="Text.About" xml:space="preserve">À propos</x:String>
|
||||
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Compilé avec </x:String>
|
||||
<x:String x:Key="Text.About.Copyright" xml:space="preserve">© 2024 sourcegit-scm</x:String>
|
||||
<x:String x:Key="Text.About.Editor" xml:space="preserve">• TextEditor de </x:String>
|
||||
<!-- Seemingly not used yet -->
|
||||
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• La police Monospace vient de </x:String>
|
||||
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• Les polices Monospace proviennent de </x:String>
|
||||
<x:String x:Key="Text.About.Menu" xml:space="preserve">À propos de SourceGit</x:String>
|
||||
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Le code source est disponible sur </x:String>
|
||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client Git gratuit et open source</x:String>
|
||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client Git Open Source et Gratuit</x:String>
|
||||
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Ajouter un Worktree</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Branche existante</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Créer une nouvelle branche</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Location:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Emplacement :</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Chemin vers ce worktree. Relatif supporté.</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Nom de branche:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optionnel. Par défaut le nom du dossier de destination.</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optionnel. Nom du dossier de destination par défaut.</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Suivre la branche :</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Suivi de la branche distante</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Créer une nouvelle branche</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Branche existante</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Appliquer</x:String>
|
||||
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erreur</x:String>
|
||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Soulever les erreurs et refuser d'appliquer le patch</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Toutes erreurs</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similaire à 'error', mais plus détaillé</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Toutes les erreurs</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similaire à 'Erreur', mais plus détaillé</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Fichier de patch :</x:String>
|
||||
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selectionner le fichier .patch à appliquer</x:String>
|
||||
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorer les espaces blancs</x:String>
|
||||
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorer les changements d'espaces blancs</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Pas d'avertissement</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Désactive l'avertissement des espaces blancs terminaux</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Désactiver l'avertissement sur les espaces blancs terminaux</x:String>
|
||||
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Appliquer le patch</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Affiche les avertissements Outputs warnings for a few such errors, mais applique</x:String>
|
||||
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espace blanc:</x:String>
|
||||
<x:String x:Key="Text.Archive" xml:space="preserve">Archive...</x:String>
|
||||
<x:String x:Key="Text.Archive.File" xml:space="preserve">Sauvegarder l'archive vers :</x:String>
|
||||
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Selectionner le chemin de l'archive</x:String>
|
||||
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Révision:</x:String>
|
||||
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archive</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Avertissement</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Affiche des avertissements pour ce type d'erreurs tout en appliquant le patch</x:String>
|
||||
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espaces blancs :</x:String>
|
||||
<x:String x:Key="Text.Archive" xml:space="preserve">Archiver...</x:String>
|
||||
<x:String x:Key="Text.Archive.File" xml:space="preserve">Enregistrer l'archive sous :</x:String>
|
||||
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Sélectionnez le chemin du fichier d'archive</x:String>
|
||||
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Révision :</x:String>
|
||||
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archiver</x:String>
|
||||
<x:String x:Key="Text.Askpass" xml:space="preserve">SourceGit Askpass</x:String>
|
||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String>
|
||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">SUPPRIMER</x:String>
|
||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String>
|
||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME SUR CE FICHIER NON SUPPORTÉ !!!</x:String>
|
||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String>
|
||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparer avec la branche</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparer avec le Worktree</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparer avec le worktree</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copier le nom de la branche</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Supprimer ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Supprimer {0} branches sélectionnées</x:String>
|
||||
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Rejeter tous les changements</x:String>
|
||||
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finir ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merger ${0}$ dans ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Pull ${0}$ dans ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ sur ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward vers ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Terminer ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Fusionner ${0}$ dans ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Tirer ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Tirer ${0}$ dans ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Pousser ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebaser ${0}$ sur ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renommer ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Définir la branche de suivi</x:String>
|
||||
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String>
|
||||
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Ne plus suivre la branche distante</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparer les branches</x:String>
|
||||
<x:String x:Key="Text.Bytes" xml:space="preserve">Octets</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">ANNULER</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset vers cette révision</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Reset vers la révision parente</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Réinitialiser à la révision parente</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Réinitialiser à cette révision</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGER LE MODE D'AFFICHAGE</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Afficher comme liste de dossiers/fichiers</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Afficher comme liste de chemins</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">Afficher comme arborescence</x:String>
|
||||
<x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Branch</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Avertissement: un checkout vers un commit aboutiera vers un HEAD détaché</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout ce commit</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit :</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branche :</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Changement locaux:</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Avertissement: un checkout vers un commit aboutiera vers un HEAD détaché</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Changements locaux :</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Annuler</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.DoNothing" xml:space="preserve">Ne rien faire</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash et Réappliquer</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry-Pick</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s) :</x:String>
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Mettre en stash et réappliquer</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branche :</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry-Pick de ce commit</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit :</x:String>
|
||||
<x:String x:Key="Text.CherryPick.CommitChanges" xml:space="preserve">Commit tous les changements</x:String>
|
||||
<x:String x:Key="Text.ClearStashes" xml:space="preserve">Vider les Stashes</x:String>
|
||||
<x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">Voulez-vous vider tous les stashes. Êtes-vous sûr de vouloir continuer ?</x:String>
|
||||
<x:String x:Key="Text.Clone" xml:space="preserve">Cloner le dépôt distant</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Title" xml:space="preserve">Cherry Pick</x:String>
|
||||
<x:String x:Key="Text.ClearStashes" xml:space="preserve">Supprimer les stashes</x:String>
|
||||
<x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">Vous essayez de supprimer tous les stashes. Êtes-vous sûr de vouloir continuer ?</x:String>
|
||||
<x:String x:Key="Text.Clone.AdditionalParam" xml:space="preserve">Paramètres supplémentaires :</x:String>
|
||||
<x:String x:Key="Text.Clone.AdditionalParam.Placeholder" xml:space="preserve">Arguments additionnels au clônage. Optionnel.</x:String>
|
||||
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nom local :</x:String>
|
||||
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nom de dépôt. Optionnel.</x:String>
|
||||
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Dossier parent :</x:String>
|
||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL du dépôt :</x:String>
|
||||
<x:String x:Key="Text.Clone" xml:space="preserve">Cloner le dépôt distant</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">FERMER</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Éditeur</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Changer de commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick ce commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout ce commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Comparer avec le Worktree</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copier les infos</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Comparer avec le worktree</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copier les informations</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copier le SHA</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Rebase interactif de ${0}$ ici</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ ici</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ ici</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebaser ${0}$ ici</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Réinitialiser ${0}$ ici</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Annuler le commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reformuler</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Sauver en tant que patch...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Enregistrer en tant que patch...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash dans le parent</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGEMENTS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Chercher des changements...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Rechercher les changements...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FICHIERS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Fichiers LFS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Fichier LFS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Sous-module</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATION</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATIONS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTEUR</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGÉ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Vérifier les références contenant ce commit</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">LE COMMIT EST CONTENU PAR</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Afficher seulement les 100 premiers changements. Voir tous les changements dans l'onglet CHANGEMENTS.</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">MESSAGE</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Enter le sujet du commit</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Description</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configurer</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Entrez le message du commit</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Configurer le dépôt</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">MODÈLE DE COMMIT</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Nom de modèle:</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Contenu de modèle:</x:String>
|
||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Addresse e-mail</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Addresse e-mail</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Nom de modèle:</x:String>
|
||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Adresse e-mail</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Adresse e-mail</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Add Sample Jira Rule</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Fetch les dépôts distants automatiquement</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">minute(s)</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">SUIVI DES PROBLÈMES</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Ajouter une règle d'exemple Github</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Ajouter une règle d'exemple Jira</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">Nouvelle règle</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">Issue Regex Expression:</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Nom de règle :</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Veuillez utiliser $1, $2 pour accéder aux valeurs des groupes regex.</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">URL résultant:</x:String>
|
||||
<!-- A vérifier -->
|
||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
|
||||
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
|
||||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP proxy used by this repository</x:String>
|
||||
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">Proxy HTTP</x:String>
|
||||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">Proxy HTTP utilisé par ce dépôt</x:String>
|
||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">Nom d'utilisateur</x:String>
|
||||
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Nom d'utilisateur pour ce dépôt</x:String>
|
||||
<x:String x:Key="Text.Copy" xml:space="preserve">Copier</x:String>
|
||||
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copier tout le texte</x:String>
|
||||
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copier le nom de fichier</x:String>
|
||||
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPIER LE MESSAGE</x:String>
|
||||
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copier le chemin</x:String>
|
||||
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copier le nom de fichier</x:String>
|
||||
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Créer une branche...</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basé sur :</x:String>
|
||||
<!-- A vérifier si féminin-->
|
||||
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Check out the created branch</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Passer à la branche créée</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">Changements locaux :</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">Ne rien faire</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Réappliquer</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nouveau nom de branche:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter le nom de branche.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nom de la nouvelle branche :</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Entrez le nom de la branche.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Créer une branche locale</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Créer un tag...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nouveau tag à :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Signature GPG</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Message de tag :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Message du tag :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Message.Placeholder" xml:space="preserve">Optionnel.</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Nom de tag :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Format Recommendé : v1.0.0-alpha</x:String>
|
||||
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push vers tous les arpès création</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Nom du tag :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Format recommandé : v1.0.0-alpha</x:String>
|
||||
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Pousser sur tous les dépôts distants après création</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Créer un nouveau tag</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Kind:</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Type :</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">annoté</x:String>
|
||||
<!-- A vérifier si féminin-->
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">léger</x:String>
|
||||
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Maintenir Ctrl pour commencer directement</x:String>
|
||||
<x:String x:Key="Text.Cut" xml:space="preserve">Couper</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Supprimer la branche</x:String>
|
||||
|
@ -187,39 +190,39 @@
|
|||
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Cible :</x:String>
|
||||
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirmer la suppression du groupe</x:String>
|
||||
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirmer la suppression du dépôt</x:String>
|
||||
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Supprimer le Sous-module</x:String>
|
||||
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Supprimer le sous-module</x:String>
|
||||
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Chemin du sous-module :</x:String>
|
||||
<x:String x:Key="Text.DeleteTag" xml:space="preserve">Supprimer le tag</x:String>
|
||||
<x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Tag:</x:String>
|
||||
<x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Delete from remote repositories</x:String>
|
||||
<x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Tag :</x:String>
|
||||
<x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Supprimer des dépôts distants</x:String>
|
||||
<x:String x:Key="Text.Diff.Binary" xml:space="preserve">DIFF BINAIRE</x:String>
|
||||
<x:String x:Key="Text.Diff.Binary.New" xml:space="preserve">NOUVEAU</x:String>
|
||||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ANCIEN</x:String>
|
||||
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Copier</x:String>
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Mode de fichier changé</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJECT CHANGE</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">CHANGEMENT D'OBJET LFS</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Différence suivante</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">PAS DE CHANGEMENT OU SEULEMENT EN FIN DE LIGNE</x:String>
|
||||
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Différence précédente</x:String>
|
||||
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Afficher les caractères invisibles</x:String>
|
||||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diff côte-à-côte</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SOUS-MODULE</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NOUVEAU</x:String>
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Permuter</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Coloration syntaxique</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Retour à la ligne</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Ouvrir dans l'outil de merge</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Ouvrir dans l'outil de fusion</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Réduit le nombre de ligne visibles</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Augmente le nombre de ligne visibles</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SÉLECTIONNER UN FICHIER POUR VOIR LES CHANGEMENTS</x:String>
|
||||
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Afficher les caractères invisibles</x:String>
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Permuter</x:String>
|
||||
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Ouvrir dans l'outil de merge</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SÉLECTIONNEZ UN FICHIER POUR VOIR LES CHANGEMENTS</x:String>
|
||||
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Ouvrir dans l'outil de fusion</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">Rejeter les changements</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">Tous les changements dans la copie de travail.</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changements :</x:String>
|
||||
<x:String x:Key="Text.Discard.Total" xml:space="preserve">{0} changements seront rejetés</x:String>
|
||||
<x:String x:Key="Text.Discard.Warning" xml:space="preserve">Vous ne pouvez pas annuler cette action !!!</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Bookmark:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">Nouveau nom:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Signet :</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">Nouveau nom :</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Cible :</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Éditer le groupe sélectionné</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Éditer le dépôt sélectionné</x:String>
|
||||
|
@ -227,28 +230,28 @@
|
|||
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch toutes les branches distantes</x:String>
|
||||
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Fetch sans les tags</x:String>
|
||||
<x:String x:Key="Text.Fetch.Prune" xml:space="preserve">Purger les branches distantes mortes</x:String>
|
||||
<x:String x:Key="Text.Fetch.Prune" xml:space="preserve">Élaguer les branches mortes distantes</x:String>
|
||||
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote :</x:String>
|
||||
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch des changements distants</x:String>
|
||||
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Récupérer les changements distants</x:String>
|
||||
<x:String x:Key="Text.FileCM.AssumeUnchanged" xml:space="preserve">Présumer inchangé</x:String>
|
||||
<x:String x:Key="Text.FileCM.Discard" xml:space="preserve">Rejeter...</x:String>
|
||||
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Rejeter {0} fichiers...</x:String>
|
||||
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Rejeter les changements dans les lignes sélectionnées</x:String>
|
||||
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Ouvrir l'outil de merge externe</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Savegarder le patch sous...</x:String>
|
||||
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
|
||||
<!-- Est-ce un verbe ou un nom ? -->
|
||||
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} files</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Changes in Selected Line(s)</x:String>
|
||||
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Ouvrir l'outil de fusion externe</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Enregistrer en tant que patch...</x:String>
|
||||
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Indexer</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Indexer {0} fichiers</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Indexer les changements dans les lignes sélectionnées</x:String>
|
||||
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">Stash...</x:String>
|
||||
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">Stash {0} fichiers...</x:String>
|
||||
<x:String x:Key="Text.FileCM.Unstage" xml:space="preserve">Unstage</x:String>
|
||||
<x:String x:Key="Text.FileCM.UnstageMulti" xml:space="preserve">Unstage {0} files</x:String>
|
||||
<x:String x:Key="Text.FileCM.UnstageSelectedLines" xml:space="preserve">Unstage Changes in Selected Line(s)</x:String>
|
||||
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">Use Theirs (checkout --theirs)</x:String>
|
||||
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">Use Mine (checkout --ours)</x:String>
|
||||
<x:String x:Key="Text.FileHistory" xml:space="preserve">File History</x:String>
|
||||
<x:String x:Key="Text.Filter" xml:space="preserve">FILTER</x:String>
|
||||
<x:String x:Key="Text.FileCM.Unstage" xml:space="preserve">Désindexer</x:String>
|
||||
<x:String x:Key="Text.FileCM.UnstageMulti" xml:space="preserve">Désindexer {0} fichiers</x:String>
|
||||
<x:String x:Key="Text.FileCM.UnstageSelectedLines" xml:space="preserve">Désindexer les changements dans les lignes sélectionnées</x:String>
|
||||
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">Utiliser les miennes (checkout --ours)</x:String>
|
||||
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">Utiliser les leurs (checkout --theirs)</x:String>
|
||||
<x:String x:Key="Text.FileHistory" xml:space="preserve">Historique du fichier</x:String>
|
||||
<x:String x:Key="Text.FileHistory.FileContent" xml:space="preserve">CONTENU</x:String>
|
||||
<x:String x:Key="Text.Filter" xml:space="preserve">FILTRER</x:String>
|
||||
<x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String>
|
||||
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Development Branch:</x:String>
|
||||
<x:String x:Key="Text.GitFlow.Feature" xml:space="preserve">Feature:</x:String>
|
||||
|
@ -397,9 +400,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Historique de commits</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Guide de longueur du sujet</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch les dépôts distants automatiquement</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Intervalle de fetch auto</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">minute(s)</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Activer auto CRLF</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Répertoire de clônage par défaut</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">E-mail utilsateur</x:String>
|
||||
|
@ -492,7 +492,6 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">RESOLVE</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Search By</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">File</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Message</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
|
@ -552,7 +551,6 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MONTH</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">WEEK</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">YEAR</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">AUTHORS: </x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULES</x:String>
|
||||
|
@ -599,7 +597,6 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT & PUSH</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Modèles/Historiques</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Entrée</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLITS DÉTECTÉS</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">LES CONFLITS DE FICHIER SONT RÉSOLUS</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLURE LES FICHIERS NON-SUIVIS</x:String>
|
||||
|
|
|
@ -132,6 +132,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Endereço de Email</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Endereço de email</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Buscar remotos automaticamente</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minuto(s)</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">RASTREADOR DE PROBLEMAS</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Adicionar Regra de Exemplo do Github</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Adicionar Regra de Exemplo do Jira</x:String>
|
||||
|
@ -391,9 +393,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Commits do Histórico</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Comprimento do Guia de Assunto</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Buscar remotos automaticamente</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Intervalo de Busca Automática</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minuto(s)</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Habilitar Auto CRLF</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Diretório Padrão de Clone</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">E-mail do Usuário</x:String>
|
||||
|
@ -485,7 +484,6 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADICIONAR REMOTO</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">RESOLVER</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Pesquisar Commit</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Pesquisar Por</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Arquivo</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Mensagem</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
|
@ -545,7 +543,6 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MÊS</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">SEMANA</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">ANO</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">AUTORES: </x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMÓDULOS</x:String>
|
||||
|
@ -592,7 +589,6 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT & PUSH</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/Histories</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLITOS DETECTADOS</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">CONFLITOS DE ARQUIVOS RESOLVIDOS</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUIR ARQUIVOS NÃO RASTREADOS</x:String>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceInclude Source="avares://SourceGit/Resources/Locales/en_US.axaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<x:String x:Key="Text.About" xml:space="preserve">О программе</x:String>
|
||||
<x:String x:Key="Text.About.Menu" xml:space="preserve">О SourceGit</x:String>
|
||||
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Сборка с </x:String>
|
||||
|
@ -118,7 +121,7 @@
|
|||
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">ИНФОРМАЦИЯ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">АВТОР</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">ИЗМЕНЁННЫЙ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">ФИКСАТОР</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">ИСПОЛНИТЕЛЬ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Проверить ссылки, содержащие эту фиксацию</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">ФИКСАЦИЯ СОДЕРЖИТСЯ В</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Отображаются только первые 100 изменений. Смотрите все изменения на вкладке ИЗМЕНЕНИЯ.</x:String>
|
||||
|
@ -136,6 +139,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Адрес электронной почты</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Адрес электронной почты</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Автоматическое извлечение внешних хранилищ</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Минут(а/ы)</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ОТСЛЕЖИВАНИЕ ПРОБЛЕМ</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Добавить пример правила для Git</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Добавить пример правила Jira</x:String>
|
||||
|
@ -176,8 +181,8 @@
|
|||
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Выложить на все внешние хранилища после создания</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Создать новый тег</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Добрый:</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">аннотированный</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">лёгкий</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">Аннотированный</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">Лёгкий</x:String>
|
||||
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Удерживайте Ctrl, чтобы начать непосредственно</x:String>
|
||||
<x:String x:Key="Text.Cut" xml:space="preserve">Вырезать</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Удалить ветку</x:String>
|
||||
|
@ -289,10 +294,11 @@
|
|||
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Показать блокировки</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">Нет заблокированных файлов</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Блокировка</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Показывать только мои блокировки</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">Блокировки ХБФ</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Разблокировка</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Принудительная разблокировка</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Обрезка</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Разблокировать</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Принудительно разблокировать</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Обрезать</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Запустите `git lfs prune", чтобы удалить старые файлы ХБФ из локального хранилища</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Забрать</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Забрать объекты ХБФ</x:String>
|
||||
|
@ -324,6 +330,7 @@
|
|||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">ХРАНИЛИЩЕ</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Фиксация подготовленных изменений</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Фиксировать и выложить подготовленные изменения</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Подготовить все изменения и зафиксировать</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">Отклонить выбранные изменения</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Режим доски (по-умолчанию)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Принудительно перезагрузить этот репозиторий</x:String>
|
||||
|
@ -342,10 +349,10 @@
|
|||
<x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Отклонить</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">Инициализировать хранилище</x:String>
|
||||
<x:String x:Key="Text.Init.Path" xml:space="preserve">Путь:</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Выполняется частичный забор. Нажмите 'Отбой' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Выполняет запрос слияния. Нажмите 'Отбой' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Выполняется перенос. Нажмите 'Отбой' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Выполняется возврат. Нажмите 'Отбой' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Выполняется частичный забор. Нажмите 'Отказ' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Выполняет запрос слияния. Нажмите 'Отказ' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Выполняется перенос. Нажмите 'Отказ' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Выполняется возврат. Нажмите 'Отказ' для восстановления заголовка.</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Интерактивное перемещение</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">целевая ветка:</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">На:</x:String>
|
||||
|
@ -409,9 +416,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">История фиксаций</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Длина темы фиксации</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Автоматическое извлечение внешних хранилищ</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Интервал автоматического извлечения</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">Минут(а/ы)</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Включить автозавершение CRLF</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Каталог клонирования по-умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">Электроная почта пользователя</x:String>
|
||||
|
@ -488,14 +492,15 @@
|
|||
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">Новое имя:</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Уникальное имя для данной ветки</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Ветка:</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ОТБОЙ</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String>
|
||||
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних хранилищ...</x:String>
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистка (Сбор мусора и удаление) </x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду `git gc` для данного хранилища.</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
|
||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка этого хранилища</x:String>
|
||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String>
|
||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Открыть в файловом менеджере</x:String>
|
||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">поиск веток, тегов и подмодулей</x:String>
|
||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Поиск веток, тегов и подмодулей</x:String>
|
||||
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">ОТФИЛЬТРОВАНО ОТ:</x:String>
|
||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">ЛОКАЛЬНЫЕ ВЕТКИ</x:String>
|
||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Навигация по заголовку</x:String>
|
||||
|
@ -508,11 +513,11 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ДОБАВИТЬ ВНЕШНЕЕ ХРАНИЛИЩЕ</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">РАЗРЕШИТЬ</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Поиск фиксации</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Поиск по</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Файл</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Сообщение</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">Автор и фиксатор</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">Автор и исполнитель</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Текущая ветка</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Показать теги как дерево</x:String>
|
||||
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Статистики </x:String>
|
||||
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">ПОДМОДУЛИ</x:String>
|
||||
|
@ -523,7 +528,7 @@
|
|||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
|
||||
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">РАБОЧИЕ ДЕРЕВЬЯ</x:String>
|
||||
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ДОБАВИТЬ РАБОЧЕЕ ДЕРЕВО</x:String>
|
||||
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">ОБРЕЗКА</x:String>
|
||||
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">ОБРЕЗАТЬ</x:String>
|
||||
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">Адрес хранилища Git</x:String>
|
||||
<x:String x:Key="Text.Reset" xml:space="preserve">Сбросить текущую втеку до версии</x:String>
|
||||
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Режим сброса:</x:String>
|
||||
|
@ -568,12 +573,12 @@
|
|||
<x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">ОТЛОЖЕННЫЕ</x:String>
|
||||
<x:String x:Key="Text.Statistics" xml:space="preserve">Статистики</x:String>
|
||||
<x:String x:Key="Text.Statistics.CommitAmount" xml:space="preserve">ФИКСАЦИИ</x:String>
|
||||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">ФИКСАТОРЫ</x:String>
|
||||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">ИСПОЛНИТЕЛИ</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">МЕСЯЦ</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">НЕДЕЛЯ</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">ГОД</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">ФИКСАЦИИ: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">АВТОРЫ: </x:String>
|
||||
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">ОБЗОР</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">ПОДМОДУЛИ</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Добавить подмодули</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Копировать относительный путь</x:String>
|
||||
|
@ -581,7 +586,7 @@
|
|||
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Открыть подмодуль хранилища</x:String>
|
||||
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Относительный путь:</x:String>
|
||||
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Относительный каталог для хранения подмодуля.</x:String>
|
||||
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">удалить подмодуль</x:String>
|
||||
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Удалить подмодуль</x:String>
|
||||
<x:String x:Key="Text.Sure" xml:space="preserve">ОК</x:String>
|
||||
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Копировать имя тега</x:String>
|
||||
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Удалить ${0}$...</x:String>
|
||||
|
@ -617,10 +622,11 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Изменить</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.AutoStage" xml:space="preserve">Автоподготовка</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Теперь вы можете подготовитть этот файл.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">ФИКСАЦИЯ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">ФИКСАЦИЯ и ОТПРАВКА</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">ЗАФИКСИРОВАТЬ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">ЗАФИКСИРОВАТЬ и ОТПРАВИТЬ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Шаблон/Истории</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Запуск события щелчка</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Подготовить все изменения и зафиксировать</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">ОБНАРУЖЕНЫ КОНФЛИКТЫ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">КОНФЛИКТЫ ФАЙЛОВ РАЗРЕШЕНЫ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
||||
|
|
|
@ -139,6 +139,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">启用定时自动拉取远程更新</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分钟</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE追踪</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增匹配Github Issue规则</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增匹配Jira规则</x:String>
|
||||
|
@ -292,6 +294,7 @@
|
|||
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">显示LFS对象锁</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">没有锁定的LFS文件</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">锁定</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">仅显示被我锁定的文件</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS对象锁状态</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解锁</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">强制解锁</x:String>
|
||||
|
@ -327,6 +330,7 @@
|
|||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">仓库页面快捷键</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暂存区更改</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暂存区更改并推送</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">自动暂存全部变更并提交</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">丢弃选中的更改</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">切换左边栏为分支/标签等显示模式(默认)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新加载仓库状态</x:String>
|
||||
|
@ -408,9 +412,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">启用定时自动拉取远程更新</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">自动拉取间隔</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">分钟</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">自动换行转换</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">默认克隆路径</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">邮箱</x:String>
|
||||
|
@ -487,6 +488,7 @@
|
|||
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能与现有分支名相同</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 :</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String>
|
||||
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自动拉取远端变更中...</x:String>
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`git gc`命令。</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
|
||||
|
@ -506,11 +508,11 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">添加远程</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">解决冲突</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">查找提交</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">搜索途径</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">文件</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">提交信息</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">提交指纹</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">作者及提交者</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">仅在当前分支中查找</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">以树型结构展示</x:String>
|
||||
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">提交统计</x:String>
|
||||
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">子模块列表</x:String>
|
||||
|
@ -569,9 +571,9 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">提交者</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">本月</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">本周</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">最近一年</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">提交次数: </x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">贡献者人数: </x:String>
|
||||
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">总览</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">子模块</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">添加子模块</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">复制路径</x:String>
|
||||
|
@ -618,7 +620,8 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交并推送</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">历史输入/模板</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">触发点击事件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">自动暂存所有变更并提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">检测到冲突</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">文件冲突已解决</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">显示未跟踪文件</x:String>
|
||||
|
|
|
@ -139,6 +139,8 @@
|
|||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String>
|
||||
<x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">啟用定時自動提取 (fetch) 遠端更新</x:String>
|
||||
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">分鐘</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">Issue 追蹤</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">新增符合 GitHub Issue 規則</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">新增符合 Jira 規則</x:String>
|
||||
|
@ -292,6 +294,7 @@
|
|||
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">顯示 LFS 物件鎖</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">沒有鎖定的 LFS 物件</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">鎖定</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">僅顯示被我鎖定的檔案</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS 物件鎖</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解鎖</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">強制解鎖</x:String>
|
||||
|
@ -327,6 +330,7 @@
|
|||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">存放庫頁面快速鍵</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暫存區變更</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暫存區變更並推送</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">自動暫存全部變更並提交</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.DiscardSelected" xml:space="preserve">捨棄選取的變更</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">切換左邊欄為分支/標籤等顯示模式 (預設)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">強制重新載入存放庫</x:String>
|
||||
|
@ -412,9 +416,6 @@
|
|||
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String>
|
||||
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">提交標題字數偵測</x:String>
|
||||
<x:String x:Key="Text.Preference.Git" xml:space="preserve">Git 設定</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">啟用定時自動提取 (fetch) 遠端更新</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">自動提取間隔</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">分鐘</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">自動換行轉換</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">預設複製 (clone) 路徑</x:String>
|
||||
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">電子郵件</x:String>
|
||||
|
@ -492,6 +493,7 @@
|
|||
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名稱不能與現有分支名稱相同</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支:</x:String>
|
||||
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">中止</x:String>
|
||||
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自動提取遠端變更中...</x:String>
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本存放庫 (GC)</x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行 `git gc` 命令。</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
|
||||
|
@ -511,11 +513,11 @@
|
|||
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">新增遠端</x:String>
|
||||
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">解決衝突</x:String>
|
||||
<x:String x:Key="Text.Repository.Search" xml:space="preserve">搜尋提交</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">搜尋方式</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">檔案</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">提交訊息</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">提交編號</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">作者及提交者</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">僅搜尋當前分支</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">以樹型結構展示</x:String>
|
||||
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">提交統計</x:String>
|
||||
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">子模組列表</x:String>
|
||||
|
@ -574,9 +576,9 @@
|
|||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">提交者</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">本月</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">本週</x:String>
|
||||
<x:String x:Key="Text.Statistics.MostRecentYear" xml:space="preserve">最近一年</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">提交次數:</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalAuthors" xml:space="preserve">貢獻者人數:</x:String>
|
||||
<x:String x:Key="Text.Statistics.Overview" xml:space="preserve">總覽</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">子模組</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">新增子模組</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">複製路徑</x:String>
|
||||
|
@ -623,7 +625,8 @@
|
|||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提 交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交並推送</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">歷史輸入/範本</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">觸發點擊事件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">自動暫存全部變更並提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">檢測到衝突</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">檔案衝突已解決</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">顯示未追蹤檔案</x:String>
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
<Setter Property="MaxWidth" Value="1024"/>
|
||||
<Setter Property="MaxHeight" Value="768"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Arrow"/>
|
||||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
|
@ -962,12 +963,13 @@
|
|||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="RadioButton.icon_button">
|
||||
<Style Selector="RadioButton.switch_button">
|
||||
<Setter Property="Height" Value="24"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border Background="Transparent">
|
||||
<Border CornerRadius="12" Background="{TemplateBinding Background}">
|
||||
<ContentPresenter x:Name="PART_ContentPresenter"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
|
@ -980,9 +982,17 @@
|
|||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:checked">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:checked Path">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Opacity" Value="0.65"/>
|
||||
<Setter Property="Fill" Value="White"/>
|
||||
</Style>
|
||||
<Style Selector="^ TextBlock">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
|
||||
</Style>
|
||||
<Style Selector="^:checked TextBlock">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
<PackageReference Include="Avalonia.Diagnostics" Version="11.1.3" Condition="'$(Configuration)' == 'Debug'" />
|
||||
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
|
||||
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc3.3" />
|
||||
<PackageReference Include="TextMateSharp" Version="1.0.63" />
|
||||
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.63" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -104,6 +104,7 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
CallUIThread(() =>
|
||||
{
|
||||
_repo.MarkFetched();
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
});
|
||||
|
|
|
@ -15,10 +15,15 @@ namespace SourceGit.ViewModels
|
|||
public string Name { get; private set; } = string.Empty;
|
||||
public object Backend { get; private set; } = null;
|
||||
public int Depth { get; set; } = 0;
|
||||
public bool IsFiltered { get; set; } = false;
|
||||
public bool IsSelected { get; set; } = false;
|
||||
public List<BranchTreeNode> Children { get; private set; } = new List<BranchTreeNode>();
|
||||
|
||||
public bool IsFiltered
|
||||
{
|
||||
get => _isFiltered;
|
||||
set => SetProperty(ref _isFiltered, value);
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
|
@ -46,6 +51,7 @@ namespace SourceGit.ViewModels
|
|||
get => Backend is Models.Branch b ? b.FriendlyName : null;
|
||||
}
|
||||
|
||||
private bool _isFiltered = false;
|
||||
private bool _isExpanded = false;
|
||||
private CornerRadius _cornerRadius = new CornerRadius(4);
|
||||
|
||||
|
|
|
@ -62,7 +62,16 @@ namespace SourceGit.ViewModels
|
|||
rs = new Commands.Stash(_repo.FullPath).Pop("stash@{0}");
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
CallUIThread(() =>
|
||||
{
|
||||
var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
|
||||
if (b != null)
|
||||
_repo.AutoAddBranchFilterPostCheckout(b);
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
});
|
||||
|
||||
return rs;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -321,6 +321,9 @@ namespace SourceGit.ViewModels
|
|||
menu.Items.Add(resetToFirstParent);
|
||||
menu.Items.Add(new MenuItem { Header = "-" });
|
||||
|
||||
if (File.Exists(Path.Combine(fullPath)))
|
||||
TryToAddContextMenuItemsForGitLFS(menu, change.Path);
|
||||
|
||||
var copyPath = new MenuItem();
|
||||
copyPath.Header = App.Text("CopyPath");
|
||||
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
|
@ -346,6 +349,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
var fullPath = Path.Combine(_repo.FullPath, file.Path);
|
||||
var explore = new MenuItem();
|
||||
explore.Header = App.Text("RevealFile");
|
||||
|
@ -385,6 +389,10 @@ namespace SourceGit.ViewModels
|
|||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(explore);
|
||||
menu.Items.Add(saveAs);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
var history = new MenuItem();
|
||||
history.Header = App.Text("FileHistory");
|
||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
|
@ -406,6 +414,10 @@ namespace SourceGit.ViewModels
|
|||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(history);
|
||||
menu.Items.Add(blame);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
var resetToThisRevision = new MenuItem();
|
||||
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
|
||||
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
|
||||
|
@ -428,6 +440,13 @@ namespace SourceGit.ViewModels
|
|||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(resetToThisRevision);
|
||||
menu.Items.Add(resetToFirstParent);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
if (File.Exists(Path.Combine(fullPath)))
|
||||
TryToAddContextMenuItemsForGitLFS(menu, file.Path);
|
||||
|
||||
var copyPath = new MenuItem();
|
||||
copyPath.Header = App.Text("CopyPath");
|
||||
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
|
@ -446,16 +465,6 @@ namespace SourceGit.ViewModels
|
|||
e.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(explore);
|
||||
menu.Items.Add(saveAs);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(history);
|
||||
menu.Items.Add(blame);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(resetToThisRevision);
|
||||
menu.Items.Add(resetToFirstParent);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(copyPath);
|
||||
menu.Items.Add(copyFileName);
|
||||
return menu;
|
||||
|
@ -532,6 +541,90 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private void TryToAddContextMenuItemsForGitLFS(ContextMenu menu, string path)
|
||||
{
|
||||
var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled();
|
||||
if (!lfsEnabled)
|
||||
return;
|
||||
|
||||
var lfs = new MenuItem();
|
||||
lfs.Header = App.Text("GitLFS");
|
||||
lfs.Icon = App.CreateMenuIcon("Icons.LFS");
|
||||
|
||||
var lfsLock = new MenuItem();
|
||||
lfsLock.Header = App.Text("GitLFS.Locks.Lock");
|
||||
lfsLock.Icon = App.CreateMenuIcon("Icons.Lock");
|
||||
lfsLock.IsEnabled = _repo.Remotes.Count > 0;
|
||||
if (_repo.Remotes.Count == 1)
|
||||
{
|
||||
lfsLock.Click += async (_, e) =>
|
||||
{
|
||||
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(_repo.Remotes[0].Name, path));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var remote in _repo.Remotes)
|
||||
{
|
||||
var remoteName = remote.Name;
|
||||
var lockRemote = new MenuItem();
|
||||
lockRemote.Header = remoteName;
|
||||
lockRemote.Click += async (_, e) =>
|
||||
{
|
||||
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(remoteName, path));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
lfsLock.Items.Add(lockRemote);
|
||||
}
|
||||
}
|
||||
lfs.Items.Add(lfsLock);
|
||||
|
||||
var lfsUnlock = new MenuItem();
|
||||
lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock");
|
||||
lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock");
|
||||
lfsUnlock.IsEnabled = _repo.Remotes.Count > 0;
|
||||
if (_repo.Remotes.Count == 1)
|
||||
{
|
||||
lfsUnlock.Click += async (_, e) =>
|
||||
{
|
||||
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(_repo.Remotes[0].Name, path, false));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var remote in _repo.Remotes)
|
||||
{
|
||||
var remoteName = remote.Name;
|
||||
var unlockRemote = new MenuItem();
|
||||
unlockRemote.Header = remoteName;
|
||||
unlockRemote.Click += async (_, e) =>
|
||||
{
|
||||
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(remoteName, path, false));
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
lfsUnlock.Items.Add(unlockRemote);
|
||||
}
|
||||
}
|
||||
lfs.Items.Add(lfsUnlock);
|
||||
|
||||
menu.Items.Add(lfs);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
|
||||
private static partial Regex REG_LFS_FORMAT();
|
||||
|
||||
|
|
|
@ -126,6 +126,15 @@ namespace SourceGit.ViewModels
|
|||
|
||||
CallUIThread(() =>
|
||||
{
|
||||
if (CheckoutAfterCreated)
|
||||
{
|
||||
_repo.AutoAddBranchFilterPostCheckout(new Models.Branch()
|
||||
{
|
||||
FullName = $"refs/heads/{_name}",
|
||||
Upstream = BasedOn is Models.Branch { IsLocal: false } remoteBranch ? remoteBranch.FullName : string.Empty,
|
||||
});
|
||||
}
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
});
|
||||
|
|
|
@ -62,7 +62,12 @@ namespace SourceGit.ViewModels
|
|||
new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, Prune, NoTags, SetProgressDescription).Exec();
|
||||
}
|
||||
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
CallUIThread(() =>
|
||||
{
|
||||
_repo.MarkFetched();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -41,12 +41,12 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public int ViewMode
|
||||
public bool IsViewContent
|
||||
{
|
||||
get => _viewMode;
|
||||
get => _isViewContent;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _viewMode, value))
|
||||
if (SetProperty(ref _isViewContent, value))
|
||||
RefreshViewContent();
|
||||
}
|
||||
}
|
||||
|
@ -93,10 +93,10 @@ namespace SourceGit.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
if (_viewMode == 0)
|
||||
SetViewContentAsDiff();
|
||||
else
|
||||
if (_isViewContent)
|
||||
SetViewContentAsRevisionFile();
|
||||
else
|
||||
SetViewContentAsDiff();
|
||||
}
|
||||
|
||||
private void SetViewContentAsRevisionFile()
|
||||
|
@ -197,7 +197,7 @@ namespace SourceGit.ViewModels
|
|||
private bool _isLoading = true;
|
||||
private List<Models.Commit> _commits = null;
|
||||
private Models.Commit _selectedCommit = null;
|
||||
private int _viewMode = 0;
|
||||
private bool _isViewContent = false;
|
||||
private object _viewContent = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Threading;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
@ -9,40 +9,49 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
public class LFSLocks : ObservableObject
|
||||
{
|
||||
public bool HasValidUserName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = false;
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => _isLoading;
|
||||
private set => SetProperty(ref _isLoading, value);
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
public bool ShowOnlyMyLocks
|
||||
{
|
||||
get => _isEmpty;
|
||||
private set => SetProperty(ref _isEmpty, value);
|
||||
get => _showOnlyMyLocks;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _showOnlyMyLocks, value))
|
||||
UpdateVisibleLocks();
|
||||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<Models.LFSLock> Locks
|
||||
public List<Models.LFSLock> VisibleLocks
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
get => _visibleLocks;
|
||||
private set => SetProperty(ref _visibleLocks, value);
|
||||
}
|
||||
|
||||
public LFSLocks(string repo, string remote)
|
||||
{
|
||||
_repo = repo;
|
||||
_remote = remote;
|
||||
Locks = new AvaloniaList<Models.LFSLock>();
|
||||
_userName = new Commands.Config(repo).Get("user.name");
|
||||
|
||||
HasValidUserName = !string.IsNullOrEmpty(_userName);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var collect = new Commands.LFS(_repo).Locks(_remote);
|
||||
_cachedLocks = new Commands.LFS(_repo).Locks(_remote);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (collect.Count > 0)
|
||||
Locks.AddRange(collect);
|
||||
|
||||
UpdateVisibleLocks();
|
||||
IsLoading = false;
|
||||
IsEmpty = collect.Count == 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -59,17 +68,41 @@ namespace SourceGit.ViewModels
|
|||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (succ)
|
||||
Locks.Remove(lfsLock);
|
||||
{
|
||||
_cachedLocks.Remove(lfsLock);
|
||||
UpdateVisibleLocks();
|
||||
}
|
||||
|
||||
IsLoading = false;
|
||||
IsEmpty = Locks.Count == 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateVisibleLocks()
|
||||
{
|
||||
if (!_showOnlyMyLocks)
|
||||
{
|
||||
VisibleLocks = _cachedLocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
var visible = new List<Models.LFSLock>();
|
||||
foreach (var lfsLock in _cachedLocks)
|
||||
{
|
||||
if (lfsLock.User == _userName)
|
||||
visible.Add(lfsLock);
|
||||
}
|
||||
|
||||
VisibleLocks = visible;
|
||||
}
|
||||
}
|
||||
|
||||
private string _repo;
|
||||
private string _remote;
|
||||
private bool _isLoading = true;
|
||||
private bool _isEmpty = false;
|
||||
private List<Models.LFSLock> _cachedLocks = [];
|
||||
private List<Models.LFSLock> _visibleLocks = [];
|
||||
private bool _showOnlyMyLocks = false;
|
||||
private string _userName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
PopupHost.Active = value;
|
||||
|
||||
if (!_ignoreIndexChange && value is { Data: Repository })
|
||||
ActiveWorkspace.ActiveIdx = Pages.IndexOf(value);
|
||||
if (!_ignoreIndexChange && value is { Data: Repository repo })
|
||||
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(repo.FullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,10 +131,22 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public void MoveTab(LauncherPage from, LauncherPage to)
|
||||
{
|
||||
_ignoreIndexChange = true;
|
||||
|
||||
var fromIdx = Pages.IndexOf(from);
|
||||
var toIdx = Pages.IndexOf(to);
|
||||
Pages.Move(fromIdx, toIdx);
|
||||
ActivePage = from;
|
||||
|
||||
ActiveWorkspace.Repositories.Clear();
|
||||
foreach (var p in Pages)
|
||||
{
|
||||
if (p.Data is Repository r)
|
||||
ActiveWorkspace.Repositories.Add(r.FullPath);
|
||||
}
|
||||
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(from.Node.Id);
|
||||
|
||||
_ignoreIndexChange = false;
|
||||
}
|
||||
|
||||
public void GotoNextTab()
|
||||
|
@ -164,8 +176,9 @@ namespace SourceGit.ViewModels
|
|||
var last = Pages[0];
|
||||
if (last.Data is Repository repo)
|
||||
{
|
||||
ActiveWorkspace.Repositories.Remove(repo.FullPath);
|
||||
Models.AutoFetchManager.Instance.RemoveRepository(repo.FullPath);
|
||||
ActiveWorkspace.Repositories.Clear();
|
||||
ActiveWorkspace.ActiveIdx = 0;
|
||||
|
||||
repo.Close();
|
||||
|
||||
Welcome.Instance.ClearSearchFilter();
|
||||
|
@ -180,6 +193,7 @@ namespace SourceGit.ViewModels
|
|||
App.Quit(0);
|
||||
}
|
||||
|
||||
_ignoreIndexChange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -213,6 +227,8 @@ namespace SourceGit.ViewModels
|
|||
if (Pages.Count == 1)
|
||||
return;
|
||||
|
||||
_ignoreIndexChange = true;
|
||||
|
||||
var id = ActivePage.Node.Id;
|
||||
foreach (var one in Pages)
|
||||
{
|
||||
|
@ -221,12 +237,17 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
|
||||
Pages = new AvaloniaList<LauncherPage> { ActivePage };
|
||||
ActiveWorkspace.ActiveIdx = 0;
|
||||
OnPropertyChanged(nameof(Pages));
|
||||
|
||||
_ignoreIndexChange = false;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public void CloseRightTabs()
|
||||
{
|
||||
_ignoreIndexChange = true;
|
||||
|
||||
var endIdx = Pages.IndexOf(ActivePage);
|
||||
for (var i = Pages.Count - 1; i > endIdx; i--)
|
||||
{
|
||||
|
@ -234,6 +255,7 @@ namespace SourceGit.ViewModels
|
|||
Pages.Remove(Pages[i]);
|
||||
}
|
||||
|
||||
_ignoreIndexChange = false;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
|
@ -270,8 +292,6 @@ namespace SourceGit.ViewModels
|
|||
};
|
||||
|
||||
repo.Open();
|
||||
ActiveWorkspace.AddRepository(repo.FullPath);
|
||||
Models.AutoFetchManager.Instance.AddRepository(repo.FullPath, repo.GitDir);
|
||||
|
||||
if (page == null)
|
||||
{
|
||||
|
@ -294,6 +314,16 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
|
||||
ActivePage = page;
|
||||
|
||||
ActiveWorkspace.Repositories.Clear();
|
||||
foreach (var p in Pages)
|
||||
{
|
||||
if (p.Data is Repository r)
|
||||
ActiveWorkspace.Repositories.Add(r.FullPath);
|
||||
}
|
||||
|
||||
if (!_ignoreIndexChange)
|
||||
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(node.Id);
|
||||
}
|
||||
|
||||
public void DispatchNotification(string pageId, string message, bool isError)
|
||||
|
@ -490,7 +520,6 @@ namespace SourceGit.ViewModels
|
|||
if (removeFromWorkspace)
|
||||
ActiveWorkspace.Repositories.Remove(repo.FullPath);
|
||||
|
||||
Models.AutoFetchManager.Instance.RemoveRepository(repo.FullPath);
|
||||
repo.Close();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,14 @@ namespace SourceGit.ViewModels
|
|||
return _node.Id;
|
||||
}
|
||||
|
||||
public override bool IsInProgress()
|
||||
{
|
||||
if (_data is Repository { IsAutoFetching: true })
|
||||
return true;
|
||||
|
||||
return base.IsInProgress();
|
||||
}
|
||||
|
||||
public void CopyPath()
|
||||
{
|
||||
if (_node.IsRepository)
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public static bool CanCreatePopup()
|
||||
{
|
||||
return Active != null && (Active._popup == null || !Active._popup.InProgress);
|
||||
return Active?.IsInProgress() != true;
|
||||
}
|
||||
|
||||
public static void ShowPopup(Popup popup)
|
||||
|
@ -40,6 +40,11 @@ namespace SourceGit.ViewModels
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
public virtual bool IsInProgress()
|
||||
{
|
||||
return _popup is { InProgress: true };
|
||||
}
|
||||
|
||||
public async void ProcessPopup()
|
||||
{
|
||||
if (_popup != null)
|
||||
|
|
|
@ -216,35 +216,6 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _gitDefaultCloneDir, value);
|
||||
}
|
||||
|
||||
public bool GitAutoFetch
|
||||
{
|
||||
get => Models.AutoFetchManager.Instance.IsEnabled;
|
||||
set
|
||||
{
|
||||
if (Models.AutoFetchManager.Instance.IsEnabled != value)
|
||||
{
|
||||
Models.AutoFetchManager.Instance.IsEnabled = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int? GitAutoFetchInterval
|
||||
{
|
||||
get => Models.AutoFetchManager.Instance.Interval;
|
||||
set
|
||||
{
|
||||
if (value is null || value < 1)
|
||||
return;
|
||||
|
||||
if (Models.AutoFetchManager.Instance.Interval != value)
|
||||
{
|
||||
Models.AutoFetchManager.Instance.Interval = (int)value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int ShellOrTerminal
|
||||
{
|
||||
get => _shellOrTerminal;
|
||||
|
@ -337,6 +308,12 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public uint StatisticsSampleColor
|
||||
{
|
||||
get => _statisticsSampleColor;
|
||||
set => SetProperty(ref _statisticsSampleColor, value);
|
||||
}
|
||||
|
||||
public List<RepositoryNode> RepositoryNodes
|
||||
{
|
||||
get;
|
||||
|
@ -621,5 +598,7 @@ namespace SourceGit.ViewModels
|
|||
private int _shellOrTerminal = -1;
|
||||
private int _externalMergeToolType = 0;
|
||||
private string _externalMergeToolPath = string.Empty;
|
||||
|
||||
private uint _statisticsSampleColor = 0xFF00FF00;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,8 @@ namespace SourceGit.ViewModels
|
|||
if (!rs)
|
||||
return false;
|
||||
|
||||
_repo.MarkFetched();
|
||||
|
||||
// Use merge/rebase instead of pull as fetch is done manually.
|
||||
if (UseRebase)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
|
@ -209,6 +210,12 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _isSearchLoadingVisible, value);
|
||||
}
|
||||
|
||||
public bool OnlySearchCommitsInCurrentBranch
|
||||
{
|
||||
get => _onlySearchCommitsInCurrentBranch;
|
||||
set => SetProperty(ref _onlySearchCommitsInCurrentBranch, value);
|
||||
}
|
||||
|
||||
public int SearchCommitFilterType
|
||||
{
|
||||
get => _searchCommitFilterType;
|
||||
|
@ -323,6 +330,12 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsAutoFetching
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
var settingsFile = Path.Combine(_gitDir, "sourcegit.settings");
|
||||
|
@ -359,6 +372,7 @@ namespace SourceGit.ViewModels
|
|||
_inProgressContext = null;
|
||||
_hasUnsolvedConflicts = false;
|
||||
|
||||
_autoFetchTimer = new Timer(AutoFetchImpl, null, 5000, 5000);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
|
@ -377,6 +391,9 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
_settings = null;
|
||||
|
||||
_autoFetchTimer.Dispose();
|
||||
_autoFetchTimer = null;
|
||||
|
||||
_watcher?.Dispose();
|
||||
_histories.Cleanup();
|
||||
_workingCopy.Cleanup();
|
||||
|
@ -578,13 +595,13 @@ namespace SourceGit.ViewModels
|
|||
visible.Add(commit);
|
||||
break;
|
||||
case 1:
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByUser).Result();
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByUser, _onlySearchCommitsInCurrentBranch).Result();
|
||||
break;
|
||||
case 2:
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByMessage).Result();
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByMessage, _onlySearchCommitsInCurrentBranch).Result();
|
||||
break;
|
||||
case 3:
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByFile).Result();
|
||||
visible = new Commands.QueryCommits(_fullpath, _searchCommitFilter, Models.CommitSearchMethod.ByFile, _onlySearchCommitsInCurrentBranch).Result();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -628,6 +645,11 @@ namespace SourceGit.ViewModels
|
|||
_watcher.MarkWorkingCopyDirtyManually();
|
||||
}
|
||||
|
||||
public void MarkFetched()
|
||||
{
|
||||
_lastFetchTime = DateTime.Now;
|
||||
}
|
||||
|
||||
public void NavigateToCommit(string sha)
|
||||
{
|
||||
if (_histories != null)
|
||||
|
@ -643,20 +665,49 @@ namespace SourceGit.ViewModels
|
|||
NavigateToCommit(_currentBranch.Head);
|
||||
}
|
||||
|
||||
public void UpdateFilter(string filter, bool toggle)
|
||||
public void AutoAddBranchFilterPostCheckout(Models.Branch local)
|
||||
{
|
||||
if (_settings.Filters.Count == 0 || _settings.Filters.Contains(local.FullName))
|
||||
return;
|
||||
|
||||
var hasLeft = false;
|
||||
foreach (var b in _branches)
|
||||
{
|
||||
if (!b.FullName.Equals(local.FullName, StringComparison.Ordinal) &&
|
||||
!b.FullName.Equals(local.Upstream, StringComparison.Ordinal) &&
|
||||
!_settings.Filters.Contains(b.FullName))
|
||||
{
|
||||
hasLeft = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasLeft)
|
||||
_settings.Filters.Clear();
|
||||
else if (string.IsNullOrEmpty(local.Upstream) || _settings.Filters.Contains(local.Upstream))
|
||||
_settings.Filters.Add(local.FullName);
|
||||
else
|
||||
_settings.Filters.AddRange([local.FullName, local.Upstream]);
|
||||
}
|
||||
|
||||
public void UpdateFilters(List<string> filters, bool toggle)
|
||||
{
|
||||
var changed = false;
|
||||
if (toggle)
|
||||
{
|
||||
if (!_settings.Filters.Contains(filter))
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
_settings.Filters.Add(filter);
|
||||
changed = true;
|
||||
if (!_settings.Filters.Contains(filter))
|
||||
{
|
||||
_settings.Filters.Add(filter);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
changed = _settings.Filters.Remove(filter);
|
||||
foreach (var filter in filters)
|
||||
changed |= _settings.Filters.Remove(filter);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
|
@ -837,32 +888,14 @@ namespace SourceGit.ViewModels
|
|||
var hasUnsolvedConflict = _workingCopy.SetData(changes);
|
||||
var inProgress = null as InProgressContext;
|
||||
|
||||
var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge");
|
||||
var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply");
|
||||
if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD")))
|
||||
{
|
||||
inProgress = new CherryPickInProgress(_fullpath);
|
||||
}
|
||||
else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(rebaseMergeFolder))
|
||||
{
|
||||
else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(Path.Combine(_gitDir, "rebase-merge")))
|
||||
inProgress = new RebaseInProgress(this);
|
||||
}
|
||||
else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD")))
|
||||
{
|
||||
inProgress = new RevertInProgress(_fullpath);
|
||||
}
|
||||
else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD")))
|
||||
{
|
||||
inProgress = new MergeInProgress(_fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Directory.Exists(rebaseMergeFolder))
|
||||
Directory.Delete(rebaseMergeFolder, true);
|
||||
|
||||
if (Directory.Exists(rebaseApplyFolder))
|
||||
Directory.Delete(rebaseApplyFolder, true);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
|
@ -2005,6 +2038,28 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private void AutoFetchImpl(object sender)
|
||||
{
|
||||
if (!_settings.EnableAutoFetch || IsAutoFetching)
|
||||
return;
|
||||
|
||||
var lockFile = Path.Combine(_gitDir, "index.lock");
|
||||
if (File.Exists(lockFile))
|
||||
return;
|
||||
|
||||
var now = DateTime.Now;
|
||||
var desire = _lastFetchTime.AddMinutes(_settings.AutoFetchInterval);
|
||||
if (desire > now)
|
||||
return;
|
||||
|
||||
IsAutoFetching = true;
|
||||
Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching)));
|
||||
new Commands.Fetch(_fullpath, "--all", true, false, null) { RaiseError = false }.Exec();
|
||||
_lastFetchTime = DateTime.Now;
|
||||
IsAutoFetching = false;
|
||||
Dispatcher.UIThread.Invoke(() => OnPropertyChanged(nameof(IsAutoFetching)));
|
||||
}
|
||||
|
||||
private string _fullpath = string.Empty;
|
||||
private string _gitDir = string.Empty;
|
||||
private Models.RepositorySettings _settings = null;
|
||||
|
@ -2023,6 +2078,7 @@ namespace SourceGit.ViewModels
|
|||
private bool _isSearchLoadingVisible = false;
|
||||
private bool _isSearchCommitSuggestionOpen = false;
|
||||
private int _searchCommitFilterType = 2;
|
||||
private bool _onlySearchCommitsInCurrentBranch = false;
|
||||
private bool _enableFirstParentInHistories = false;
|
||||
private string _searchCommitFilter = string.Empty;
|
||||
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
|
||||
|
@ -2050,5 +2106,8 @@ namespace SourceGit.ViewModels
|
|||
private InProgressContext _inProgressContext = null;
|
||||
private bool _hasUnsolvedConflicts = false;
|
||||
private Models.Commit _searchResultSelectedCommit = null;
|
||||
|
||||
private Timer _autoFetchTimer = null;
|
||||
private DateTime _lastFetchTime = DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,26 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _httpProxy, value);
|
||||
}
|
||||
|
||||
public bool EnableAutoFetch
|
||||
{
|
||||
get => _repo.Settings.EnableAutoFetch;
|
||||
set => _repo.Settings.EnableAutoFetch = value;
|
||||
}
|
||||
|
||||
public int? AutoFetchInterval
|
||||
{
|
||||
get => _repo.Settings.AutoFetchInterval;
|
||||
set
|
||||
{
|
||||
if (value is null || value < 1)
|
||||
return;
|
||||
|
||||
var interval = (int)value;
|
||||
if (_repo.Settings.AutoFetchInterval != interval)
|
||||
_repo.Settings.AutoFetchInterval = interval;
|
||||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<Models.CommitTemplate> CommitTemplates
|
||||
{
|
||||
get => _repo.Settings.CommitTemplates;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
|
@ -28,6 +31,25 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _selectedReport, value);
|
||||
}
|
||||
|
||||
public uint SampleColor
|
||||
{
|
||||
get => Preference.Instance.StatisticsSampleColor;
|
||||
set
|
||||
{
|
||||
if (value != Preference.Instance.StatisticsSampleColor)
|
||||
{
|
||||
Preference.Instance.StatisticsSampleColor = value;
|
||||
OnPropertyChanged(nameof(SampleBrush));
|
||||
_selectedReport?.ChangeColor(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IBrush SampleBrush
|
||||
{
|
||||
get => new SolidColorBrush(SampleColor);
|
||||
}
|
||||
|
||||
public Statistics(string repo)
|
||||
{
|
||||
Task.Run(() =>
|
||||
|
@ -47,18 +69,15 @@ namespace SourceGit.ViewModels
|
|||
if (_data == null)
|
||||
return;
|
||||
|
||||
switch (_selectedIndex)
|
||||
var report = _selectedIndex switch
|
||||
{
|
||||
case 0:
|
||||
SelectedReport = _data.Year;
|
||||
break;
|
||||
case 1:
|
||||
SelectedReport = _data.Month;
|
||||
break;
|
||||
default:
|
||||
SelectedReport = _data.Week;
|
||||
break;
|
||||
}
|
||||
0 => _data.All,
|
||||
1 => _data.Month,
|
||||
_ => _data.Week,
|
||||
};
|
||||
|
||||
report.ChangeColor(SampleColor);
|
||||
SelectedReport = report;
|
||||
}
|
||||
|
||||
private bool _isLoading = true;
|
||||
|
|
|
@ -240,11 +240,6 @@ namespace SourceGit.ViewModels
|
|||
_cached = changes;
|
||||
_count = _cached.Count;
|
||||
|
||||
var unstaged = new List<Models.Change>();
|
||||
var staged = new List<Models.Change>();
|
||||
var selectedUnstaged = new List<Models.Change>();
|
||||
var selectedStaged = new List<Models.Change>();
|
||||
|
||||
var lastSelectedUnstaged = new HashSet<string>();
|
||||
var lastSelectedStaged = new HashSet<string>();
|
||||
if (_selectedUnstaged != null && _selectedUnstaged.Count > 0)
|
||||
|
@ -258,6 +253,8 @@ namespace SourceGit.ViewModels
|
|||
lastSelectedStaged.Add(c.Path);
|
||||
}
|
||||
|
||||
var unstaged = new List<Models.Change>();
|
||||
var selectedUnstaged = new List<Models.Change>();
|
||||
var hasConflict = false;
|
||||
foreach (var c in changes)
|
||||
{
|
||||
|
@ -271,7 +268,8 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
staged = GetStagedChanges();
|
||||
var staged = GetStagedChanges();
|
||||
var selectedStaged = new List<Models.Change>();
|
||||
foreach (var c in staged)
|
||||
{
|
||||
if (lastSelectedStaged.Contains(c.Path))
|
||||
|
@ -418,12 +416,17 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public void Commit()
|
||||
{
|
||||
DoCommit(false);
|
||||
DoCommit(AutoStageBeforeCommit, false);
|
||||
}
|
||||
|
||||
public void CommitWithAutoStage()
|
||||
{
|
||||
DoCommit(true, false);
|
||||
}
|
||||
|
||||
public void CommitWithPush()
|
||||
{
|
||||
DoCommit(true);
|
||||
DoCommit(AutoStageBeforeCommit, true);
|
||||
}
|
||||
|
||||
public ContextMenu CreateContextMenuForUnstagedChanges()
|
||||
|
@ -1276,7 +1279,7 @@ namespace SourceGit.ViewModels
|
|||
_repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
private void DoCommit(bool autoPush)
|
||||
private void DoCommit(bool autoStage, bool autoPush)
|
||||
{
|
||||
if (!PopupHost.CanCreatePopup())
|
||||
{
|
||||
|
@ -1290,7 +1293,6 @@ namespace SourceGit.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
var autoStage = AutoStageBeforeCommit;
|
||||
if (!_useAmend)
|
||||
{
|
||||
if (autoStage)
|
||||
|
|
|
@ -51,12 +51,6 @@ namespace SourceGit.ViewModels
|
|||
get => new SolidColorBrush(_color);
|
||||
}
|
||||
|
||||
public void AddRepository(string repo)
|
||||
{
|
||||
if (!Repositories.Contains(repo))
|
||||
Repositories.Add(repo);
|
||||
}
|
||||
|
||||
private string _name = string.Empty;
|
||||
private uint _color = 4278221015;
|
||||
private bool _isActive = false;
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace SourceGit.Views
|
|||
return;
|
||||
|
||||
var view = TextView;
|
||||
if (view != null && view.VisualLinesValid)
|
||||
if (view is { VisualLinesValid: true })
|
||||
{
|
||||
var typeface = view.CreateTypeface();
|
||||
var underlinePen = new Pen(Brushes.DarkOrange);
|
||||
|
@ -142,12 +142,12 @@ namespace SourceGit.Views
|
|||
return new Size(maxWidth, 0);
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
base.OnPointerMoved(e);
|
||||
|
||||
var view = TextView;
|
||||
if (!e.Handled && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && view != null && view.VisualLinesValid)
|
||||
if (!e.Handled && view is { VisualLinesValid: true })
|
||||
{
|
||||
var pos = e.GetPosition(this);
|
||||
var typeface = view.CreateTypeface();
|
||||
|
@ -158,7 +158,48 @@ namespace SourceGit.Views
|
|||
continue;
|
||||
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber >= _editor.BlameData.LineInfos.Count)
|
||||
if (lineNumber > _editor.BlameData.LineInfos.Count)
|
||||
break;
|
||||
|
||||
var info = _editor.BlameData.LineInfos[lineNumber - 1];
|
||||
var y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop) - view.VerticalOffset;
|
||||
var shaLink = new FormattedText(
|
||||
info.CommitSHA,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
_editor.FontSize,
|
||||
Brushes.DarkOrange);
|
||||
|
||||
var rect = new Rect(0, y, shaLink.Width, shaLink.Height);
|
||||
if (rect.Contains(pos))
|
||||
{
|
||||
Cursor = Cursor.Parse("Hand");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cursor = Cursor.Default;
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
|
||||
var view = TextView;
|
||||
if (!e.Handled && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && view is { VisualLinesValid: true })
|
||||
{
|
||||
var pos = e.GetPosition(this);
|
||||
var typeface = view.CreateTypeface();
|
||||
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
|
||||
continue;
|
||||
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber > _editor.BlameData.LineInfos.Count)
|
||||
break;
|
||||
|
||||
var info = _editor.BlameData.LineInfos[lineNumber - 1];
|
||||
|
@ -262,7 +303,7 @@ namespace SourceGit.Views
|
|||
continue;
|
||||
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber >= BlameData.LineInfos.Count)
|
||||
if (lineNumber > BlameData.LineInfos.Count)
|
||||
break;
|
||||
|
||||
var info = BlameData.LineInfos[lineNumber - 1];
|
||||
|
@ -321,7 +362,7 @@ namespace SourceGit.Views
|
|||
return;
|
||||
|
||||
var caret = TextArea.Caret;
|
||||
if (caret == null || caret.Line >= BlameData.LineInfos.Count)
|
||||
if (caret == null || caret.Line > BlameData.LineInfos.Count)
|
||||
return;
|
||||
|
||||
_highlight = BlameData.LineInfos[caret.Line - 1].CommitSHA;
|
||||
|
|
|
@ -54,10 +54,10 @@
|
|||
|
||||
<!-- Name -->
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Name}"
|
||||
Classes="primary"
|
||||
FontWeight="{Binding NameFontWeight}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
Text="{Binding Name}"
|
||||
Classes="primary"
|
||||
FontWeight="{Binding NameFontWeight}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
|
||||
<!-- Tracking status -->
|
||||
<v:BranchTreeNodeTrackStatusPresenter Grid.Column="2"
|
||||
|
@ -72,9 +72,9 @@
|
|||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
IsCheckedChanged="OnToggleFilter"
|
||||
IsVisible="{Binding IsBranch}"
|
||||
IsChecked="{Binding IsFiltered}"
|
||||
Click="OnToggleFilterClicked"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
@ -428,12 +428,23 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void OnToggleFilter(object sender, RoutedEventArgs e)
|
||||
private void OnToggleFilterClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton toggle && DataContext is ViewModels.Repository repo)
|
||||
if (DataContext is ViewModels.Repository repo &&
|
||||
sender is ToggleButton toggle &&
|
||||
toggle.DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch } node)
|
||||
{
|
||||
if (toggle.DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch })
|
||||
repo.UpdateFilter(branch.FullName, toggle.IsChecked == true);
|
||||
bool filtered = toggle.IsChecked == true;
|
||||
List<string> filters = [branch.FullName];
|
||||
if (branch.IsLocal && !string.IsNullOrEmpty(branch.Upstream))
|
||||
{
|
||||
filters.Add(branch.Upstream);
|
||||
|
||||
node.IsFiltered = filtered;
|
||||
UpdateUpstreamFilterState(repo.RemoteBranchTrees, branch.Upstream, filtered);
|
||||
}
|
||||
|
||||
repo.UpdateFilters(filters, filtered);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
@ -466,6 +477,23 @@ namespace SourceGit.Views
|
|||
CollectBranchesInNode(outs, sub);
|
||||
}
|
||||
|
||||
private bool UpdateUpstreamFilterState(List<ViewModels.BranchTreeNode> collection, string upstream, bool isFiltered)
|
||||
{
|
||||
foreach (var node in collection)
|
||||
{
|
||||
if (node.Backend is Models.Branch b && b.FullName == upstream)
|
||||
{
|
||||
node.IsFiltered = isFiltered;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.Backend is Models.Remote r && upstream.StartsWith($"refs/remotes/{r.Name}/", StringComparison.Ordinal))
|
||||
return UpdateUpstreamFilterState(node.Children, upstream, isFiltered);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool _disableSelectionChangingEvent = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!e.Handled && e.Key != Key.Space)
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
|
@ -166,10 +166,10 @@ namespace SourceGit.Views
|
|||
{
|
||||
if (lastUnselected == -1)
|
||||
continue;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
lastUnselected = i;
|
||||
}
|
||||
}
|
||||
|
@ -186,10 +186,10 @@ namespace SourceGit.Views
|
|||
{
|
||||
if (lastUnselected == -1)
|
||||
continue;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
lastUnselected = i;
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ namespace SourceGit.Views
|
|||
_disableSelectionChangingEvent = true;
|
||||
|
||||
var selected = new List<Models.Change>();
|
||||
if (sender is ListBox { SelectedItems: {} selectedItems })
|
||||
if (sender is ListBox { SelectedItems: { } selectedItems })
|
||||
{
|
||||
foreach (var item in selectedItems)
|
||||
{
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
x:DataType="vm:CommitDetail">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailChangesLeftWidth, Mode=TwoWay}" MinWidth="200" MaxWidth="480"/>
|
||||
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailChangesLeftWidth, Mode=TwoWay}" MinWidth="200"/>
|
||||
<ColumnDefinition Width="4"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*" MinWidth="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid Grid.Column="0" RowDefinitions="26,*">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
|
@ -15,7 +14,7 @@ namespace SourceGit.Views
|
|||
menu.Closing += OnContextMenuClosing; // Clear context menu because it is dynamic.
|
||||
|
||||
control.ContextMenu = menu;
|
||||
control.ContextMenu.Open();
|
||||
control.ContextMenu?.Open();
|
||||
}
|
||||
|
||||
private static void OnContextMenuClosing(object sender, CancelEventArgs e)
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
<TextBlock Grid.Column="2"
|
||||
Classes="primary"
|
||||
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Cursor="Hand"
|
||||
Background="Transparent"
|
||||
Foreground="DarkOrange"
|
||||
TextDecorations="Underline"
|
||||
|
@ -115,75 +116,19 @@
|
|||
IsVisible="{Binding IsLoading}"/>
|
||||
|
||||
<Grid Grid.Column="2" RowDefinitions="Auto,*,Auto" IsVisible="{Binding !IsLoading}">
|
||||
<ListBox Grid.Row="0"
|
||||
Margin="0,8"
|
||||
SelectedIndex="{Binding ViewMode, Mode=TwoWay}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
CornerRadius="14"
|
||||
Padding="3,0">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<StackPanel Grid.Row="0" Margin="0,8" Height="28" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<RadioButton Classes="switch_button"
|
||||
GroupName="SearchGroup"
|
||||
IsChecked="{Binding !IsViewContent, Mode=OneWay}">
|
||||
<TextBlock Margin="16,0" Text="{DynamicResource Text.FileHistory.FileChange}" FontWeight="Bold"/>
|
||||
</RadioButton>
|
||||
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem Border.switcher_bg">
|
||||
<Setter Property="Height" Value="22"/>
|
||||
<Setter Property="CornerRadius" Value="11"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="16,0"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:selected Border.switcher_bg">
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.view_mode_switcher">
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:pointerover TextBlock.view_mode_switcher">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:selected TextBlock.view_mode_switcher">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
|
||||
<ListBoxItem>
|
||||
<Border Classes="switcher_bg">
|
||||
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.FileHistory.FileChange}"/>
|
||||
</Border>
|
||||
</ListBoxItem>
|
||||
|
||||
<ListBoxItem>
|
||||
<Border Classes="switcher_bg">
|
||||
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.FileHistory.FileContent}"/>
|
||||
</Border>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
<RadioButton Classes="switch_button"
|
||||
GroupName="SearchGroup"
|
||||
IsChecked="{Binding IsViewContent, Mode=TwoWay}">
|
||||
<TextBlock Margin="16,0" Text="{DynamicResource Text.FileHistory.FileContent}" FontWeight="Bold"/>
|
||||
</RadioButton>
|
||||
</StackPanel>
|
||||
|
||||
<ContentControl Grid.Row="1" Margin="4,4,8,8" Content="{Binding ViewContent}">
|
||||
<ContentControl.DataTemplates>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Increase}}"
|
||||
Margin="0,8"/>
|
||||
|
||||
<Grid RowDefinitions="20,20,20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
|
||||
<Grid RowDefinitions="20,20,20,20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+H, macOS=⌘+⇧+H}"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.GoHome}" />
|
||||
|
||||
|
@ -102,12 +102,15 @@
|
|||
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"/>
|
||||
<TextBlock Grid.Row="7" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Commit}" />
|
||||
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+⇧+Enter}"/>
|
||||
<TextBlock Grid.Row="8" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CommitAndPush}" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CommitWithAutoStage}" />
|
||||
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Classes="primary bold" Text="F5"/>
|
||||
<TextBlock Grid.Row="9" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Classes="primary bold" Text="{OnPlatform Alt+Enter, macOS=⌥+Enter}"/>
|
||||
<TextBlock Grid.Row="9" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CommitAndPush}" />
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Classes="primary bold" Text="F5"/>
|
||||
<TextBlock Grid.Row="10" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.LFSLocks"
|
||||
x:DataType="vm:LFSLocks"
|
||||
|
@ -13,7 +14,7 @@
|
|||
Title="{DynamicResource Text.GitLFS.Locks.Title}"
|
||||
Width="600" Height="400"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
<!-- TitleBar -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
|
||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||
|
@ -43,11 +44,25 @@
|
|||
IsVisible="{OnPlatform True, macOS=False}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Filter and Unlock All -->
|
||||
<CheckBox Grid.Row="1"
|
||||
Margin="8,0,0,0"
|
||||
Content="{DynamicResource Text.GitLFS.Locks.OnlyMine}"
|
||||
IsChecked="{Binding ShowOnlyMyLocks, Mode=TwoWay}"
|
||||
VerticalAlignment="Center">
|
||||
<CheckBox.IsEnabled>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="HasValidUserName"/>
|
||||
<Binding Path="!IsLoading"/>
|
||||
</MultiBinding>
|
||||
</CheckBox.IsEnabled>
|
||||
</CheckBox>
|
||||
|
||||
<!-- Locked Files -->
|
||||
<Grid Grid.Row="1">
|
||||
<ListBox Margin="8"
|
||||
<Grid Grid.Row="2">
|
||||
<ListBox Margin="8,0,8,8"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
ItemsSource="{Binding Locks}"
|
||||
ItemsSource="{Binding VisibleLocks}"
|
||||
SelectionMode="Single"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
|
@ -89,9 +104,14 @@
|
|||
</ListBox>
|
||||
|
||||
<!-- Empty -->
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsEmpty}">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<StackPanel.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="!IsLoading"/>
|
||||
<Binding Path="VisibleLocks" Converter="{x:Static c:ListConverters.IsNullOrEmpty}"/>
|
||||
</MultiBinding>
|
||||
</StackPanel.IsVisible>
|
||||
|
||||
<Path Width="48" Height="48" Data="{StaticResource Icons.Empty}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Margin="0,16,0,0" Text="{DynamicResource Text.GitLFS.Locks.Empty}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</StackPanel>
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
</Button>
|
||||
|
||||
<!-- Workspace Switcher -->
|
||||
<Button Grid.Column="1" Classes="icon_button" VerticalAlignment="Bottom" Click="OnOpenWorkspaceMenu">
|
||||
<Button Grid.Column="1" Classes="icon_button" VerticalAlignment="Bottom" Margin="0,0,0,1" Click="OnOpenWorkspaceMenu">
|
||||
<ToolTip.Tip>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource Text.Workspace}" FontWeight="Bold" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace SourceGit.Views
|
|||
|
||||
var geo = new StreamGeometry();
|
||||
var angle = Math.PI / 2;
|
||||
var y = height + 0.1;
|
||||
var y = height + 0.5;
|
||||
using (var ctx = geo.Open())
|
||||
{
|
||||
double x;
|
||||
|
@ -94,17 +94,17 @@ namespace SourceGit.Views
|
|||
x = drawRightX;
|
||||
y = 6;
|
||||
ctx.ArcTo(new Point(x, y), new Size(6, 6), angle, false, SweepDirection.Clockwise);
|
||||
y = height + 0.1 - 5;
|
||||
y = height + 0.5 - 5;
|
||||
ctx.LineTo(new Point(x, y));
|
||||
x += 5;
|
||||
y = height + 0.1;
|
||||
y = height + 0.5;
|
||||
ctx.ArcTo(new Point(x, y), new Size(5, 5), angle, false, SweepDirection.CounterClockwise);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = LauncherTabsScroller.Bounds.Right;
|
||||
ctx.LineTo(new Point(x, y));
|
||||
y = height + 0.1;
|
||||
y = height + 0.5;
|
||||
ctx.LineTo(new Point(x, y));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<TabItem.Header>
|
||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
|
||||
</TabItem.Header>
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preference.General.Locale}"
|
||||
HorizontalAlignment="Right"
|
||||
|
@ -99,7 +99,7 @@
|
|||
Margin="0,0,16,0"/>
|
||||
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="*,64">
|
||||
<Slider Grid.Column="0"
|
||||
Minimum="20000" Maximum="100000"
|
||||
Minimum="5000" Maximum="100000"
|
||||
TickPlacement="BottomRight" TickFrequency="5000"
|
||||
IsSnapToTickEnabled="True"
|
||||
VerticalAlignment="Center"
|
||||
|
@ -116,32 +116,6 @@
|
|||
Height="32"
|
||||
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Preference.Git.AutoFetch}"
|
||||
IsChecked="{Binding GitAutoFetch, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0"
|
||||
IsVisible="{Binding GitAutoFetch}"
|
||||
Text="{DynamicResource Text.Preference.Git.AutoFetchInterval}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<Grid Grid.Row="6" Grid.Column="1" Height="32" ColumnDefinitions="*,Auto" IsVisible="{Binding GitAutoFetch}">
|
||||
<NumericUpDown Grid.Column="0"
|
||||
Minimum="1" Maximum="60" Increment="1"
|
||||
Height="28"
|
||||
Padding="4"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="3"
|
||||
ParsingNumberStyle="Integer"
|
||||
FormatString="0"
|
||||
Value="{Binding GitAutoFetchInterval, Mode=TwoWay, FallbackValue=10}"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="5,0,0,0"
|
||||
Text="{DynamicResource Text.Preference.Git.AutoFetchIntervalSuffix}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
|
|
|
@ -19,31 +19,22 @@
|
|||
<!-- Left Panel -->
|
||||
<Grid Grid.Column="0" RowDefinitions="Auto,*">
|
||||
<!-- Page Switcher for Left Contents (Dashboard or CommitSearch) -->
|
||||
<Grid Grid.Row="0" Height="24" Margin="0,6" HorizontalAlignment="Center" ColumnDefinitions="48,1,48">
|
||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||
Height="24"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
CornerRadius="12"/>
|
||||
|
||||
<RadioButton Grid.Column="0"
|
||||
Classes="icon_button"
|
||||
<StackPanel Grid.Row="0" Margin="0,6" Height="24" HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<RadioButton Classes="switch_button"
|
||||
Width="48"
|
||||
GroupName="SearchGroup"
|
||||
IsChecked="{Binding !IsSearching, Mode=OneWay}">
|
||||
<Path Width="14" Height="14" Stretch="Fill" HorizontalAlignment="Center" Data="{StaticResource Icons.Home}"/>
|
||||
<Path Width="12" Height="12" Stretch="Fill" HorizontalAlignment="Center" Data="{StaticResource Icons.Home}"/>
|
||||
</RadioButton>
|
||||
|
||||
<Rectangle Grid.Column="1" Width="0.65" HorizontalAlignment="Center" VerticalAlignment="Stretch" Fill="{DynamicResource Brush.Border2}"/>
|
||||
|
||||
<RadioButton Grid.Column="2"
|
||||
<RadioButton Classes="switch_button"
|
||||
Width="48"
|
||||
Classes="icon_button"
|
||||
GroupName="SearchGroup"
|
||||
IsChecked="{Binding IsSearching, Mode=TwoWay}">
|
||||
<Path Width="14" Height="14" Stretch="Fill" HorizontalAlignment="Center" Data="{StaticResource Icons.Search}"/>
|
||||
<Path Width="12" Height="12" Stretch="Fill" HorizontalAlignment="Center" Data="{StaticResource Icons.Search}"/>
|
||||
</RadioButton>
|
||||
</Grid>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!-- Dashboard -->
|
||||
<Grid Grid.Row="1" Margin="0,0,0,8" RowDefinitions="Auto,Auto,*" IsVisible="{Binding !IsSearching}">
|
||||
<!-- Page Switcher for Right Panel -->
|
||||
|
@ -138,6 +129,12 @@
|
|||
Watermark="{DynamicResource Text.Repository.Filter}"
|
||||
Text="{Binding Filter, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center">
|
||||
<TextBox.Styles>
|
||||
<Style Selector="TextBox /template/ TextBlock#PART_Watermark">
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
</TextBox.Styles>
|
||||
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
|
@ -343,15 +340,15 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Commit Search Panel -->
|
||||
<Grid Grid.Row="1" RowDefinitions="24,32,*" Margin="8,0,4,8" IsVisible="{Binding IsSearching}" PropertyChanged="OnSearchCommitPanelPropertyChanged">
|
||||
<Grid Grid.Row="1" RowDefinitions="Auto,26,*" Margin="8,0,4,8" IsVisible="{Binding IsSearching}" PropertyChanged="OnSearchCommitPanelPropertyChanged">
|
||||
<!-- Search Input Box -->
|
||||
<Grid Grid.Row="0">
|
||||
<Grid Grid.Row="0" Height="26" Margin="0,4,0,0">
|
||||
<TextBox x:Name="TxtSearchCommitsBox"
|
||||
Height="24"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
CornerRadius="4"
|
||||
CornerRadius="12"
|
||||
Watermark="{DynamicResource Text.Repository.Search}"
|
||||
Text="{Binding SearchCommitFilter, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center"
|
||||
|
@ -430,18 +427,11 @@
|
|||
</Popup>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{DynamicResource Text.Repository.Search.By}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
Margin="2,0,0,0"/>
|
||||
|
||||
<ComboBox Grid.Column="1"
|
||||
MinHeight="24" Height="24"
|
||||
Padding="8,0"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
HorizontalAlignment="Right"
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<ComboBox MinHeight="24" Height="24"
|
||||
Padding="4,0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
SelectedIndex="{Binding SearchCommitFilterType, Mode=TwoWay}">
|
||||
<ComboBox.Items>
|
||||
<TextBlock Text="{DynamicResource Text.Repository.Search.BySHA}" FontSize="12"/>
|
||||
|
@ -450,9 +440,17 @@
|
|||
<TextBlock Text="{DynamicResource Text.Repository.Search.ByFile}" FontSize="12"/>
|
||||
</ComboBox.Items>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
|
||||
|
||||
<CheckBox Height="24"
|
||||
Margin="4,0,0,0"
|
||||
IsChecked="{Binding OnlySearchCommitsInCurrentBranch, Mode=TwoWay}"
|
||||
IsVisible="{Binding SearchCommitFilterType, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
|
||||
<TextBlock Text="{DynamicResource Text.Repository.Search.InCurrentBranch}" FontSize="12"/>
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
Margin="0,8,0,0"
|
||||
ItemsSource="{Binding SearchedCommits}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SearchResultSelectedCommit, Mode=TwoWay}"
|
||||
|
@ -631,5 +629,19 @@
|
|||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
|
||||
<!-- Right (Auto-Fetch) -->
|
||||
<Border Grid.Column="2" Margin="12" HorizontalAlignment="Center" VerticalAlignment="Center" Effect="drop-shadow(0 0 12 #A0000000)" IsVisible="{Binding IsAutoFetching}">
|
||||
<Border Background="{DynamicResource Brush.Popup}" CornerRadius="6">
|
||||
<StackPanel Orientation="Vertical" Margin="16,8">
|
||||
<TextBlock Text="{DynamicResource Text.Repository.AutoFetching}"/>
|
||||
<ProgressBar Margin="0,8,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsIndeterminate="{Binding IsAutoFetching}"
|
||||
Background="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.Accent}"
|
||||
Minimum="0" Maximum="100"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.Git}"/>
|
||||
</TabItem.Header>
|
||||
|
||||
<Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="16,4,16,8" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
|
@ -106,6 +106,26 @@
|
|||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Preference.GPG.TagEnabled}"
|
||||
IsChecked="{Binding GPGTagSigningEnabled, Mode=TwoWay}"/>
|
||||
|
||||
<StackPanel Grid.Row="6" Grid.Column="1" Orientation="Horizontal">
|
||||
<CheckBox x:Name="AutoFetchCheckBox"
|
||||
Content="{DynamicResource Text.Configure.Git.AutoFetch}"
|
||||
IsChecked="{Binding EnableAutoFetch, Mode=TwoWay}"/>
|
||||
|
||||
<NumericUpDown Minimum="1" Maximum="60" Increment="1"
|
||||
Height="26" Width="110"
|
||||
Margin="8,0,0,0" Padding="4"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="3"
|
||||
ParsingNumberStyle="Integer"
|
||||
FormatString="0"
|
||||
Value="{Binding AutoFetchInterval, Mode=TwoWay, FallbackValue=10}"
|
||||
IsEnabled="{Binding #AutoFetchCheckBox.IsChecked}"/>
|
||||
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Margin="5,0,0,0"
|
||||
Text="{DynamicResource Text.Configure.Git.AutoFetchIntervalSuffix}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
|
@ -186,7 +206,11 @@
|
|||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CommitMessageTemplate.Content}"/>
|
||||
<v:CommitMessageTextBox Height="150" Text="{Binding Content, Mode=TwoWay}"/>
|
||||
<v:CommitMessageTextBox Margin="0,4,0,0" Height="100" Text="{Binding Content, Mode=TwoWay}"/>
|
||||
<TextBlock Margin="0,2,0,0"
|
||||
Text="You can use ${files_num}, ${files} and ${files:N} where N is the max number of file paths to output."
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!e.Handled)
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
x:DataType="vm:CommitDetail">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailFilesLeftWidth, Mode=TwoWay}" MinWidth="200" MaxWidth="480"/>
|
||||
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailFilesLeftWidth, Mode=TwoWay}" MinWidth="200"/>
|
||||
<ColumnDefinition Width="4"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*" MinWidth="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- File Tree -->
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:lvc="using:LiveChartsCore.SkiaSharpView.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Statistics"
|
||||
x:DataType="vm:Statistics"
|
||||
x:Name="ThisControl"
|
||||
Title="{DynamicResource Text.Statistics}"
|
||||
Width="860" Height="500"
|
||||
Width="800" Height="500"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False">
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
|
@ -62,6 +63,7 @@
|
|||
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Width" Value="100"/>
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
|
@ -80,7 +82,6 @@
|
|||
<Setter Property="CornerRadius" Value="11"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="16,0"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:selected Border.switcher_bg">
|
||||
|
@ -90,6 +91,7 @@
|
|||
<Style Selector="TextBlock.view_mode_switcher">
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBoxItem:pointerover TextBlock.view_mode_switcher">
|
||||
|
@ -103,7 +105,7 @@
|
|||
|
||||
<ListBoxItem>
|
||||
<Border Classes="switcher_bg">
|
||||
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.MostRecentYear}"/>
|
||||
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.Statistics.Overview}"/>
|
||||
</Border>
|
||||
</ListBoxItem>
|
||||
|
||||
|
@ -120,15 +122,30 @@
|
|||
</ListBoxItem>
|
||||
</ListBox>
|
||||
|
||||
<!-- Color Picker -->
|
||||
<Border Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" Width="28" Height="28" CornerRadius="14" Margin="0,0,24,0">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<Border Padding="8">
|
||||
<v:ColorPicker Value="{Binding SampleColor, Mode=TwoWay}"/>
|
||||
</Border>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.ColorPicker}" Fill="{Binding SampleBrush}"/>
|
||||
</Button>
|
||||
</Border>
|
||||
|
||||
<!-- Contents -->
|
||||
<ContentControl Grid.Row="2" Content="{Binding SelectedReport, Mode=OneWay}">
|
||||
<ContentControl Grid.Row="2" Content="{Binding SelectedReport, Mode=OneWay}" Margin="8,8,8,16">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:StatisticsReport">
|
||||
<Grid ColumnDefinitions="256,*" Margin="8,8,8,16">
|
||||
<Grid ColumnDefinitions="256,*">
|
||||
<Grid Grid.Column="0" RowDefinitions="*,16">
|
||||
<!-- Table By Committer -->
|
||||
<ListBox Grid.Column="0"
|
||||
ItemsSource="{Binding ByAuthor}"
|
||||
ItemsSource="{Binding Authors}"
|
||||
SelectionMode="Single"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
|
@ -150,7 +167,7 @@
|
|||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="m:StatisticsSample">
|
||||
<DataTemplate DataType="m:StaticsticsAuthor">
|
||||
<Border BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||
<Grid ColumnDefinitions="*,100">
|
||||
<Border Grid.Column="0" Padding="8,0" ClipToBounds="True">
|
||||
|
@ -170,7 +187,7 @@
|
|||
<!-- Total Committers -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Statistics.TotalAuthors}" FontSize="11" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Classes="primary" Text="{Binding ByAuthor.Count}" FontSize="11" Margin="4,0,0,0"/>
|
||||
<TextBlock Classes="primary" Text="{Binding Authors.Count}" FontSize="11" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Total Commits -->
|
||||
|
@ -182,12 +199,12 @@
|
|||
</Grid>
|
||||
|
||||
<!-- Graph -->
|
||||
<v:Chart Grid.Column="1"
|
||||
Margin="16"
|
||||
LabelBrush="{DynamicResource Brush.FG1}"
|
||||
LineBrush="{DynamicResource Brush.Border2}"
|
||||
ShapeBrush="{DynamicResource Brush.Accent}"
|
||||
Samples="{Binding Samples}"/>
|
||||
<lvc:CartesianChart Grid.Column="1"
|
||||
Margin="0"
|
||||
Padding="0"
|
||||
Series="{Binding Series}"
|
||||
XAxes="{Binding XAxes}" YAxes="{Binding YAxes}"
|
||||
ZoomMode="X"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
|
|
|
@ -1,220 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class Chart : Control
|
||||
{
|
||||
public static readonly StyledProperty<IBrush> LabelBrushProperty =
|
||||
AvaloniaProperty.Register<Chart, IBrush>(nameof(LabelBrush), Brushes.Black);
|
||||
|
||||
public IBrush LabelBrush
|
||||
{
|
||||
get => GetValue(LabelBrushProperty);
|
||||
set => SetValue(LabelBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBrushProperty =
|
||||
AvaloniaProperty.Register<Chart, IBrush>(nameof(LineBrush), Brushes.Gray);
|
||||
|
||||
public IBrush LineBrush
|
||||
{
|
||||
get => GetValue(LineBrushProperty);
|
||||
set => SetValue(LineBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> ShapeBrushProperty =
|
||||
AvaloniaProperty.Register<Chart, IBrush>(nameof(ShapeBrush), Brushes.Gray);
|
||||
|
||||
public IBrush ShapeBrush
|
||||
{
|
||||
get => GetValue(ShapeBrushProperty);
|
||||
set => SetValue(ShapeBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<List<Models.StatisticsSample>> SamplesProperty =
|
||||
AvaloniaProperty.Register<Chart, List<Models.StatisticsSample>>(nameof(Samples));
|
||||
|
||||
public List<Models.StatisticsSample> Samples
|
||||
{
|
||||
get => GetValue(SamplesProperty);
|
||||
set => SetValue(SamplesProperty, value);
|
||||
}
|
||||
|
||||
static Chart()
|
||||
{
|
||||
SamplesProperty.Changed.AddClassHandler<Chart>((c, _) =>
|
||||
{
|
||||
c._hitBoxes.Clear();
|
||||
c._lastHitIdx = -1;
|
||||
c.InvalidateMeasure();
|
||||
});
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (Samples == null || Bounds.Width == 0)
|
||||
return;
|
||||
|
||||
var samples = Samples;
|
||||
int maxV = 0;
|
||||
foreach (var s in samples)
|
||||
{
|
||||
if (maxV < s.Count)
|
||||
maxV = s.Count;
|
||||
}
|
||||
|
||||
if (maxV < 5)
|
||||
maxV = 5;
|
||||
else if (maxV < 10)
|
||||
maxV = 10;
|
||||
else if (maxV < 50)
|
||||
maxV = 50;
|
||||
else if (maxV < 100)
|
||||
maxV = 100;
|
||||
else if (maxV < 200)
|
||||
maxV = 200;
|
||||
else if (maxV < 500)
|
||||
maxV = 500;
|
||||
else
|
||||
maxV = (int)Math.Ceiling(maxV / 500.0) * 500;
|
||||
|
||||
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
|
||||
var pen = new Pen(LineBrush);
|
||||
var width = Bounds.Width;
|
||||
var height = Bounds.Height;
|
||||
|
||||
// Draw coordinate
|
||||
var maxLabel = new FormattedText($"{maxV}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12.0, LabelBrush);
|
||||
var horizonStart = maxLabel.Width + 8;
|
||||
var labelHeight = maxLabel.Height;
|
||||
var bg = this.FindResource("Brush.Contents") as IBrush;
|
||||
context.DrawText(maxLabel, new Point(0, -maxLabel.Height * 0.5));
|
||||
context.DrawRectangle(bg, pen, new Rect(horizonStart, 0, width - horizonStart, height - labelHeight));
|
||||
|
||||
if (samples.Count == 0)
|
||||
return;
|
||||
|
||||
// Draw horizontal lines
|
||||
var stepX = (width - horizonStart) / samples.Count;
|
||||
var stepV = (height - labelHeight) / 5;
|
||||
var labelStepV = maxV / 5;
|
||||
var gridPen = new Pen(LineBrush, 1, new DashStyle() { Dashes = [2, 2, 0, 2], Offset = 1 });
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
var vLabel = new FormattedText(
|
||||
$"{maxV - i * labelStepV}",
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
12.0,
|
||||
LabelBrush);
|
||||
|
||||
var dashHeight = i * stepV;
|
||||
var vy = Math.Max(0, dashHeight - vLabel.Height * 0.5);
|
||||
using (context.PushOpacity(.1))
|
||||
{
|
||||
context.DrawLine(gridPen, new Point(horizonStart + 1, dashHeight), new Point(width, dashHeight));
|
||||
}
|
||||
context.DrawText(vLabel, new Point(horizonStart - vLabel.Width - 8, vy));
|
||||
}
|
||||
|
||||
// Calculate hit boxes
|
||||
if (_hitBoxes.Count == 0)
|
||||
{
|
||||
var shapeWidth = Math.Min(32, stepX - 4);
|
||||
for (int i = 0; i < samples.Count; i++)
|
||||
{
|
||||
var h = samples[i].Count * (height - labelHeight) / maxV;
|
||||
var x = horizonStart + 1 + stepX * i + (stepX - shapeWidth) * 0.5;
|
||||
var y = height - labelHeight - h;
|
||||
_hitBoxes.Add(new Rect(x, y, shapeWidth, h - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw shapes
|
||||
for (int i = 0; i < samples.Count; i++)
|
||||
{
|
||||
var hLabel = new FormattedText(
|
||||
samples[i].Name,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
10.0,
|
||||
LabelBrush);
|
||||
var rect = _hitBoxes[i];
|
||||
var xLabel = rect.X - (hLabel.Width - rect.Width) * 0.5;
|
||||
var yLabel = height - labelHeight + 4;
|
||||
|
||||
context.DrawRectangle(ShapeBrush, null, rect);
|
||||
|
||||
var test = (stepX - 4) / hLabel.Width;
|
||||
if (test < 1.0)
|
||||
{
|
||||
var matrix = Matrix.CreateRotation(Math.Acos(test)) * Matrix.CreateTranslation(xLabel + hLabel.Width * 0.5, yLabel);
|
||||
using (context.PushTransform(matrix))
|
||||
context.DrawText(hLabel, new Point(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DrawText(hLabel, new Point(xLabel, yLabel));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw labels on hover
|
||||
if (_lastHitIdx >= 0 && _lastHitIdx < samples.Count)
|
||||
{
|
||||
var rect = _hitBoxes[_lastHitIdx];
|
||||
var tooltip = new FormattedText(
|
||||
$"{samples[_lastHitIdx].Count}",
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
12.0,
|
||||
LabelBrush);
|
||||
|
||||
var tx = rect.X - (tooltip.Width - rect.Width) * 0.5;
|
||||
var ty = rect.Y - tooltip.Height - 4;
|
||||
context.DrawText(tooltip, new Point(tx, ty));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerMoved(e);
|
||||
|
||||
var p = e.GetPosition(this);
|
||||
for (int i = 0; i < _hitBoxes.Count; i++)
|
||||
{
|
||||
if (_hitBoxes[i].Contains(p))
|
||||
{
|
||||
if (_lastHitIdx != i)
|
||||
{
|
||||
_lastHitIdx = i;
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lastHitIdx != -1)
|
||||
{
|
||||
_lastHitIdx = -1;
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Rect> _hitBoxes = new List<Rect>();
|
||||
private int _lastHitIdx = -1;
|
||||
}
|
||||
|
||||
public partial class Statistics : ChromelessWindow
|
||||
{
|
||||
public Statistics()
|
||||
|
|
|
@ -47,8 +47,9 @@
|
|||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
IsCheckedChanged="OnToggleFilter"
|
||||
IsChecked="{Binding IsFiltered}"
|
||||
Click="OnToggleFilterClicked"
|
||||
IsChecked="{Binding IsFiltered, Mode=TwoWay}"
|
||||
IsVisible="{Binding !IsFolder}"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
@ -78,8 +79,8 @@
|
|||
Classes="filter"
|
||||
Margin="0,0,8,0"
|
||||
Background="Transparent"
|
||||
IsCheckedChanged="OnToggleFilter"
|
||||
IsChecked="{Binding IsFiltered}"
|
||||
Click="OnToggleFilterClicked"
|
||||
IsChecked="{Binding IsFiltered, Mode=TwoWay}"
|
||||
ToolTip.Tip="{DynamicResource Text.Filter}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -247,7 +247,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void OnToggleFilter(object sender, RoutedEventArgs e)
|
||||
private void OnToggleFilterClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton toggle && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
|
@ -258,7 +258,7 @@ namespace SourceGit.Views
|
|||
target = tag;
|
||||
|
||||
if (target != null)
|
||||
repo.UpdateFilter(target.Name, toggle.IsChecked == true);
|
||||
repo.UpdateFilters([target.Name], toggle.IsChecked == true);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
|
|
|
@ -437,8 +437,8 @@ namespace SourceGit.Views
|
|||
base.OnLoaded(e);
|
||||
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
TextArea.TextView.PointerEntered += OnTextViewPointerEntered;
|
||||
TextArea.TextView.PointerMoved += OnTextViewPointerMoved;
|
||||
TextArea.TextView.PointerEntered += OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerMoved += OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerWheelChanged += OnTextViewPointerWheelChanged;
|
||||
|
||||
UpdateTextMate();
|
||||
|
@ -449,8 +449,8 @@ namespace SourceGit.Views
|
|||
base.OnUnloaded(e);
|
||||
|
||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||
TextArea.TextView.PointerEntered -= OnTextViewPointerEntered;
|
||||
TextArea.TextView.PointerMoved -= OnTextViewPointerMoved;
|
||||
TextArea.TextView.PointerEntered -= OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerMoved -= OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerWheelChanged -= OnTextViewPointerWheelChanged;
|
||||
|
||||
if (_textMate != null)
|
||||
|
@ -510,25 +510,43 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTextViewPointerEntered(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (EnableChunkSelection && sender is TextView view)
|
||||
UpdateSelectedChunk(e.GetPosition(view).Y + view.VerticalOffset);
|
||||
}
|
||||
|
||||
private void OnTextViewPointerMoved(object sender, PointerEventArgs e)
|
||||
private void OnTextViewPointerChanged(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (EnableChunkSelection && sender is TextView view)
|
||||
{
|
||||
var chunk = SelectedChunk;
|
||||
if (chunk != null)
|
||||
var selection = TextArea.Selection;
|
||||
if (selection == null || selection.IsEmpty)
|
||||
{
|
||||
var rect = new Rect(0, chunk.Y, Bounds.Width, chunk.Height);
|
||||
if (rect.Contains(e.GetPosition(this)))
|
||||
return;
|
||||
if (_lastSelectStart != _lastSelectEnd)
|
||||
{
|
||||
_lastSelectStart = TextLocation.Empty;
|
||||
_lastSelectEnd = TextLocation.Empty;
|
||||
}
|
||||
|
||||
var chunk = SelectedChunk;
|
||||
if (chunk != null)
|
||||
{
|
||||
var rect = new Rect(0, chunk.Y, Bounds.Width, chunk.Height);
|
||||
if (rect.Contains(e.GetPosition(this)))
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateSelectedChunk(e.GetPosition(view).Y + view.VerticalOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateSelectedChunk(e.GetPosition(view).Y + view.VerticalOffset);
|
||||
var start = selection.StartPosition.Location;
|
||||
var end = selection.EndPosition.Location;
|
||||
if (_lastSelectStart != start || _lastSelectEnd != end)
|
||||
{
|
||||
_lastSelectStart = start;
|
||||
_lastSelectEnd = end;
|
||||
UpdateSelectedChunk(e.GetPosition(view).Y + view.VerticalOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedChunk == null)
|
||||
UpdateSelectedChunk(e.GetPosition(view).Y + view.VerticalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +665,9 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
private TextMate.Installation _textMate = null;
|
||||
protected LineStyleTransformer _lineStyleTransformer = null;
|
||||
private TextLocation _lastSelectStart = TextLocation.Empty;
|
||||
private TextLocation _lastSelectEnd = TextLocation.Empty;
|
||||
private LineStyleTransformer _lineStyleTransformer = null;
|
||||
}
|
||||
|
||||
public class CombinedTextDiffPresenter : ThemedTextDiffPresenter
|
||||
|
@ -674,18 +694,6 @@ namespace SourceGit.Views
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
var scroller = (ScrollViewer)e.NameScope.Find("PART_ScrollViewer");
|
||||
if (scroller != null)
|
||||
{
|
||||
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
|
||||
scroller.GotFocus += (_, _) => TrySetChunk(null);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateSelectedChunk(double y)
|
||||
{
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
|
@ -802,6 +810,27 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
var scroller = this.FindDescendantOfType<ScrollViewer>();
|
||||
if (scroller != null)
|
||||
{
|
||||
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
|
||||
scroller.GotFocus += OnTextViewScrollGotFocus;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
var scroller = this.FindDescendantOfType<ScrollViewer>();
|
||||
if (scroller != null)
|
||||
scroller.GotFocus -= OnTextViewScrollGotFocus;
|
||||
|
||||
base.OnUnloaded(e);
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
@ -833,6 +862,16 @@ namespace SourceGit.Views
|
|||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e)
|
||||
{
|
||||
if (EnableChunkSelection && sender is ScrollViewer viewer)
|
||||
{
|
||||
var area = viewer.FindDescendantOfType<TextArea>();
|
||||
if (!area.IsPointerOver)
|
||||
TrySetChunk(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SingleSideTextDiffPresenter : ThemedTextDiffPresenter
|
||||
|
@ -1001,8 +1040,6 @@ namespace SourceGit.Views
|
|||
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
_scrollViewer.ScrollChanged -= OnTextViewScrollChanged;
|
||||
|
@ -1012,6 +1049,7 @@ namespace SourceGit.Views
|
|||
|
||||
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
|
||||
|
||||
base.OnUnloaded(e);
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1085,12 @@ namespace SourceGit.Views
|
|||
|
||||
private void OnTextViewScrollGotFocus(object sender, GotFocusEventArgs e)
|
||||
{
|
||||
TrySetChunk(null);
|
||||
if (EnableChunkSelection && sender is ScrollViewer viewer)
|
||||
{
|
||||
var area = viewer.FindDescendantOfType<TextArea>();
|
||||
if (!area.IsPointerOver)
|
||||
TrySetChunk(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class RepositoryListBox : ListBox
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(ListBox);
|
||||
|
@ -40,7 +40,7 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!e.Handled)
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
<v:CommitMessageTextBox Grid.Row="2" Text="{Binding CommitMessage, Mode=TwoWay}"/>
|
||||
|
||||
<!-- Commit Options -->
|
||||
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto">
|
||||
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto,Auto">
|
||||
<Button Grid.Column="0"
|
||||
Classes="icon_button"
|
||||
Margin="4,0,0,0" Padding="0"
|
||||
|
@ -185,7 +185,7 @@
|
|||
ToolTip.Tip="{DynamicResource Text.WorkingCopy.CommitMessageHelper}"
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0">
|
||||
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Menu}"/>
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Menu}"/>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
|
@ -223,19 +223,38 @@
|
|||
Padding="8,0"
|
||||
Command="{Binding Commit}"
|
||||
HotKey="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"
|
||||
ToolTip.Tip="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0"/>
|
||||
|
||||
ToolTip.VerticalOffset="0">
|
||||
<ToolTip.Tip>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock TextAlignment="Left" TextWrapping="Wrap">
|
||||
<Run Text="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"/>
|
||||
<Run Foreground="{DynamicResource Brush.FG2}" Text="{DynamicResource Text.WorkingCopy.CommitTip}"/>
|
||||
</TextBlock>
|
||||
<TextBlock TextAlignment="Left" TextWrapping="Wrap" Margin="0,4,0,0">
|
||||
<Run Text="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+⇧+Enter}"/>
|
||||
<Run Foreground="{DynamicResource Brush.FG2}" Text="{DynamicResource Text.WorkingCopy.CommitWithAutoStage}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</ToolTip.Tip>
|
||||
</Button>
|
||||
|
||||
<!-- Invisible button just to add another hotkey `Ctrl+Shift+Enter` to commit with auto-stage -->
|
||||
<Button Grid.Column="7"
|
||||
Width="0" Height="0"
|
||||
Background="Transparent"
|
||||
Command="{Binding CommitWithAutoStage}"
|
||||
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"/>
|
||||
|
||||
<Button Grid.Column="8"
|
||||
Classes="flat"
|
||||
Content="{DynamicResource Text.WorkingCopy.CommitAndPush}"
|
||||
Height="28"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,0"
|
||||
Command="{Binding CommitWithPush}"
|
||||
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
|
||||
ToolTip.Tip="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
|
||||
HotKey="Alt+Enter"
|
||||
ToolTip.Tip="{OnPlatform Alt+Enter, macOS=⌥+Enter}"
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0"
|
||||
IsVisible="{Binding IsCommitWithPushVisible}"/>
|
||||
|
|
|
@ -81,7 +81,6 @@ namespace SourceGit.Views
|
|||
{
|
||||
vm.Discard(selected);
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue