diff --git a/.gitignore b/.gitignore index a0576b9fc..b8ed1295a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ build/*.AppImage SourceGit.app/ build.command src/Properties/launchSettings.json +*.lscache diff --git a/README.md b/README.md index e26b52c72..2bf6c6968 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,9 @@ You can define your own conventional commit types (per-repository) by following Everyone is welcome to submit a PR. Please make sure your PR is based on the latest `develop` branch and the target branch of PR is `develop`. +This project has a submodule in `depends/AvaloniaEdit` which is a custom fork of [Official AvaloniaEdit](https://github.com/AvaloniaUI/AvaloniaEdit). +Please make sure it is initialized - enable `--recurse-submodules` option while cloning or run `git submodule update --init` after cloned. + In short, here are the commands to get started once [.NET tools are installed](https://dotnet.microsoft.com/en-us/download): ```sh diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md index f5e0b5400..3e2f1143c 100644 --- a/THIRD-PARTY-LICENSES.md +++ b/THIRD-PARTY-LICENSES.md @@ -7,25 +7,25 @@ The project uses the following third-party libraries or assets ### AvaloniaUI - **Source**: https://github.com/AvaloniaUI/Avalonia -- **Version**: 11.3.13 +- **Version**: 12.0.4 - **License**: MIT License - **License Link**: https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md +### Avalonia.Controls.DataGrid + +- **Source**: https://github.com/AvaloniaUI/Avalonia.Controls.DataGrid +- **Version**: 12.0.2 +- **License**: MIT License +- **License Link**: https://github.com/AvaloniaUI/Avalonia.Controls.DataGrid/blob/master/licence.md + ### AvaloniaEdit - **Official Source**: https://github.com/AvaloniaUI/AvaloniaEdit - **Fork (Modified)**: https://github.com/love-linger/AvaloniaEdit -- **Version**: 11.4.1 +- **Version**: Based on 12.0.x - **License**: MIT License - **License Link**: https://github.com/AvaloniaUI/AvaloniaEdit/blob/master/LICENSE -### LiveChartsCore.SkiaSharpView.Avalonia - -- **Source**: https://github.com/beto-rodriguez/LiveCharts2 -- **Version**: 2.0.0 -- **License**: MIT License -- **License Link**: https://github.com/beto-rodriguez/LiveCharts2/blob/master/LICENSE - ### TextMateSharp - **Source**: https://github.com/danipen/TextMateSharp @@ -61,6 +61,12 @@ The project uses the following third-party libraries or assets - **License**: MIT License - **License Link**: https://github.com/nickbabcock/Pfim/blob/master/LICENSE.txt +### StbImageSharp + +- **Source**: https://github.com/StbSharp/StbImageSharp +- **Version**: 2.30.15 +- **License**: Public Domain + ## Fonts ### JetBrainsMono diff --git a/TRANSLATION.md b/TRANSLATION.md index 1263c1103..915f82e31 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,7 +6,7 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-93.73%25-yellow) +### ![de__DE](https://img.shields.io/badge/de__DE-91.83%25-yellow)
Missing keys in de_DE.axaml @@ -15,6 +15,11 @@ This document shows the translation status of each locale file in the repository - Text.AIAssistant.Use - Text.App.HideOthers - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad - Text.BranchCM.CompareWithSpecial - Text.CheckoutBranchFromStash - Text.CheckoutBranchFromStash.Branch @@ -25,6 +30,8 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.BranchesAndTags - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime - Text.CommitDetail.CollapseToBottom - Text.CommitMessageTextBox.Column - Text.Compare.Changes @@ -32,10 +39,13 @@ This document shows the translation status of each locale file in the repository - Text.Compare.Commits.LeftOnly - Text.Compare.Commits.RightOnly - Text.Compare.Commits.Tips +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.ConfigureCustomActionControls.StringFormatter - Text.ConfigureCustomActionControls.StringFormatter.Tip - Text.ConfigureCustomActionControls.UseFriendlyName - Text.ConfirmEmptyCommit.StageSelectedThenCommit +- Text.CopyAsPatch +- Text.Diff.EmptyFile - Text.Diff.Submodule.UncommittedChanges - Text.Discard.IncludeModified - Text.GotoRevisionSelector @@ -54,6 +64,10 @@ This document shows the translation status of each locale file in the repository - Text.Init.CommandTip - Text.Init.ErrorMessageTip - Text.InteractiveRebase.NoVerify +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.OpenLocalRepository - Text.OpenLocalRepository.Bookmark - Text.OpenLocalRepository.Group @@ -63,174 +77,116 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.AI.Model.AutoFetchAvailableModels - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.Git.UseStashAndReapplyByDefault - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.EnableAutoFetch - Text.StashCM.ApplyFileChanges - Text.StashCM.Branch - Text.SubmoduleRevisionCompare - Text.SubmoduleRevisionCompare.OpenDetails +- Text.UpdateSubmodules.Recursive - Text.Worktree.Branch - Text.Worktree.Head - Text.Worktree.Path
-### ![es__ES](https://img.shields.io/badge/es__ES-97.98%25-yellow) +### ![el__GR](https://img.shields.io/badge/el__GR-99.10%25-yellow) + +
+Missing keys in el_GR.axaml + +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.CopyAsPatch +- Text.Diff.EmptyFile +- Text.UpdateSubmodules.Recursive + +
+ +### ![es__ES](https://img.shields.io/badge/es__ES-99.10%25-yellow)
Missing keys in es_ES.axaml -- Text.CommitDetail.CollapseToBottom -- Text.Compare.Changes -- Text.Compare.Commits -- Text.Compare.Commits.LeftOnly -- Text.Compare.Commits.RightOnly -- Text.Compare.Commits.Tips -- Text.Histories.HighlightsInGraph -- Text.Histories.HighlightsInGraph.All -- Text.Histories.HighlightsInGraph.CurrentBranchOnly -- Text.Histories.HighlightsInGraph.CurrentBranchAndSelectedCommits -- Text.Histories.HighlightsInGraph.SelectedCommitsOnly -- Text.HistoriesDetailsStandalone -- Text.HistoriesDetailsStandalone.CommitDetail -- Text.HistoriesDetailsStandalone.RevisionCompare -- Text.Hotkeys.Repo.ToggleHistoriesDetailPanel -- Text.InteractiveRebase.NoVerify -- Text.Preferences.AI.Model -- Text.Preferences.AI.Model.AutoFetchAvailableModels -- Text.Preferences.General.ShowRelativeTimeInGraph -- Text.Rebase.NoVerify +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.CopyAsPatch +- Text.Diff.EmptyFile +- Text.UpdateSubmodules.Recursive
-### ![fr__FR](https://img.shields.io/badge/fr__FR-88.07%25-yellow) +### ![fr__FR](https://img.shields.io/badge/fr__FR-98.01%25-yellow)
Missing keys in fr_FR.axaml -- Text.About.GitSourceRevision -- Text.About.ReleaseDate -- Text.AIAssistant.Use -- Text.App.HideOthers -- Text.Apply.3Way -- Text.Blame.IgnoreWhitespace -- Text.BranchCM.CompareTwo -- Text.BranchCM.CompareWith -- Text.BranchCM.CompareWithHead -- Text.BranchCM.CompareWithSpecial -- Text.BranchCM.EditDescription -- Text.ChangeCM.Merge -- Text.ChangeCM.MergeExternal -- Text.ChangeCM.ResetFileTo -- Text.Checkout.WarnUpdatingSubmodules -- Text.CheckoutBranchFromStash -- Text.CheckoutBranchFromStash.Branch -- Text.CheckoutBranchFromStash.Stash -- Text.Clone.Bookmark -- Text.Clone.Group -- Text.CommandPalette.Branches -- Text.CommandPalette.BranchesAndTags -- Text.CommandPalette.RepositoryActions -- Text.CommandPalette.RevisionFiles -- Text.CommitDetail.CollapseToBottom -- Text.CommitMessageTextBox.Column -- Text.CommitMessageTextBox.Placeholder -- Text.Compare.Changes -- Text.Compare.Commits -- Text.Compare.Commits.LeftOnly -- Text.Compare.Commits.RightOnly -- Text.Compare.Commits.Tips -- Text.Configure.Git.AskBeforeAutoUpdatingSubmodules -- Text.ConfigureCustomActionControls.StringFormatter -- Text.ConfigureCustomActionControls.StringFormatter.Tip -- Text.ConfigureCustomActionControls.UseFriendlyName -- Text.ConfirmEmptyCommit.StageSelectedThenCommit -- Text.Diff.Submodule.UncommittedChanges -- Text.Discard.IncludeModified -- Text.EditBranchDescription -- Text.EditBranchDescription.Target -- Text.FileCM.CustomAction -- Text.GotoRevisionSelector -- Text.Histories.Header.DateTime -- Text.Histories.HighlightsInGraph -- Text.Histories.HighlightsInGraph.All -- Text.Histories.HighlightsInGraph.CurrentBranchOnly -- Text.Histories.HighlightsInGraph.CurrentBranchAndSelectedCommits -- Text.Histories.HighlightsInGraph.SelectedCommitsOnly -- Text.Histories.ShowColumns -- Text.HistoriesDetailsStandalone -- Text.HistoriesDetailsStandalone.CommitDetail -- Text.HistoriesDetailsStandalone.RevisionCompare -- Text.Hotkeys.Global.OpenLocalRepository -- Text.Hotkeys.Global.ShowWorkspaceDropdownMenu -- Text.Hotkeys.Global.Zoom -- Text.Hotkeys.Repo.CreateBranch -- Text.Hotkeys.Repo.GoToChild -- Text.Hotkeys.Repo.GoToParent -- Text.Hotkeys.Repo.ToggleHistoriesDetailPanel -- Text.Init.CommandTip -- Text.Init.ErrorMessageTip -- Text.InteractiveRebase.NoVerify -- Text.MergeConflictEditor.AcceptBoth.MineFirst -- Text.MergeConflictEditor.AcceptBoth.TheirsFirst -- Text.MergeConflictEditor.UseBoth -- Text.MergeConflictEditor.AllResolved -- Text.MergeConflictEditor.ConflictsRemaining -- Text.MergeConflictEditor.Mine -- Text.MergeConflictEditor.NextConflict -- Text.MergeConflictEditor.PrevConflict -- Text.MergeConflictEditor.Result -- Text.MergeConflictEditor.SaveAndStage -- Text.MergeConflictEditor.Theirs -- Text.MergeConflictEditor.Title -- Text.MergeConflictEditor.UnsavedChanges -- Text.MergeConflictEditor.UseMine -- Text.MergeConflictEditor.UseTheirs -- Text.MergeConflictEditor.Undo -- Text.No -- Text.OpenFile -- Text.OpenLocalRepository -- Text.OpenLocalRepository.Bookmark -- Text.OpenLocalRepository.Group -- Text.OpenLocalRepository.Path -- Text.PageTabBar.Tab.MoveToWorkspace -- Text.PageTabBar.Tab.Refresh -- Text.Preferences.AI.AdditionalPrompt -- Text.Preferences.AI.Model -- Text.Preferences.AI.Model.AutoFetchAvailableModels -- Text.Preferences.DiffMerge.DiffArgs -- Text.Preferences.DiffMerge.DiffArgs.Tip -- Text.Preferences.DiffMerge.MergeArgs -- Text.Preferences.DiffMerge.MergeArgs.Tip -- Text.Preferences.General.ShowRelativeTimeInGraph -- Text.Preferences.General.Use24Hours -- Text.Preferences.Git.UseStashAndReapplyByDefault -- Text.Preferences.Shell.Args -- Text.Preferences.Shell.Args.Tip -- Text.Rebase.NoVerify -- Text.RemoteCM.EnableAutoFetch -- Text.Repository.OpenAsFolder -- Text.Repository.Resolve -- Text.SelfUpdate.CurrentVersion -- Text.SelfUpdate.ReleaseDate -- Text.StashCM.ApplyFileChanges -- Text.StashCM.Branch -- Text.SubmoduleRevisionCompare -- Text.SubmoduleRevisionCompare.OpenDetails -- Text.TagCM.CompareTwo -- Text.TagCM.CompareWith -- Text.TagCM.CompareWithHead -- Text.WorkingCopy.Conflicts.Merge -- Text.WorkingCopy.Conflicts.MergeExternal -- Text.Worktree.Branch -- Text.Worktree.Head -- Text.Worktree.Path -- Text.Yes +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.CopyAsPatch +- Text.Diff.EmptyFile +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts +- Text.Preferences.General.UseCompactBranchNames +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts +- Text.UpdateSubmodules.Recursive
-### ![id__ID](https://img.shields.io/badge/id__ID-86.35%25-yellow) +### ![he__IL](https://img.shields.io/badge/he__IL-98.01%25-yellow) + +
+Missing keys in he_IL.axaml + +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.CopyAsPatch +- Text.Diff.EmptyFile +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts +- Text.Preferences.General.UseCompactBranchNames +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts +- Text.UpdateSubmodules.Recursive + +
+ +### ![id__ID](https://img.shields.io/badge/id__ID-84.66%25-yellow)
Missing keys in id_ID.axaml @@ -241,6 +197,11 @@ This document shows the translation status of each locale file in the repository - Text.AIAssistant.Use - Text.App.HideOthers - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad - Text.Blame.BlameOnPreviousRevision - Text.Blame.IgnoreWhitespace - Text.BranchCM.CompareTwo @@ -263,6 +224,8 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.BranchesAndTags - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime - Text.CommitDetail.CollapseToBottom - Text.CommitMessageTextBox.Column - Text.CommitMessageTextBox.Placeholder @@ -274,12 +237,15 @@ This document shows the translation status of each locale file in the repository - Text.Configure.CommitMessageTemplate.BuiltinVars - Text.Configure.Git.AskBeforeAutoUpdatingSubmodules - Text.Configure.Git.ConventionalTypesOverride +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.ConfigureCustomActionControls.StringFormatter - Text.ConfigureCustomActionControls.StringFormatter.Tip - Text.ConfigureCustomActionControls.StringValue.Tip - Text.ConfigureCustomActionControls.UseFriendlyName - Text.ConfirmEmptyCommit.StageSelectedThenCommit +- Text.CopyAsPatch - Text.DealWithLocalChanges.DoNothing +- Text.Diff.EmptyFile - Text.Diff.Submodule.UncommittedChanges - Text.Discard.IncludeModified - Text.EditBranchDescription @@ -288,7 +254,6 @@ This document shows the translation status of each locale file in the repository - Text.GitLFS.Locks.UnlockAllMyLocks - Text.GitLFS.Locks.UnlockAllMyLocks.Confirm - Text.GotoRevisionSelector -- Text.Histories.Header.DateTime - Text.Histories.HighlightsInGraph - Text.Histories.HighlightsInGraph.All - Text.Histories.HighlightsInGraph.CurrentBranchOnly @@ -311,6 +276,10 @@ This document shows the translation status of each locale file in the repository - Text.InteractiveRebase.NoVerify - Text.Launcher.Commands - Text.Launcher.OpenRepository +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.MergeConflictEditor.AcceptBoth.MineFirst - Text.MergeConflictEditor.AcceptBoth.TheirsFirst - Text.MergeConflictEditor.UseBoth @@ -346,12 +315,17 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.DiffMerge.MergeArgs.Tip - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.Git.UseStashAndReapplyByDefault - Text.Preferences.Shell.Args - Text.Preferences.Shell.Args.Tip - Text.PushToNewBranch - Text.PushToNewBranch.Title - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.EnableAutoFetch - Text.Repository.OpenAsFolder - Text.Repository.Resolve @@ -364,6 +338,7 @@ This document shows the translation status of each locale file in the repository - Text.TagCM.CompareTwo - Text.TagCM.CompareWith - Text.TagCM.CompareWithHead +- Text.UpdateSubmodules.Recursive - Text.WorkingCopy.Conflicts.Merge - Text.WorkingCopy.Conflicts.MergeExternal - Text.Worktree.Branch @@ -373,7 +348,7 @@ This document shows the translation status of each locale file in the repository
-### ![it__IT](https://img.shields.io/badge/it__IT-93.12%25-yellow) +### ![it__IT](https://img.shields.io/badge/it__IT-91.33%25-yellow)
Missing keys in it_IT.axaml @@ -382,6 +357,11 @@ This document shows the translation status of each locale file in the repository - Text.AIAssistant.Use - Text.App.HideOthers - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad - Text.BranchCM.CompareWithSpecial - Text.ChangeCM.ResetFileTo - Text.CheckoutBranchFromStash @@ -393,6 +373,8 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.BranchesAndTags - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime - Text.CommitDetail.CollapseToBottom - Text.CommitMessageTextBox.Column - Text.Compare.Changes @@ -400,14 +382,16 @@ This document shows the translation status of each locale file in the repository - Text.Compare.Commits.LeftOnly - Text.Compare.Commits.RightOnly - Text.Compare.Commits.Tips +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.ConfigureCustomActionControls.StringFormatter - Text.ConfigureCustomActionControls.StringFormatter.Tip - Text.ConfigureCustomActionControls.UseFriendlyName - Text.ConfirmEmptyCommit.StageSelectedThenCommit +- Text.CopyAsPatch +- Text.Diff.EmptyFile - Text.Diff.Submodule.UncommittedChanges - Text.Discard.IncludeModified - Text.GotoRevisionSelector -- Text.Histories.Header.DateTime - Text.Histories.HighlightsInGraph - Text.Histories.HighlightsInGraph.All - Text.Histories.HighlightsInGraph.CurrentBranchOnly @@ -425,6 +409,10 @@ This document shows the translation status of each locale file in the repository - Text.Init.CommandTip - Text.Init.ErrorMessageTip - Text.InteractiveRebase.NoVerify +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.OpenLocalRepository - Text.OpenLocalRepository.Bookmark - Text.OpenLocalRepository.Group @@ -434,8 +422,13 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.AI.Model.AutoFetchAvailableModels - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.Git.UseStashAndReapplyByDefault - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.EnableAutoFetch - Text.SelfUpdate.CurrentVersion - Text.SelfUpdate.ReleaseDate @@ -443,13 +436,14 @@ This document shows the translation status of each locale file in the repository - Text.StashCM.Branch - Text.SubmoduleRevisionCompare - Text.SubmoduleRevisionCompare.OpenDetails +- Text.UpdateSubmodules.Recursive - Text.Worktree.Branch - Text.Worktree.Head - Text.Worktree.Path
-### ![ja__JP](https://img.shields.io/badge/ja__JP-94.03%25-yellow) +### ![ja__JP](https://img.shields.io/badge/ja__JP-92.13%25-yellow)
Missing keys in ja_JP.axaml @@ -458,6 +452,11 @@ This document shows the translation status of each locale file in the repository - Text.AIAssistant.Use - Text.App.HideOthers - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad - Text.BranchCM.CompareWithSpecial - Text.CheckoutBranchFromStash - Text.CheckoutBranchFromStash.Branch @@ -468,17 +467,22 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.BranchesAndTags - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles +- Text.CommitCM.CopyAuthorTime +- Text.CommitCM.CopyCommitterTime - Text.CommitDetail.CollapseToBottom - Text.Compare.Changes - Text.Compare.Commits - Text.Compare.Commits.LeftOnly - Text.Compare.Commits.RightOnly - Text.Compare.Commits.Tips +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.ConfigureCustomActionControls.StringFormatter - Text.ConfigureCustomActionControls.StringFormatter.Tip - Text.ConfigureCustomActionControls.UseFriendlyName - Text.ConfirmEmptyCommit.StageSelectedThenCommit +- Text.CopyAsPatch - Text.DealWithLocalChanges.DoNothing +- Text.Diff.EmptyFile - Text.Diff.Submodule.UncommittedChanges - Text.Discard.IncludeModified - Text.Histories.HighlightsInGraph @@ -495,6 +499,10 @@ This document shows the translation status of each locale file in the repository - Text.Init.CommandTip - Text.Init.ErrorMessageTip - Text.InteractiveRebase.NoVerify +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.OpenLocalRepository - Text.OpenLocalRepository.Bookmark - Text.OpenLocalRepository.Group @@ -504,163 +512,38 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.AI.Model.AutoFetchAvailableModels - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.Git.UseStashAndReapplyByDefault - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.EnableAutoFetch - Text.StashCM.Branch - Text.SubmoduleRevisionCompare - Text.SubmoduleRevisionCompare.OpenDetails +- Text.UpdateSubmodules.Recursive - Text.Worktree.Branch - Text.Worktree.Head - Text.Worktree.Path
-### ![ko__KR](https://img.shields.io/badge/ko__KR-86.25%25-yellow) +### ![ko__KR](https://img.shields.io/badge/ko__KR-99.50%25-yellow)
Missing keys in ko_KR.axaml -- Text.About.GitSourceRevision -- Text.About.ReleaseDate -- Text.AIAssistant.Use -- Text.App.HideOthers -- Text.Apply.3Way -- Text.Blame.BlameOnPreviousRevision -- Text.Blame.IgnoreWhitespace -- Text.Blame.TypeNotSupported -- Text.BranchCM.CompareTwo -- Text.BranchCM.CompareWith -- Text.BranchCM.CompareWithHead -- Text.BranchCM.CompareWithSpecial -- Text.BranchCM.CreatePR -- Text.BranchCM.CreatePRForUpstream -- Text.BranchCM.EditDescription -- Text.ChangeCM.Merge -- Text.ChangeCM.MergeExternal -- Text.ChangeCM.ResetFileTo -- Text.Checkout.WarnUpdatingSubmodules -- Text.CheckoutBranchFromStash -- Text.CheckoutBranchFromStash.Branch -- Text.CheckoutBranchFromStash.Stash -- Text.Clone.Bookmark -- Text.Clone.Group -- Text.CommandPalette.Branches -- Text.CommandPalette.BranchesAndTags -- Text.CommandPalette.RepositoryActions -- Text.CommandPalette.RevisionFiles -- Text.CommitDetail.CollapseToBottom -- Text.CommitMessageTextBox.Column -- Text.CommitMessageTextBox.Placeholder -- Text.Compare.Changes -- Text.Compare.Commits -- Text.Compare.Commits.LeftOnly -- Text.Compare.Commits.RightOnly -- Text.Compare.Commits.Tips -- Text.Configure.Git.AskBeforeAutoUpdatingSubmodules -- Text.Configure.Git.ConventionalTypesOverride -- Text.ConfigureCustomActionControls.StringFormatter -- Text.ConfigureCustomActionControls.StringFormatter.Tip -- Text.ConfigureCustomActionControls.StringValue.Tip -- Text.ConfigureCustomActionControls.UseFriendlyName -- Text.ConfirmEmptyCommit.StageSelectedThenCommit -- Text.DealWithLocalChanges.DoNothing -- Text.Diff.Submodule.UncommittedChanges -- Text.Discard.IncludeModified -- Text.EditBranchDescription -- Text.EditBranchDescription.Target -- Text.FileCM.CustomAction -- Text.GitLFS.Locks.UnlockAllMyLocks -- Text.GitLFS.Locks.UnlockAllMyLocks.Confirm -- Text.GotoRevisionSelector -- Text.Histories.Header.DateTime -- Text.Histories.HighlightsInGraph -- Text.Histories.HighlightsInGraph.All -- Text.Histories.HighlightsInGraph.CurrentBranchOnly -- Text.Histories.HighlightsInGraph.CurrentBranchAndSelectedCommits -- Text.Histories.HighlightsInGraph.SelectedCommitsOnly -- Text.Histories.ShowColumns -- Text.HistoriesDetailsStandalone -- Text.HistoriesDetailsStandalone.CommitDetail -- Text.HistoriesDetailsStandalone.RevisionCompare -- Text.Hotkeys.Global.OpenLocalRepository -- Text.Hotkeys.Global.ShowWorkspaceDropdownMenu -- Text.Hotkeys.Global.Zoom -- Text.Hotkeys.Repo.CreateBranch -- Text.Hotkeys.Repo.GoToChild -- Text.Hotkeys.Repo.GoToParent -- Text.Hotkeys.Repo.OpenCommandPalette -- Text.Hotkeys.Repo.ToggleHistoriesDetailPanel -- Text.Init.CommandTip -- Text.Init.ErrorMessageTip -- Text.InteractiveRebase.NoVerify -- Text.Launcher.Commands -- Text.Launcher.OpenRepository -- Text.MergeConflictEditor.AcceptBoth.MineFirst -- Text.MergeConflictEditor.AcceptBoth.TheirsFirst -- Text.MergeConflictEditor.UseBoth -- Text.MergeConflictEditor.AllResolved -- Text.MergeConflictEditor.ConflictsRemaining -- Text.MergeConflictEditor.Mine -- Text.MergeConflictEditor.NextConflict -- Text.MergeConflictEditor.PrevConflict -- Text.MergeConflictEditor.Result -- Text.MergeConflictEditor.SaveAndStage -- Text.MergeConflictEditor.Theirs -- Text.MergeConflictEditor.Title -- Text.MergeConflictEditor.UnsavedChanges -- Text.MergeConflictEditor.UseMine -- Text.MergeConflictEditor.UseTheirs -- Text.MergeConflictEditor.Undo -- Text.No -- Text.Open -- Text.Open.SystemDefaultEditor -- Text.OpenFile -- Text.OpenLocalRepository -- Text.OpenLocalRepository.Bookmark -- Text.OpenLocalRepository.Group -- Text.OpenLocalRepository.Path -- Text.PageTabBar.Tab.MoveToWorkspace -- Text.PageTabBar.Tab.Refresh -- Text.Preferences.AI.AdditionalPrompt -- Text.Preferences.AI.Model -- Text.Preferences.AI.Model.AutoFetchAvailableModels -- Text.Preferences.Appearance.UseFixedTabWidth -- Text.Preferences.DiffMerge.DiffArgs -- Text.Preferences.DiffMerge.DiffArgs.Tip -- Text.Preferences.DiffMerge.MergeArgs -- Text.Preferences.DiffMerge.MergeArgs.Tip -- Text.Preferences.General.ShowRelativeTimeInGraph -- Text.Preferences.General.Use24Hours -- Text.Preferences.Git.UseStashAndReapplyByDefault -- Text.Preferences.Shell.Args -- Text.Preferences.Shell.Args.Tip -- Text.PushToNewBranch -- Text.PushToNewBranch.Title -- Text.Rebase.NoVerify -- Text.RemoteCM.EnableAutoFetch -- Text.Repository.OpenAsFolder -- Text.Repository.Resolve -- Text.SelfUpdate.CurrentVersion -- Text.SelfUpdate.ReleaseDate -- Text.StashCM.ApplyFileChanges -- Text.StashCM.Branch -- Text.Submodule.Status.Unmerged -- Text.SubmoduleRevisionCompare -- Text.SubmoduleRevisionCompare.OpenDetails -- Text.TagCM.CompareTwo -- Text.TagCM.CompareWith -- Text.TagCM.CompareWithHead -- Text.WorkingCopy.Conflicts.Merge -- Text.WorkingCopy.Conflicts.MergeExternal -- Text.Worktree.Branch -- Text.Worktree.Head -- Text.Worktree.Path -- Text.Yes +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.Diff.EmptyFile +- Text.UpdateSubmodules.Recursive
-### ![pt__BR](https://img.shields.io/badge/pt__BR-65.72%25-red) +### ![pt__BR](https://img.shields.io/badge/pt__BR-64.44%25-red)
Missing keys in pt_BR.axaml @@ -669,6 +552,11 @@ This document shows the translation status of each locale file in the repository - Text.AIAssistant.Use - Text.App.HideOthers - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad - Text.Blame.BlameOnPreviousRevision - Text.BranchCM.CompareWithSpecial - Text.BranchCM.InteractiveRebase.Manually @@ -698,8 +586,10 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles - Text.CommitCM.CopyAuthor +- Text.CommitCM.CopyAuthorTime - Text.CommitCM.CopyCommitMessage - Text.CommitCM.CopyCommitter +- Text.CommitCM.CopyCommitterTime - Text.CommitCM.CopySubject - Text.CommitCM.InteractiveRebase - Text.CommitCM.InteractiveRebase.Drop @@ -708,7 +598,6 @@ This document shows the translation status of each locale file in the repository - Text.CommitCM.InteractiveRebase.Manually - Text.CommitCM.InteractiveRebase.Reword - Text.CommitCM.InteractiveRebase.Squash -- Text.CommitCM.Merge - Text.CommitCM.MergeMultiple - Text.CommitCM.PushRevision - Text.CommitCM.Rebase @@ -741,6 +630,7 @@ This document shows the translation status of each locale file in the repository - Text.Configure.CustomAction.WaitForExit - Text.Configure.Git.AskBeforeAutoUpdatingSubmodules - Text.Configure.Git.ConventionalTypesOverride +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.Configure.Git.PreferredMergeMode - Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit - Text.Configure.IssueTracker.AddSampleGiteeIssue @@ -767,6 +657,7 @@ This document shows the translation status of each locale file in the repository - Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmRestart.Title - Text.ConfirmRestart.Message +- Text.CopyAsPatch - Text.CopyFullPath - Text.CreateBranch.OverwriteExisting - Text.DeinitSubmodule @@ -778,6 +669,7 @@ This document shows the translation status of each locale file in the repository - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.EmptyFile - Text.Diff.First - Text.Diff.Image.Blend - Text.Diff.Image.Difference @@ -805,7 +697,6 @@ This document shows the translation status of each locale file in the repository - Text.GitLFS.Locks.UnlockAllMyLocks - Text.GitLFS.Locks.UnlockAllMyLocks.Confirm - Text.GotoRevisionSelector -- Text.Histories.Header.DateTime - Text.Histories.HighlightsInGraph - Text.Histories.HighlightsInGraph.All - Text.Histories.HighlightsInGraph.CurrentBranchOnly @@ -839,6 +730,10 @@ This document shows the translation status of each locale file in the repository - Text.Launcher.Workspaces - Text.Merge.Edit - Text.Merge.Source +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.MergeConflictEditor.AcceptBoth.MineFirst - Text.MergeConflictEditor.AcceptBoth.TheirsFirst - Text.MergeConflictEditor.UseBoth @@ -890,6 +785,7 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.ShowTagsInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.General.UseGitHubStyleAvatar - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.SSLVerify @@ -903,6 +799,10 @@ This document shows the translation status of each locale file in the repository - Text.PushToNewBranch - Text.PushToNewBranch.Title - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.CustomAction - Text.RemoteCM.EnableAutoFetch - Text.Repository.BranchSort @@ -980,6 +880,7 @@ This document shows the translation status of each locale file in the repository - Text.TagCM.CopyName - Text.TagCM.CustomAction - Text.TagCM.DeleteMultiple +- Text.UpdateSubmodules.Recursive - Text.UpdateSubmodules.UpdateToRemoteTrackingBranch - Text.ViewLogs - Text.ViewLogs.Clear @@ -1007,34 +908,20 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-98.08%25-yellow) +### ![ru__RU](https://img.shields.io/badge/ru__RU-99.50%25-yellow)
Missing keys in ru_RU.axaml -- Text.Compare.Changes -- Text.Compare.Commits -- Text.Compare.Commits.LeftOnly -- Text.Compare.Commits.RightOnly -- Text.Compare.Commits.Tips -- Text.Histories.HighlightsInGraph -- Text.Histories.HighlightsInGraph.All -- Text.Histories.HighlightsInGraph.CurrentBranchOnly -- Text.Histories.HighlightsInGraph.CurrentBranchAndSelectedCommits -- Text.Histories.HighlightsInGraph.SelectedCommitsOnly -- Text.HistoriesDetailsStandalone -- Text.HistoriesDetailsStandalone.CommitDetail -- Text.HistoriesDetailsStandalone.RevisionCompare -- Text.Hotkeys.Repo.ToggleHistoriesDetailPanel -- Text.InteractiveRebase.NoVerify -- Text.Preferences.AI.Model -- Text.Preferences.AI.Model.AutoFetchAvailableModels -- Text.Preferences.General.ShowRelativeTimeInGraph -- Text.Rebase.NoVerify +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules +- Text.Diff.EmptyFile +- Text.UpdateSubmodules.Recursive
-### ![ta__IN](https://img.shields.io/badge/ta__IN-67.75%25-red) +### ![ta__IN](https://img.shields.io/badge/ta__IN-66.33%25-red)
Missing keys in ta_IN.axaml @@ -1050,15 +937,20 @@ This document shows the translation status of each locale file in the repository - Text.App.HideOthers - Text.App.ShowAll - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard - Text.Askpass.Passphrase - Text.Avatar.Load - Text.Bisect - Text.Bisect.Abort - Text.Bisect.Bad -- Text.Bisect.Detecting - Text.Bisect.Good - Text.Bisect.Skip -- Text.Bisect.WaitingForRange +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Bisect.WaitingForFirstGood +- Text.Bisect.WaitingForMark - Text.Blame.BlameOnPreviousRevision - Text.Blame.IgnoreWhitespace - Text.BranchCM.CompareTwo @@ -1100,8 +992,10 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles - Text.CommitCM.CopyAuthor +- Text.CommitCM.CopyAuthorTime - Text.CommitCM.CopyCommitMessage - Text.CommitCM.CopyCommitter +- Text.CommitCM.CopyCommitterTime - Text.CommitCM.CopySubject - Text.CommitCM.InteractiveRebase - Text.CommitCM.InteractiveRebase.Drop @@ -1137,6 +1031,7 @@ This document shows the translation status of each locale file in the repository - Text.Configure.CustomAction.Scope.Tag - Text.Configure.Git.AskBeforeAutoUpdatingSubmodules - Text.Configure.Git.ConventionalTypesOverride +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.Configure.Git.PreferredMergeMode - Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit - Text.Configure.IssueTracker.Share @@ -1161,6 +1056,7 @@ This document shows the translation status of each locale file in the repository - Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmRestart.Title - Text.ConfirmRestart.Message +- Text.CopyAsPatch - Text.CreateBranch.OverwriteExisting - Text.DealWithLocalChanges.DoNothing - Text.DeinitSubmodule @@ -1169,6 +1065,7 @@ This document shows the translation status of each locale file in the repository - Text.DeleteMultiTags - Text.DeleteMultiTags.DeleteFromRemotes - Text.DeleteMultiTags.Tip +- Text.Diff.EmptyFile - Text.Diff.Image.Blend - Text.Diff.Image.Difference - Text.Diff.Image.SideBySide @@ -1192,7 +1089,6 @@ This document shows the translation status of each locale file in the repository - Text.GitLFS.Locks.UnlockAllMyLocks - Text.GitLFS.Locks.UnlockAllMyLocks.Confirm - Text.GotoRevisionSelector -- Text.Histories.Header.DateTime - Text.Histories.HighlightsInGraph - Text.Histories.HighlightsInGraph.All - Text.Histories.HighlightsInGraph.CurrentBranchOnly @@ -1220,6 +1116,10 @@ This document shows the translation status of each locale file in the repository - Text.Launcher.Pages - Text.Launcher.Workspaces - Text.Merge.Edit +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.MergeConflictEditor.AcceptBoth.MineFirst - Text.MergeConflictEditor.AcceptBoth.TheirsFirst - Text.MergeConflictEditor.UseBoth @@ -1263,6 +1163,7 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.General.ShowChangesTabInCommitDetailByDefault - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.General.UseGitHubStyleAvatar - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.UseLibsecret @@ -1275,6 +1176,10 @@ This document shows the translation status of each locale file in the repository - Text.PushToNewBranch - Text.PushToNewBranch.Title - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.CustomAction - Text.RemoteCM.EnableAutoFetch - Text.Repository.BranchSort @@ -1337,6 +1242,7 @@ This document shows the translation status of each locale file in the repository - Text.TagCM.CustomAction - Text.TagCM.DeleteMultiple - Text.UpdateSubmodules.Target +- Text.UpdateSubmodules.Recursive - Text.UpdateSubmodules.UpdateToRemoteTrackingBranch - Text.ViewLogs - Text.ViewLogs.Clear @@ -1361,7 +1267,7 @@ This document shows the translation status of each locale file in the repository
-### ![uk__UA](https://img.shields.io/badge/uk__UA-68.55%25-red) +### ![uk__UA](https://img.shields.io/badge/uk__UA-67.13%25-red)
Missing keys in uk_UA.axaml @@ -1377,15 +1283,20 @@ This document shows the translation status of each locale file in the repository - Text.App.HideOthers - Text.App.ShowAll - Text.Apply.3Way +- Text.Apply.Source +- Text.Apply.Source.File +- Text.Apply.Source.Clipboard - Text.Askpass.Passphrase - Text.Avatar.Load - Text.Bisect - Text.Bisect.Abort - Text.Bisect.Bad -- Text.Bisect.Detecting - Text.Bisect.Good - Text.Bisect.Skip -- Text.Bisect.WaitingForRange +- Text.Bisect.WaitingForCheckoutAnother +- Text.Bisect.WaitingForFirstBad +- Text.Bisect.WaitingForFirstGood +- Text.Bisect.WaitingForMark - Text.Blame.BlameOnPreviousRevision - Text.Blame.IgnoreWhitespace - Text.BranchCM.CompareTwo @@ -1427,8 +1338,10 @@ This document shows the translation status of each locale file in the repository - Text.CommandPalette.RepositoryActions - Text.CommandPalette.RevisionFiles - Text.CommitCM.CopyAuthor +- Text.CommitCM.CopyAuthorTime - Text.CommitCM.CopyCommitMessage - Text.CommitCM.CopyCommitter +- Text.CommitCM.CopyCommitterTime - Text.CommitCM.CopySubject - Text.CommitCM.InteractiveRebase - Text.CommitCM.InteractiveRebase.Drop @@ -1464,6 +1377,7 @@ This document shows the translation status of each locale file in the repository - Text.Configure.CustomAction.Scope.Tag - Text.Configure.Git.AskBeforeAutoUpdatingSubmodules - Text.Configure.Git.ConventionalTypesOverride +- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit - Text.Configure.IssueTracker.Share - Text.ConfigureCustomActionControls @@ -1484,6 +1398,7 @@ This document shows the translation status of each locale file in the repository - Text.ConfirmEmptyCommit.StageSelectedThenCommit - Text.ConfirmRestart.Title - Text.ConfirmRestart.Message +- Text.CopyAsPatch - Text.CreateBranch.OverwriteExisting - Text.DealWithLocalChanges.DoNothing - Text.DeinitSubmodule @@ -1492,6 +1407,7 @@ This document shows the translation status of each locale file in the repository - Text.DeleteMultiTags - Text.DeleteMultiTags.DeleteFromRemotes - Text.DeleteMultiTags.Tip +- Text.Diff.EmptyFile - Text.Diff.Image.Blend - Text.Diff.Image.Difference - Text.Diff.Image.SideBySide @@ -1515,7 +1431,6 @@ This document shows the translation status of each locale file in the repository - Text.GitLFS.Locks.UnlockAllMyLocks - Text.GitLFS.Locks.UnlockAllMyLocks.Confirm - Text.GotoRevisionSelector -- Text.Histories.Header.DateTime - Text.Histories.HighlightsInGraph - Text.Histories.HighlightsInGraph.All - Text.Histories.HighlightsInGraph.CurrentBranchOnly @@ -1543,6 +1458,10 @@ This document shows the translation status of each locale file in the repository - Text.Launcher.Pages - Text.Launcher.Workspaces - Text.Merge.Edit +- Text.Merge.Test +- Text.Merge.Test.NoConflicts +- Text.Merge.Test.UnknownError +- Text.Merge.Test.WillCauseConflicts - Text.MergeConflictEditor.AcceptBoth.MineFirst - Text.MergeConflictEditor.AcceptBoth.TheirsFirst - Text.MergeConflictEditor.UseBoth @@ -1586,6 +1505,7 @@ This document shows the translation status of each locale file in the repository - Text.Preferences.General.ShowChangesTabInCommitDetailByDefault - Text.Preferences.General.ShowRelativeTimeInGraph - Text.Preferences.General.Use24Hours +- Text.Preferences.General.UseCompactBranchNames - Text.Preferences.General.UseGitHubStyleAvatar - Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.UseLibsecret @@ -1598,6 +1518,10 @@ This document shows the translation status of each locale file in the repository - Text.PushToNewBranch - Text.PushToNewBranch.Title - Text.Rebase.NoVerify +- Text.Rebase.Test +- Text.Rebase.Test.OK +- Text.Rebase.Test.UnknownError +- Text.Rebase.Test.WillCauseConflicts - Text.RemoteCM.CustomAction - Text.RemoteCM.EnableAutoFetch - Text.Repository.BranchSort @@ -1659,6 +1583,7 @@ This document shows the translation status of each locale file in the repository - Text.TagCM.CopyName - Text.TagCM.CustomAction - Text.TagCM.DeleteMultiple +- Text.UpdateSubmodules.Recursive - Text.UpdateSubmodules.UpdateToRemoteTrackingBranch - Text.ViewLogs - Text.ViewLogs.Clear diff --git a/VERSION b/VERSION index b3d745254..1cc437020 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2026.11 \ No newline at end of file +2026.13 \ No newline at end of file diff --git a/build/resources/_common/applications/sourcegit.desktop b/build/resources/_common/applications/sourcegit.desktop index bcf9c813c..966b1d65f 100644 --- a/build/resources/_common/applications/sourcegit.desktop +++ b/build/resources/_common/applications/sourcegit.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Name=SourceGit Comment=Open-source & Free Git GUI Client -Exec=/opt/sourcegit/sourcegit +Exec=/opt/sourcegit/sourcegit %u Icon=/usr/share/icons/sourcegit.png Terminal=false Type=Application diff --git a/depends/AvaloniaEdit b/depends/AvaloniaEdit index 1e6f595ff..988266523 160000 --- a/depends/AvaloniaEdit +++ b/depends/AvaloniaEdit @@ -1 +1 @@ -Subproject commit 1e6f595ff0da0dc20637322cbab9531892c12cbc +Subproject commit 988266523608381a9af83f4d67508bb2e26d85f5 diff --git a/screenshots/theme_dark.png b/screenshots/theme_dark.png index 6e8af07b3..6ecde949b 100644 Binary files a/screenshots/theme_dark.png and b/screenshots/theme_dark.png differ diff --git a/screenshots/theme_light.png b/screenshots/theme_light.png index 10988efdb..205e38d6b 100644 Binary files a/screenshots/theme_light.png and b/screenshots/theme_light.png differ diff --git a/src/AI/Agent.cs b/src/AI/Agent.cs index fd857ef58..e1b102724 100644 --- a/src/AI/Agent.cs +++ b/src/AI/Agent.cs @@ -50,10 +50,11 @@ public async Task GenerateCommitMessageAsync(string repo, string changeList, Act var text = completion.Content[0].Text.ReplaceLineEndings("\n").Trim(); var start = 0; var len = text.Length; - if (text.StartsWith("```\n", StringComparison.Ordinal)) + if (text.StartsWith("```", StringComparison.Ordinal)) { - start += 4; - len -= 4; + var idx = text.IndexOf('\n') + 1; + start += idx; + len -= idx; } if (text.EndsWith("\n```", StringComparison.Ordinal)) @@ -82,7 +83,12 @@ public async Task GenerateCommitMessageAsync(string repo, string changeList, Act #pragma warning disable SCME0001 var hasReasoningContent = completion.Patch.TryGetValue("$.choices[0].message.reasoning_content"u8, out string reasoning); if (hasReasoningContent) - message.Patch.Set("$.reasoning_content"u8, reasoning); + { + if (string.IsNullOrEmpty(reasoning)) + message.Patch.Set("$.reasoning_content"u8, BinaryData.FromString("\"\"")); + else + message.Patch.Set("$.reasoning_content"u8, reasoning); + } #pragma warning restore SCME0001 messages.Add(message); diff --git a/src/App.Commands.cs b/src/App.Commands.cs index daa930b76..06c0afbf1 100644 --- a/src/App.Commands.cs +++ b/src/App.Commands.cs @@ -81,17 +81,20 @@ public static bool IsCheckForUpdateCommandVisible public static readonly Command HideAppCommand = new Command(_ => { - Native.OS.HideSelf(); + if (OperatingSystem.IsMacOS()) + Native.MacOSUtilities.HideSelf(); }); public static readonly Command HideOtherApplicationsCommand = new Command(_ => { - Native.OS.HideOtherApplications(); + if (OperatingSystem.IsMacOS()) + Native.MacOSUtilities.HideOtherApplications(); }); public static readonly Command ShowAllApplicationsCommand = new Command(_ => { - Native.OS.ShowAllApplications(); + if (OperatingSystem.IsMacOS()) + Native.MacOSUtilities.ShowAllApplications(); }); } } diff --git a/src/App.JsonCodeGen.cs b/src/App.JsonCodeGen.cs index 43dcdde14..8eef67ae7 100644 --- a/src/App.JsonCodeGen.cs +++ b/src/App.JsonCodeGen.cs @@ -51,20 +51,6 @@ public override void Write(Utf8JsonWriter writer, GridLength value, JsonSerializ } } - public class DataGridLengthConverter : JsonConverter - { - public override DataGridLength Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var size = reader.GetDouble(); - return new DataGridLength(size, DataGridLengthUnitType.Pixel, 0, size); - } - - public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value.DisplayValue); - } - } - [JsonSourceGenerationOptions( WriteIndented = true, IgnoreReadOnlyFields = true, @@ -73,7 +59,6 @@ public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSeri typeof(DateTimeConverter), typeof(ColorConverter), typeof(GridLengthConverter), - typeof(DataGridLengthConverter), ] )] [JsonSerializable(typeof(Models.ExternalToolCustomization))] @@ -87,5 +72,6 @@ public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSeri [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(ViewModels.Preferences))] + [JsonSerializable(typeof(ViewModels.RepositoryNodeMinimalInfo))] internal partial class JsonCodeGen : JsonSerializerContext { } } diff --git a/src/App.axaml b/src/App.axaml index 2fa982635..bfc05cfb4 100644 --- a/src/App.axaml +++ b/src/App.axaml @@ -12,8 +12,10 @@ + + diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 7e7dc8312..89096e7a3 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -7,7 +7,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.Media.Fonts; @@ -187,7 +186,7 @@ public static void SetFonts(string defaultFont, string monospaceFont) { if (!string.IsNullOrEmpty(defaultFont)) { - monospaceFont = $"fonts:SourceGit#JetBrains Mono,{defaultFont}"; + monospaceFont = $"fonts:SourceGit#JetBrains Mono NL,{defaultFont}"; resDic.Add("Fonts.Monospace", FontFamily.Parse(monospaceFont)); } } @@ -247,8 +246,6 @@ public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - BindingPlugins.DataValidators.RemoveAt(0); - // Disable tooltip if window is not active. ToolTip.ToolTipOpeningEvent.AddClassHandler((c, e) => { @@ -355,7 +352,7 @@ private bool TryLaunchAsFileHistoryViewer(IClassicDesktopStyleApplicationLifetim Models.AvatarManager.Instance.Start(); var repo = test.StdOut.Trim(); - var relativePath = Path.GetRelativePath(repo, fullPath); + var relativePath = Path.GetRelativePath(repo, fullPath).Replace('\\', '/'); if (File.Exists(fullPath)) { desktop.MainWindow = new Views.FileHistories() @@ -367,7 +364,7 @@ private bool TryLaunchAsFileHistoryViewer(IClassicDesktopStyleApplicationLifetim { desktop.MainWindow = new Views.DirHistories() { - DataContext = new ViewModels.DirHistories(repo, relativePath.TrimEnd('/', '\\')) + DataContext = new ViewModels.DirHistories(repo, relativePath.TrimEnd('/')) }; } else diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 2c453b9a1..94c7d84fa 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -172,7 +172,7 @@ protected ProcessStartInfo CreateGitStartInfo(bool redirect) } // Force using this app as SSH askpass program - var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName; + var selfExecFile = Environment.ProcessPath; 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"); diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs index 4840d14e6..a7b80c14d 100644 --- a/src/Commands/Diff.cs +++ b/src/Commands/Diff.cs @@ -20,7 +20,7 @@ public partial class Diff : Command private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/"; private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/"; - public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespace) + public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespace, bool ignoreCRAtEOL) { _result.TextDiff = new Models.TextDiff(); @@ -28,11 +28,11 @@ public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespa Context = repo; var builder = new StringBuilder(256); - builder.Append("diff --no-color --no-ext-diff --patch "); - if (Models.DiffOption.IgnoreCRAtEOL) - builder.Append("--ignore-cr-at-eol "); + builder.Append("diff --no-color --no-ext-diff --full-index --patch "); if (ignoreWhitespace) builder.Append("--ignore-space-change "); + if (ignoreCRAtEOL) + builder.Append("--ignore-cr-at-eol "); builder.Append("--unified=").Append(unified).Append(' '); builder.Append(opt.ToString()); @@ -83,6 +83,10 @@ public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespa { ProcessInlineHighlights(); _result.TextDiff.MaxLineNumber = Math.Max(_newLine, _oldLine); + _result.TextDiff.OldMode = _result.OldMode; + _result.TextDiff.NewMode = _result.NewMode; + _result.TextDiff.OldHash = _result.OldHash; + _result.TextDiff.NewHash = _result.NewHash; } return _result; @@ -91,14 +95,11 @@ public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespa private void ParseLine(byte[] lineBytes) { var line = Encoding.UTF8.GetString(lineBytes); - if (ParseFileModeChange(line)) - return; - - if (ParseLFSChange(line)) - return; - if (_result.TextDiff.Lines.Count == 0) { + if (ParseFileModeChange(line)) + return; + if (line.StartsWith("Binary", StringComparison.Ordinal)) { _result.IsBinary = true; @@ -128,6 +129,9 @@ private void ParseLine(byte[] lineBytes) } else { + if (ParseLFSChange(line)) + return; + if (line.Length == 0) { ProcessInlineHighlights(); diff --git a/src/Commands/MergeBase.cs b/src/Commands/MergeBase.cs new file mode 100644 index 000000000..2e349a84b --- /dev/null +++ b/src/Commands/MergeBase.cs @@ -0,0 +1,32 @@ +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SourceGit.Commands +{ + public partial class MergeBase : Command + { + [GeneratedRegex(@"^[0-9a-f]{8,64}$")] + private static partial Regex REG_HEX(); + + public MergeBase(string repo, string rev1, string rev2) + { + WorkingDirectory = repo; + Context = repo; + RaiseError = false; + Args = $"merge-base {rev1} {rev2}"; + } + + public async Task GetResultAsync() + { + var rs = await ReadToEndAsync().ConfigureAwait(false); + if (!rs.IsSuccess) + return string.Empty; + + var trimmed = rs.StdOut.Trim(); + if (REG_HEX().IsMatch(trimmed)) + return trimmed; + + return string.Empty; + } + } +} diff --git a/src/Commands/MergeTree.cs b/src/Commands/MergeTree.cs new file mode 100644 index 000000000..41e9ea28a --- /dev/null +++ b/src/Commands/MergeTree.cs @@ -0,0 +1,34 @@ +using System.Diagnostics; +using System.Threading.Tasks; + +namespace SourceGit.Commands +{ + public class MergeTree : Command + { + public MergeTree(string repo, string source, string dest) + { + WorkingDirectory = repo; + Args = $"merge-tree --write-tree {source} {dest}"; + } + + public async Task GetExitCodeAsync() + { + using var proc = new Process(); + proc.StartInfo = CreateGitStartInfo(false); + + var exitCode = -1; + try + { + proc.Start(); + await proc.WaitForExitAsync().ConfigureAwait(false); + exitCode = proc.ExitCode; + } + catch + { + // Ignore any exceptions and just return -1 + } + + return exitCode; + } + } +} diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 0005abd6e..64a713764 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -80,7 +80,8 @@ public QueryCommits(string repo, string filter, Models.CommitSearchMethod method commit.Subject = parts[7]; commits.Add(commit); - findHead |= commit.IsMerged; + if (!findHead && commit.IsMerged) + findHead = true; } await proc.WaitForExitAsync().ConfigureAwait(false); diff --git a/src/Commands/QueryCurrentBranchCommitHashes.cs b/src/Commands/QueryCurrentBranchCommitHashes.cs index a795e1f54..393160602 100644 --- a/src/Commands/QueryCurrentBranchCommitHashes.cs +++ b/src/Commands/QueryCurrentBranchCommitHashes.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; @@ -9,10 +8,9 @@ public class QueryCurrentBranchCommitHashes : Command { public QueryCurrentBranchCommitHashes(string repo, ulong sinceTimestamp) { - var since = DateTime.UnixEpoch.AddSeconds(sinceTimestamp).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); WorkingDirectory = repo; Context = repo; - Args = $"log --since={since.Quoted()} --format=%H"; + Args = $"log --since=@{sinceTimestamp} --format=%H"; } public async Task> GetResultAsync() diff --git a/src/Commands/QueryStagedFileBlobGuid.cs b/src/Commands/QueryStagedFileBlobGuid.cs deleted file mode 100644 index 54ecd2ac7..000000000 --- a/src/Commands/QueryStagedFileBlobGuid.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace SourceGit.Commands -{ - public partial class QueryStagedFileBlobGuid : Command - { - [GeneratedRegex(@"^\d+\s+([0-9a-f]+)\s+.*$")] - private static partial Regex REG_FORMAT(); - - public QueryStagedFileBlobGuid(string repo, string file) - { - WorkingDirectory = repo; - Context = repo; - Args = $"ls-files -s -- {file.Quoted()}"; - } - - public async Task GetResultAsync() - { - var rs = await ReadToEndAsync().ConfigureAwait(false); - var match = REG_FORMAT().Match(rs.StdOut.Trim()); - return match.Success ? match.Groups[1].Value : string.Empty; - } - } -} diff --git a/src/Commands/Replay.cs b/src/Commands/Replay.cs new file mode 100644 index 000000000..3f2546224 --- /dev/null +++ b/src/Commands/Replay.cs @@ -0,0 +1,36 @@ +using System.Diagnostics; +using System.Threading.Tasks; + +namespace SourceGit.Commands +{ + public class Replay : Command + { + public Replay(string repo, string onto, string range) + { + WorkingDirectory = repo; + Context = repo; + RaiseError = false; + Args = $"replay --onto {onto} {range}"; + } + + public async Task GetExitCodeAsync() + { + using var proc = new Process(); + proc.StartInfo = CreateGitStartInfo(false); + + var exitCode = -1; + try + { + proc.Start(); + await proc.WaitForExitAsync().ConfigureAwait(false); + exitCode = proc.ExitCode; + } + catch + { + // Ignore any exceptions and just return -1 + } + + return exitCode; + } + } +} diff --git a/src/Commands/Submodule.cs b/src/Commands/Submodule.cs index 728296ce3..d8b1dbcb7 100644 --- a/src/Commands/Submodule.cs +++ b/src/Commands/Submodule.cs @@ -43,13 +43,15 @@ public async Task SetBranchAsync(string path, string branch) return await ExecAsync().ConfigureAwait(false); } - public async Task UpdateAsync(List modules, bool init = false, bool useRemote = false) + public async Task UpdateAsync(List modules, bool init, bool recursive, bool useRemote) { var builder = new StringBuilder(); - builder.Append("submodule update --recursive"); + builder.Append("submodule update"); if (init) builder.Append(" --init"); + if (recursive) + builder.Append(" --recursive"); if (useRemote) builder.Append(" --remote"); if (modules.Count > 0) diff --git a/src/Models/Bisect.cs b/src/Models/Bisect.cs index 2ed8beb25..286a02c4f 100644 --- a/src/Models/Bisect.cs +++ b/src/Models/Bisect.cs @@ -6,16 +6,19 @@ namespace SourceGit.Models public enum BisectState { None = 0, - WaitingForRange, - Detecting, + WaitingForFirstBad, + WaitingForCheckoutAnother, + WaitingForFirstGood, + WaitingForMark, } [Flags] public enum BisectCommitFlag { None = 0, - Good = 1 << 0, - Bad = 1 << 1, + Good, + Bad, + Skipped, } public class Bisect @@ -31,5 +34,11 @@ public HashSet Goods get; set; } = []; + + public HashSet Skipped + { + get; + set; + } = []; } } diff --git a/src/Models/CommitGraph.cs b/src/Models/CommitGraph.cs index ca865a54e..8557f271d 100644 --- a/src/Models/CommitGraph.cs +++ b/src/Models/CommitGraph.cs @@ -70,7 +70,7 @@ public class Dot public List Links { get; } = []; public List Dots { get; } = []; - public static CommitGraph Generate(List commits, bool firstParentOnlyEnabled, CommitGraphHighlighting highlighting, HashSet highlightExtraCommits) + public static CommitGraph Generate(List commits, bool recalculateMergeState, bool firstParentOnlyEnabled, CommitGraphHighlighting highlighting, HashSet highlightExtraCommits) { const double unitWidth = 12; const double halfWidth = 6; @@ -89,53 +89,21 @@ public static CommitGraph Generate(List commits, bool firstParentOnlyEna PathHelper major = null; // Update merge state of this commit. - if (commit.IsMerged) - { - merged.Remove(commit.SHA); - foreach (var p in commit.Parents) - merged.Add(p); - } - else if (merged.Remove(commit.SHA)) - { - commit.IsMerged = true; - foreach (var p in commit.Parents) - merged.Add(p); - } - - // Calculate highlighted state - var isHighlighted = false; - if (highlighting == CommitGraphHighlighting.All) - { - isHighlighted = true; - } - else if (highlighting == CommitGraphHighlighting.CurrentBranchOnly) - { - isHighlighted = commit.IsMerged; - } - else if (highlighting == CommitGraphHighlighting.SelectedCommitsOnly) - { - isHighlighted = highlightExtraCommits.Remove(commit.SHA); - if (isHighlighted) - { - commit.IsHighlightedInGraph = true; - foreach (var p in commit.Parents) - highlightExtraCommits.Add(p); - } - } - else + if (recalculateMergeState) { if (commit.IsMerged) { - isHighlighted = true; + merged.Remove(commit.SHA); + foreach (var p in commit.Parents) + merged.Add(p); } - else if (highlightExtraCommits.Remove(commit.SHA)) + else if (merged.Remove(commit.SHA)) { - isHighlighted = true; + commit.IsMerged = true; foreach (var p in commit.Parents) - highlightExtraCommits.Add(p); + merged.Add(p); } } - commit.IsHighlightedInGraph = isHighlighted; // Update current y offset offsetY += unitHeight; @@ -143,6 +111,7 @@ public static CommitGraph Generate(List commits, bool firstParentOnlyEna // Find first curves that links to this commit and marks others that links to this commit ended. var offsetX = 4 - halfWidth; var maxOffsetOld = unsolved.Count > 0 ? unsolved[^1].LastX : offsetX + unitWidth; + var isHighlighted = false; foreach (var l in unsolved) { if (l.Next.Equals(commit.SHA, StringComparison.Ordinal)) @@ -151,6 +120,7 @@ public static CommitGraph Generate(List commits, bool firstParentOnlyEna { offsetX += unitWidth; major = l; + isHighlighted = major.IsHighlighted; if (commit.Parents.Count > 0) { @@ -167,6 +137,9 @@ public static CommitGraph Generate(List commits, bool firstParentOnlyEna { l.End(major.LastX, offsetY, halfHeight); ended.Add(l); + + if (!isHighlighted && l.IsHighlighted) + isHighlighted = true; } } else @@ -184,6 +157,42 @@ public static CommitGraph Generate(List commits, bool firstParentOnlyEna } ended.Clear(); + // Calculate highlighted state + if (!isHighlighted) + { + if (highlighting == CommitGraphHighlighting.All) + { + isHighlighted = true; + } + else if (highlighting == CommitGraphHighlighting.CurrentBranchOnly) + { + isHighlighted = commit.IsMerged; + } + else if (highlighting == CommitGraphHighlighting.SelectedCommitsOnly) + { + isHighlighted = highlightExtraCommits.Remove(commit.SHA); + if (isHighlighted) + { + foreach (var p in commit.Parents) + highlightExtraCommits.Add(p); + } + } + else + { + if (commit.IsMerged) + { + isHighlighted = true; + } + else if (highlightExtraCommits.Remove(commit.SHA)) + { + isHighlighted = true; + foreach (var p in commit.Parents) + highlightExtraCommits.Add(p); + } + } + } + commit.IsHighlightedInGraph = isHighlighted; + // If no path found, create new curve for branch head // Otherwise, create new curve for new merged commit if (major == null) diff --git a/src/Models/DiffOption.cs b/src/Models/DiffOption.cs index def59bedd..af64b39a4 100644 --- a/src/Models/DiffOption.cs +++ b/src/Models/DiffOption.cs @@ -6,16 +6,7 @@ namespace SourceGit.Models { public class DiffOption { - /// - /// Enable `--ignore-cr-at-eol` by default? - /// - public static bool IgnoreCRAtEOL - { - get; - set; - } = true; - - public Change WorkingCopyChange => _workingCopyChange; + public bool IsLocalChange => _revisions.Count == 0; public bool IsUnstaged => _isUnstaged; public List Revisions => _revisions; public string Path => _path; @@ -28,7 +19,6 @@ public static bool IgnoreCRAtEOL /// public DiffOption(Change change, bool isUnstaged) { - _workingCopyChange = change; _isUnstaged = isUnstaged; _path = change.Path; _orgPath = change.OriginalPath; @@ -66,18 +56,6 @@ public DiffOption(Commit commit, Change change) _orgPath = change.OriginalPath; } - /// - /// Diff with filepath. Used by FileHistories - /// - /// - /// - public DiffOption(Commit commit, string file) - { - _revisions.Add(commit.FirstParentToCompare); - _revisions.Add(commit.SHA); - _path = file; - } - /// /// Used to diff in `FileHistory` /// @@ -171,7 +149,6 @@ public override string ToString() return builder.ToString(); } - private readonly Change _workingCopyChange = null; private readonly bool _isUnstaged = false; private readonly string _path; private readonly string _orgPath = string.Empty; diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs index 27a8ff093..13d15f66e 100644 --- a/src/Models/DiffResult.cs +++ b/src/Models/DiffResult.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Text.RegularExpressions; using Avalonia.Media.Imaging; namespace SourceGit.Models @@ -44,536 +43,16 @@ public TextDiffLine(TextDiffLineType type, string line, byte[] rawContent, int o } } - public class TextDiffSelection - { - public int StartLine { get; set; } = 0; - public int EndLine { get; set; } = 0; - public bool HasChanges { get; set; } = false; - public int IgnoredAdds { get; set; } = 0; - public int IgnoredDeletes { get; set; } = 0; - } - public partial class TextDiff { public List Lines { get; set; } = new List(); public int MaxLineNumber = 0; public int AddedLines { get; set; } = 0; public int DeletedLines { get; set; } = 0; - - public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombined, bool isOldSide) - { - var rs = new TextDiffSelection(); - rs.StartLine = startLine; - rs.EndLine = endLine; - - for (int i = 0; i < startLine - 1; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Added) - rs.IgnoredAdds++; - else if (line.Type == TextDiffLineType.Deleted) - rs.IgnoredDeletes++; - } - - for (int i = startLine - 1; i < endLine; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Added) - { - if (isCombined || !isOldSide) - { - rs.HasChanges = true; - break; - } - } - else if (line.Type == TextDiffLineType.Deleted) - { - if (isCombined || isOldSide) - { - rs.HasChanges = true; - break; - } - } - } - - return rs; - } - - public void GenerateNewPatchFromSelection(string file, string fileBlobGuid, TextDiffSelection selection, bool revert, string output) - { - var isTracked = !string.IsNullOrEmpty(fileBlobGuid); - var fileGuid = isTracked ? fileBlobGuid : "00000000"; - - using var writer = new StreamWriter(output); - writer.NewLine = "\n"; - writer.WriteLine($"diff --git a/{file} b/{file}"); - if (!revert && !isTracked) - writer.WriteLine("new file mode 100644"); - writer.WriteLine($"index 00000000...{fileGuid}"); - writer.WriteLine($"--- {(revert || isTracked ? $"a/{file}" : "/dev/null")}"); - writer.WriteLine($"+++ b/{file}"); - - var additions = selection.EndLine - selection.StartLine; - if (selection.StartLine != 1) - additions++; - - if (revert) - { - var totalLines = Lines.Count - 1; - writer.WriteLine($"@@ -0,{totalLines - additions} +0,{totalLines} @@"); - for (int i = 1; i <= totalLines; i++) - { - var line = Lines[i]; - if (line.Type != TextDiffLineType.Added) - continue; - - if (i >= selection.StartLine - 1 && i < selection.EndLine) - WriteLine(writer, '+', line); - else - WriteLine(writer, ' ', line); - } - } - else - { - writer.WriteLine($"@@ -0,0 +0,{additions} @@"); - for (int i = selection.StartLine - 1; i < selection.EndLine; i++) - { - var line = Lines[i]; - if (line.Type != TextDiffLineType.Added) - continue; - WriteLine(writer, '+', line); - } - } - - writer.Flush(); - } - - public void GeneratePatchFromSelection(string file, string fileTreeGuid, TextDiffSelection selection, bool revert, string output) - { - using var writer = new StreamWriter(output); - writer.NewLine = "\n"; - writer.WriteLine($"diff --git a/{file} b/{file}"); - writer.WriteLine($"index 00000000...{fileTreeGuid} 100644"); - writer.WriteLine($"--- a/{file}"); - writer.WriteLine($"+++ b/{file}"); - - // If last line of selection is a change. Find one more line. - TextDiffLine tail = null; - if (selection.EndLine < Lines.Count) - { - var lastLine = Lines[selection.EndLine - 1]; - if (lastLine.Type == TextDiffLineType.Added || lastLine.Type == TextDiffLineType.Deleted) - { - for (int i = selection.EndLine; i < Lines.Count; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - break; - if (line.Type == TextDiffLineType.Normal || - (revert && line.Type == TextDiffLineType.Added) || - (!revert && line.Type == TextDiffLineType.Deleted)) - { - tail = line; - break; - } - } - } - } - - // If the first line is not indicator. - if (Lines[selection.StartLine - 1].Type != TextDiffLineType.Indicator) - { - var indicator = selection.StartLine - 1; - for (int i = selection.StartLine - 2; i >= 0; i--) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - indicator = i; - break; - } - } - - var ignoreAdds = 0; - var ignoreRemoves = 0; - for (int i = 0; i < indicator; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Added) - { - ignoreAdds++; - } - else if (line.Type == TextDiffLineType.Deleted) - { - ignoreRemoves++; - } - } - - for (int i = indicator; i < selection.StartLine - 1; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - ProcessIndicatorForPatch(writer, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, tail != null); - } - else if (line.Type == TextDiffLineType.Added) - { - if (revert) - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Deleted) - { - if (!revert) - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Normal) - { - WriteLine(writer, ' ', line); - } - } - } - - // Outputs the selected lines. - for (int i = selection.StartLine - 1; i < selection.EndLine; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - if (!ProcessIndicatorForPatch(writer, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, tail != null)) - break; - } - else if (line.Type == TextDiffLineType.Normal) - { - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Added) - { - WriteLine(writer, '+', line); - } - else if (line.Type == TextDiffLineType.Deleted) - { - WriteLine(writer, '-', line); - } - } - - if (tail != null) - WriteLine(writer, ' ', tail); - writer.Flush(); - } - - public void GeneratePatchFromSelectionSingleSide(string file, string fileTreeGuid, TextDiffSelection selection, bool revert, bool isOldSide, string output) - { - using var writer = new StreamWriter(output); - writer.NewLine = "\n"; - writer.WriteLine($"diff --git a/{file} b/{file}"); - writer.WriteLine($"index 00000000...{fileTreeGuid} 100644"); - writer.WriteLine($"--- a/{file}"); - writer.WriteLine($"+++ b/{file}"); - - // If last line of selection is a change. Find one more line. - TextDiffLine tail = null; - if (selection.EndLine < Lines.Count) - { - var lastLine = Lines[selection.EndLine - 1]; - if (lastLine.Type == TextDiffLineType.Added || lastLine.Type == TextDiffLineType.Deleted) - { - for (int i = selection.EndLine; i < Lines.Count; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - break; - if (revert) - { - if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added) - { - tail = line; - break; - } - } - else - { - if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Deleted) - { - tail = line; - break; - } - } - } - } - } - - // If the first line is not indicator. - if (Lines[selection.StartLine - 1].Type != TextDiffLineType.Indicator) - { - var indicator = selection.StartLine - 1; - for (int i = selection.StartLine - 2; i >= 0; i--) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - indicator = i; - break; - } - } - - var ignoreAdds = 0; - var ignoreRemoves = 0; - for (int i = 0; i < indicator; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Added) - { - ignoreAdds++; - } - else if (line.Type == TextDiffLineType.Deleted) - { - ignoreRemoves++; - } - } - - for (int i = indicator; i < selection.StartLine - 1; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - ProcessIndicatorForPatchSingleSide(writer, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, isOldSide, tail != null); - } - else if (line.Type == TextDiffLineType.Added) - { - if (revert) - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Deleted) - { - if (!revert) - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Normal) - { - WriteLine(writer, ' ', line); - } - } - } - - // Outputs the selected lines. - for (int i = selection.StartLine - 1; i < selection.EndLine; i++) - { - var line = Lines[i]; - if (line.Type == TextDiffLineType.Indicator) - { - if (!ProcessIndicatorForPatchSingleSide(writer, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, isOldSide, tail != null)) - break; - } - else if (line.Type == TextDiffLineType.Normal) - { - WriteLine(writer, ' ', line); - } - else if (line.Type == TextDiffLineType.Added) - { - if (isOldSide) - { - if (revert) - { - WriteLine(writer, ' ', line); - } - else - { - selection.IgnoredAdds++; - } - } - else - { - WriteLine(writer, '+', line); - } - } - else if (line.Type == TextDiffLineType.Deleted) - { - if (isOldSide) - { - WriteLine(writer, '-', line); - } - else - { - if (!revert) - { - WriteLine(writer, ' ', line); - } - else - { - selection.IgnoredDeletes++; - } - } - } - } - - if (tail != null) - WriteLine(writer, ' ', tail); - writer.Flush(); - } - - private bool ProcessIndicatorForPatch(StreamWriter writer, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed) - { - var match = REG_INDICATOR().Match(indicator.Content); - var oldStart = int.Parse(match.Groups[1].Value); - var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; - var oldCount = 0; - var newCount = 0; - for (int i = idx + 1; i < end; i++) - { - var test = Lines[i]; - if (test.Type == TextDiffLineType.Indicator) - break; - - if (test.Type == TextDiffLineType.Normal) - { - oldCount++; - newCount++; - } - else if (test.Type == TextDiffLineType.Added) - { - if (i < start - 1) - { - if (revert) - { - newCount++; - oldCount++; - } - } - else - { - newCount++; - } - - if (i == end - 1 && tailed) - { - newCount++; - oldCount++; - } - } - else if (test.Type == TextDiffLineType.Deleted) - { - if (i < start - 1) - { - if (!revert) - { - newCount++; - oldCount++; - } - } - else - { - oldCount++; - } - - if (i == end - 1 && tailed) - { - newCount++; - oldCount++; - } - } - } - - if (oldCount == 0 && newCount == 0) - return false; - - writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); - return true; - } - - private bool ProcessIndicatorForPatchSingleSide(StreamWriter writer, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool isOldSide, bool tailed) - { - var match = REG_INDICATOR().Match(indicator.Content); - var oldStart = int.Parse(match.Groups[1].Value); - var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; - var oldCount = 0; - var newCount = 0; - for (int i = idx + 1; i < end; i++) - { - var test = Lines[i]; - if (test.Type == TextDiffLineType.Indicator) - break; - - if (test.Type == TextDiffLineType.Normal) - { - oldCount++; - newCount++; - } - else if (test.Type == TextDiffLineType.Added) - { - if (i < start - 1 || isOldSide) - { - if (revert) - { - newCount++; - oldCount++; - } - } - else - { - newCount++; - } - - if (i == end - 1 && tailed) - { - newCount++; - oldCount++; - } - } - else if (test.Type == TextDiffLineType.Deleted) - { - if (i < start - 1) - { - if (!revert) - { - newCount++; - oldCount++; - } - } - else - { - if (isOldSide) - { - oldCount++; - } - else - { - if (!revert) - { - newCount++; - oldCount++; - } - } - } - - if (i == end - 1 && tailed) - { - newCount++; - oldCount++; - } - } - } - - if (oldCount == 0 && newCount == 0) - return false; - - writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); - return true; - } - - private static void WriteLine(StreamWriter writer, char prefix, TextDiffLine line) - { - writer.Flush(); - - writer.BaseStream.WriteByte((byte)prefix); - writer.BaseStream.Write(line.RawContent); - writer.BaseStream.WriteByte((byte)'\n'); - - if (line.NoNewLineEndOfFile) - writer.WriteLine("\\ No newline at end of file"); - } - - [GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")] - private static partial Regex REG_INDICATOR(); + public string OldMode { get; set; } = string.Empty; + public string NewMode { get; set; } = string.Empty; + public string OldHash { get; set; } = string.Empty; + public string NewHash { get; set; } = string.Empty; } public class LFSDiff @@ -600,6 +79,12 @@ public class ImageDiff public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0"; } + public class EmptyFile + { + public const string SHA1 = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"; + public const string SHA256 = "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"; + } + public class NoOrEOLChange; public class SubmoduleDiff diff --git a/src/Models/GitIgnoreFile.cs b/src/Models/GitIgnoreFile.cs index a23456b67..2f3540e8b 100644 --- a/src/Models/GitIgnoreFile.cs +++ b/src/Models/GitIgnoreFile.cs @@ -1,26 +1,36 @@ -using System.Collections.Generic; -using System.IO; -using Avalonia.Media; +using System; +using System.Collections.Generic; namespace SourceGit.Models { - public class GitIgnoreFile + public record GitIgnoreFile(string DisplayName, string FullPath, string Pattern, bool IsLocalOnly) { - public static readonly List Supported = [new(true), new(false)]; + public static List GetSupported(string repo, string gitDir, string pattern) + { + var supported = new List(); - public bool IsShared { get; set; } - public string File => IsShared ? ".gitignore" : "/info/exclude"; - public string Desc => IsShared ? "Shared" : "Private"; - public IBrush Brush => IsShared ? Brushes.Green : Brushes.Gray; + // .gitignore in repository root. + supported.Add(new(".gitignore", $"{repo}/.gitignore", pattern, false)); - public GitIgnoreFile(bool isShared) - { - IsShared = isShared; - } + // If pattern points to a file/directory that in sub-directory of repository, we should also support .gitignore in that sub-directory. + var normalizedPattern = pattern.Replace('\\', '/').TrimEnd('/'); + var lastDirIdx = normalizedPattern.LastIndexOf('/'); + if (lastDirIdx > 0) + { + var parentDir = normalizedPattern.Substring(0, lastDirIdx); + var overridedPattern = normalizedPattern.Substring(lastDirIdx + 1); + supported.Add(new($"{parentDir}/.gitignore", $"{repo}/{parentDir}/.gitignore", overridedPattern, false)); + } - public string GetFullPath(string repoPath, string gitDir) - { - return IsShared ? Path.Combine(repoPath, ".gitignore") : Path.Combine(gitDir, "info", "exclude"); + // .git/info/exclude in git directory. + var normalizedGitDir = gitDir.Replace('\\', '/'); + var testGitDir = $"{repo}/.git".Replace('\\', '/'); + if (normalizedGitDir.Equals(testGitDir, StringComparison.Ordinal)) + supported.Add(new(".git/info/exclude", $"{normalizedGitDir}/info/exclude", pattern, true)); + else + supported.Add(new(".git/info/exclude", $"{gitDir}/info/exclude", pattern, true)); + + return supported; } } } diff --git a/src/Models/GitVersions.cs b/src/Models/GitVersions.cs index 8aae63a3b..71fb4657e 100644 --- a/src/Models/GitVersions.cs +++ b/src/Models/GitVersions.cs @@ -16,5 +16,15 @@ public static class GitVersions /// The minimal version of Git that supports the `stash push` command with the `--staged` option. /// public static readonly System.Version STASH_PUSH_ONLY_STAGED = new(2, 35, 0); + + /// + /// The minimal version of Git that supports the `git merge-tree --write-tree` command, which is used for testing merge results without actually performing a merge. + /// + public static readonly System.Version TESTING_MERGE = new(2, 38, 0); + + /// + /// The minimal version of Git that supports the `git replay` command. + /// + public static readonly System.Version REPLAY = new(2, 44, 0); } } diff --git a/src/Models/Locales.cs b/src/Models/Locales.cs index 027433336..5bdb2431b 100644 --- a/src/Models/Locales.cs +++ b/src/Models/Locales.cs @@ -9,9 +9,11 @@ public class Locale public static readonly List Supported = new List() { new Locale("Deutsch", "de_DE"), + new Locale("Ελληνικά", "el_GR"), new Locale("English", "en_US"), new Locale("Español", "es_ES"), new Locale("Français", "fr_FR"), + new Locale("עברית", "he_IL"), new Locale("Bahasa Indonesia", "id_ID"), new Locale("Italiano", "it_IT"), new Locale("Português (Brasil)", "pt_BR"), diff --git a/src/Models/PatchGenerator.cs b/src/Models/PatchGenerator.cs new file mode 100644 index 000000000..f362353cf --- /dev/null +++ b/src/Models/PatchGenerator.cs @@ -0,0 +1,511 @@ +using System.IO; +using System.Text.RegularExpressions; + +namespace SourceGit.Models +{ + public partial class PatchGenerator + { + [GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")] + private static partial Regex REG_INDICATOR(); + + public bool IsValid => _selection != null; + + public PatchGenerator(DiffOption option, TextDiff diff, int startLine, int endLine, bool isCombined, bool isOldSide) + { + _targetFile = option.Path; + _diff = diff; + _isCombined = isCombined; + _isOldSide = isOldSide; + + var lines = _diff.Lines; + var hasChanges = false; + + var selection = new Selection(); + selection.StartLine = startLine; + selection.EndLine = endLine; + + for (int i = 0; i < startLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Added) + selection.IgnoredAdds++; + else if (line.Type == TextDiffLineType.Deleted) + selection.IgnoredDeletes++; + } + + for (int i = startLine; i <= endLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Added) + { + if (isCombined || !isOldSide) + { + hasChanges = true; + break; + } + } + else if (line.Type == TextDiffLineType.Deleted) + { + if (isCombined || isOldSide) + { + hasChanges = true; + break; + } + } + } + + if (hasChanges) + _selection = selection; + } + + public void Generate(string saveTo, bool revert) + { + if (_selection == null) + return; + + using var writer = CreateWriter(saveTo, revert); + + if (_isCombined) + GenerateCombined(writer, revert); + else + GenerateForSingleSide(writer, revert); + } + + private void GenerateCombined(StreamWriter writer, bool revert) + { + var lines = _diff.Lines; + var tail = FindTail(revert); + + // If the first line is not indicator. + if (lines[_selection.StartLine].Type != TextDiffLineType.Indicator) + { + var indicator = _selection.StartLine; + for (int i = _selection.StartLine - 1; i >= 0; i--) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + indicator = i; + break; + } + } + + var ignoreAdds = 0; + var ignoreRemoves = 0; + for (int i = 0; i < indicator; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Added) + { + ignoreAdds++; + } + else if (line.Type == TextDiffLineType.Deleted) + { + ignoreRemoves++; + } + } + + for (int i = indicator; i < _selection.StartLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + ProcessIndicator(writer, line, i, ignoreRemoves, ignoreAdds, revert, tail != null); + } + else if (line.Type == TextDiffLineType.Added) + { + if (revert) + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Deleted) + { + if (!revert) + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Normal) + { + Append(writer, ' ', line); + } + } + } + + // Outputs the selected lines. + for (int i = _selection.StartLine; i <= _selection.EndLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + if (!ProcessIndicator(writer, line, i, _selection.IgnoredDeletes, _selection.IgnoredAdds, revert, tail != null)) + break; + } + else if (line.Type == TextDiffLineType.Normal) + { + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Added) + { + Append(writer, '+', line); + } + else if (line.Type == TextDiffLineType.Deleted) + { + Append(writer, '-', line); + } + } + + if (tail != null) + Append(writer, ' ', tail); + } + + private void GenerateForSingleSide(StreamWriter writer, bool revert) + { + var lines = _diff.Lines; + var tail = FindTail(revert); + + // If the first line is not indicator. + if (lines[_selection.StartLine].Type != TextDiffLineType.Indicator) + { + var indicator = _selection.StartLine; + for (int i = _selection.StartLine - 1; i >= 0; i--) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + indicator = i; + break; + } + } + + var ignoreAdds = 0; + var ignoreRemoves = 0; + for (int i = 0; i < indicator; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Added) + { + ignoreAdds++; + } + else if (line.Type == TextDiffLineType.Deleted) + { + ignoreRemoves++; + } + } + + for (int i = indicator; i < _selection.StartLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + ProcessIndicatorForSingleSide(writer, line, i, ignoreRemoves, ignoreAdds, revert, tail != null); + } + else if (line.Type == TextDiffLineType.Added) + { + if (revert) + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Deleted) + { + if (!revert) + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Normal) + { + Append(writer, ' ', line); + } + } + } + + // Outputs the selected lines. + for (int i = _selection.StartLine; i <= _selection.EndLine; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + { + if (!ProcessIndicatorForSingleSide(writer, line, i, _selection.IgnoredDeletes, _selection.IgnoredAdds, revert, tail != null)) + break; + } + else if (line.Type == TextDiffLineType.Normal) + { + Append(writer, ' ', line); + } + else if (line.Type == TextDiffLineType.Added) + { + if (_isOldSide) + { + if (revert) + Append(writer, ' ', line); + else + _selection.IgnoredAdds++; + } + else + { + Append(writer, '+', line); + } + } + else if (line.Type == TextDiffLineType.Deleted) + { + if (_isOldSide) + { + Append(writer, '-', line); + } + else + { + if (!revert) + Append(writer, ' ', line); + else + _selection.IgnoredDeletes++; + } + } + } + + if (tail != null) + Append(writer, ' ', tail); + } + + private StreamWriter CreateWriter(string saveTo, bool revert) + { + var writer = new StreamWriter(saveTo) { NewLine = "\n" }; + writer.WriteLine($"diff --git \"a/{_targetFile}\" \"b/{_targetFile}\""); + + if (string.IsNullOrEmpty(_diff.OldMode)) + { + if (string.IsNullOrEmpty(_diff.NewMode) || revert) + { + writer.WriteLine($"index {_diff.OldHash}..{_diff.NewHash}"); + writer.WriteLine($"--- a/{_targetFile}"); + } + else + { + writer.WriteLine($"new file mode {_diff.NewMode}"); + writer.WriteLine($"--- /dev/null"); + } + } + else if (string.IsNullOrEmpty(_diff.NewMode)) + { + writer.WriteLine($"index {_diff.OldHash}..{_diff.NewHash} {_diff.OldMode}"); + writer.WriteLine($"--- a/{_targetFile}"); + } + else + { + writer.WriteLine($"--- a/{_targetFile}"); + } + + writer.WriteLine($"+++ b/{_targetFile}"); + return writer; + } + + private TextDiffLine FindTail(bool revert) + { + var lines = _diff.Lines; + + if (_selection.EndLine < lines.Count - 1) + { + var lastLine = lines[_selection.EndLine]; + if (lastLine.Type == TextDiffLineType.Added || lastLine.Type == TextDiffLineType.Deleted) + { + for (int i = _selection.EndLine + 1; i < lines.Count; i++) + { + var line = lines[i]; + if (line.Type == TextDiffLineType.Indicator) + break; + + if (revert) + { + if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added) + return line; + } + else + { + if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Deleted) + return line; + } + } + } + } + + return null; + } + + private void Append(StreamWriter writer, char prefix, TextDiffLine line) + { + writer.Flush(); + + writer.BaseStream.WriteByte((byte)prefix); + writer.BaseStream.Write(line.RawContent); + writer.BaseStream.WriteByte((byte)'\n'); + + if (line.NoNewLineEndOfFile) + writer.WriteLine("\\ No newline at end of file"); + } + + private bool ProcessIndicator(StreamWriter writer, TextDiffLine indicator, int idx, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed) + { + var lines = _diff.Lines; + var start = _selection.StartLine; + var end = _selection.EndLine; + var match = REG_INDICATOR().Match(indicator.Content); + var oldStart = int.Parse(match.Groups[1].Value); + var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; + var oldCount = 0; + var newCount = 0; + + for (int i = idx + 1; i <= end; i++) + { + var test = lines[i]; + if (test.Type == TextDiffLineType.Indicator) + break; + + if (test.Type == TextDiffLineType.Normal) + { + oldCount++; + newCount++; + } + else if (test.Type == TextDiffLineType.Added) + { + if (i < start) + { + if (revert) + { + newCount++; + oldCount++; + } + } + else + { + newCount++; + } + + if (i == end && tailed) + { + newCount++; + oldCount++; + } + } + else if (test.Type == TextDiffLineType.Deleted) + { + if (i < start) + { + if (!revert) + { + newCount++; + oldCount++; + } + } + else + { + oldCount++; + } + + if (i == end && tailed) + { + newCount++; + oldCount++; + } + } + } + + if (oldCount == 0 && newCount == 0) + return false; + + writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); + return true; + } + + private bool ProcessIndicatorForSingleSide(StreamWriter writer, TextDiffLine indicator, int idx, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed) + { + var lines = _diff.Lines; + var start = _selection.StartLine; + var end = _selection.EndLine; + var match = REG_INDICATOR().Match(indicator.Content); + var oldStart = int.Parse(match.Groups[1].Value); + var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; + var oldCount = 0; + var newCount = 0; + + for (int i = idx + 1; i <= end; i++) + { + var test = lines[i]; + if (test.Type == TextDiffLineType.Indicator) + break; + + if (test.Type == TextDiffLineType.Normal) + { + oldCount++; + newCount++; + } + else if (test.Type == TextDiffLineType.Added) + { + if (i < start || _isOldSide) + { + if (revert) + { + newCount++; + oldCount++; + } + } + else + { + newCount++; + } + + if (i == end && tailed) + { + newCount++; + oldCount++; + } + } + else if (test.Type == TextDiffLineType.Deleted) + { + if (i < start) + { + if (!revert) + { + newCount++; + oldCount++; + } + } + else + { + if (_isOldSide) + { + oldCount++; + } + else + { + if (!revert) + { + newCount++; + oldCount++; + } + } + } + + if (i == end && tailed) + { + newCount++; + oldCount++; + } + } + } + + if (oldCount == 0 && newCount == 0) + return false; + + writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); + return true; + } + + private class Selection + { + public int StartLine { get; set; } = 0; + public int EndLine { get; set; } = 0; + public int IgnoredAdds { get; set; } = 0; + public int IgnoredDeletes { get; set; } = 0; + } + + private string _targetFile = null; + private TextDiff _diff = null; + private bool _isCombined = false; + private bool _isOldSide = false; + private Selection _selection = null; + } +} diff --git a/src/Models/RepositorySettings.cs b/src/Models/RepositorySettings.cs index 17beedb82..483874a83 100644 --- a/src/Models/RepositorySettings.cs +++ b/src/Models/RepositorySettings.cs @@ -30,6 +30,12 @@ public string ConventionalTypesOverride set; } = string.Empty; + public bool EnableRecursiveWhenAutoUpdatingSubmodules + { + get; + set; + } = true; + public bool AskBeforeAutoUpdatingSubmodules { get; diff --git a/src/Models/RepositoryUIStates.cs b/src/Models/RepositoryUIStates.cs index dd9fa1400..acc607cf2 100644 --- a/src/Models/RepositoryUIStates.cs +++ b/src/Models/RepositoryUIStates.cs @@ -27,12 +27,24 @@ public bool IsSHAColumnVisibleInHistory set; } = true; - public bool IsDateTimeColumnVisibleInHistory + public bool IsAuthorTimeColumnVisibleInHistory + { + get; + set; + } = false; + + public bool IsCommitTimeColumnVisibleInHistory { get; set; } = true; + public double AuthorColumnWidth + { + get; + set; + } = 120; + public bool EnableTopoOrderInHistory { get; @@ -376,51 +388,8 @@ public void RemoveBranchFiltersByPrefix(string pattern) HistoryFilters.Remove(filter); } - public string BuildHistoryParams() + public string BuildHistoryParams(string gitDir) { - var includedRefs = new List(); - var excludedBranches = new List(); - var excludedRemotes = new List(); - var excludedTags = new List(); - foreach (var filter in HistoryFilters) - { - if (filter.Type == FilterType.LocalBranch) - { - if (filter.Mode == FilterMode.Included) - includedRefs.Add(filter.Pattern); - else if (filter.Mode == FilterMode.Excluded) - excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\""); - } - else if (filter.Type == FilterType.LocalBranchFolder) - { - if (filter.Mode == FilterMode.Included) - includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*"); - else if (filter.Mode == FilterMode.Excluded) - excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\""); - } - else if (filter.Type == FilterType.RemoteBranch) - { - if (filter.Mode == FilterMode.Included) - includedRefs.Add(filter.Pattern); - else if (filter.Mode == FilterMode.Excluded) - excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\""); - } - else if (filter.Type == FilterType.RemoteBranchFolder) - { - if (filter.Mode == FilterMode.Included) - includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*"); - else if (filter.Mode == FilterMode.Excluded) - excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\""); - } - else if (filter.Type == FilterType.Tag) - { - if (filter.Mode == FilterMode.Included) - includedRefs.Add($"refs/tags/{filter.Pattern}"); - else if (filter.Mode == FilterMode.Excluded) - excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\""); - } - } - var builder = new StringBuilder(); if (EnableTopoOrderInHistory) @@ -437,46 +406,75 @@ public string BuildHistoryParams() if (HistoryShowFlags.HasFlag(HistoryShowFlags.SimplifyByDecoration)) builder.Append("--simplify-by-decoration "); - if (includedRefs.Count > 0) + var mode = GetHistoryFilterMode(); + if (mode == FilterMode.None) + builder.Append("--branches --remotes --tags HEAD"); + else if (mode == FilterMode.Included) + BuildHistoryParamsForIncluded(builder); + else + BuildHistoryParamsForExcluded(builder, gitDir); + + return builder.ToString(); + } + + private void BuildHistoryParamsForIncluded(StringBuilder builder) + { + foreach (var filter in HistoryFilters) { - foreach (var r in includedRefs) - { - builder.Append(r); - builder.Append(' '); - } + if (filter.Type == FilterType.LocalBranch) + builder.Append(filter.Pattern).Append(' '); + else if (filter.Type == FilterType.LocalBranchFolder) + builder.Append($"--branches={filter.Pattern.AsSpan(11)}/* "); + else if (filter.Type == FilterType.RemoteBranch) + builder.Append(filter.Pattern).Append(' '); + else if (filter.Type == FilterType.RemoteBranchFolder) + builder.Append($"--remotes={filter.Pattern.AsSpan(13)}/* "); + else if (filter.Type == FilterType.Tag) + builder.Append($"refs/tags/{filter.Pattern} "); } - else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0) + } + + private void BuildHistoryParamsForExcluded(StringBuilder builder, string gitDir) + { + var excludedBranches = new List(); + var excludedRemotes = new List(); + var excludedTags = new List(); + foreach (var filter in HistoryFilters) { - foreach (var b in excludedBranches) - { - builder.Append(b); - builder.Append(' '); - } + if (filter.Type == FilterType.LocalBranch) + excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\" "); + else if (filter.Type == FilterType.LocalBranchFolder) + excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\" "); + else if (filter.Type == FilterType.RemoteBranch) + excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\" "); + else if (filter.Type == FilterType.RemoteBranchFolder) + excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\" "); + else if (filter.Type == FilterType.Tag) + excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\" "); + } - builder.Append("--exclude=HEAD --branches "); + foreach (var b in excludedBranches) + builder.Append(b); - foreach (var r in excludedRemotes) - { - builder.Append(r); - builder.Append(' '); - } + builder.Append("--branches "); - builder.Append("--exclude=origin/HEAD --remotes "); + var isInProgress = File.Exists(Path.Combine(gitDir, "CHERRY_PICK_HEAD")) || + Directory.Exists(Path.Combine(gitDir, "rebase-merge")) || + Directory.Exists(Path.Combine(gitDir, "rebase-apply")) || + File.Exists(Path.Combine(gitDir, "REVERT_HEAD")) || + File.Exists(Path.Combine(gitDir, "MERGE_HEAD")); + if (isInProgress) + builder.Append("HEAD "); - foreach (var t in excludedTags) - { - builder.Append(t); - builder.Append(' '); - } + foreach (var r in excludedRemotes) + builder.Append(r); - builder.Append("--tags "); - } - else - { - builder.Append("--branches --remotes --tags HEAD"); - } + builder.Append("--exclude=origin/HEAD --remotes "); - return builder.ToString(); + foreach (var t in excludedTags) + builder.Append(t); + + builder.Append("--tags "); } private string _file = string.Empty; diff --git a/src/Models/Statistics.cs b/src/Models/Statistics.cs index 700c9311b..cbf881642 100644 --- a/src/Models/Statistics.cs +++ b/src/Models/Statistics.cs @@ -2,18 +2,11 @@ using System.Collections.Generic; using System.Globalization; -using LiveChartsCore; -using LiveChartsCore.Defaults; -using LiveChartsCore.SkiaSharpView; -using LiveChartsCore.SkiaSharpView.Painting; - -using SkiaSharp; - namespace SourceGit.Models { public enum StatisticsMode { - All, + All = 0, ThisMonth, ThisWeek, } @@ -24,45 +17,98 @@ public class StatisticsAuthor(User user, int count) public int Count { get; set; } = count; } + public class StatisticsSamples + { + public DateTime StartTime { get; } + public DateTime EndTime { get; } + public int Count { get; } + public int MaxValue { get; } + public bool HasSpecialUser => _user != null; + + public StatisticsSamples(StatisticsMode mode, DateTime start, DateTime end, Dictionary all, int maxValue) + { + _mode = mode; + _all = all; + + StartTime = start; + EndTime = end; + + if (maxValue < 8) + MaxValue = 8; + else if (maxValue < 16) + MaxValue = 16; + else + MaxValue = (int)(Math.Floor(maxValue / 6.0) * 8.0); + + Count = mode switch + { + StatisticsMode.All => (end.Year - start.Year) * 12 + (end.Month - start.Month) + 1, + _ => all.Count, + }; + } + + public void WithUser(Dictionary user) + { + _user = user; + } + + public (string, int, int) GetSample(DateTime time) + { + var label = _mode switch + { + StatisticsMode.All => time.ToString("yyyy/MM"), + StatisticsMode.ThisMonth => time.ToString("MM/dd"), + _ => s_weekdays[(int)time.DayOfWeek] + }; + + var total = _all.GetValueOrDefault(time, 0); + var user = _user?.GetValueOrDefault(time, 0) ?? 0; + return (label, total, user); + } + + public DateTime NextSampleTime(DateTime time) + { + if (_mode != StatisticsMode.All) + return time.AddDays(-1); + + if (time.Month == 1) + return new DateTime(time.Year - 1, 12, 1).ToLocalTime().Date; + + return new DateTime(time.Year, time.Month - 1, 1).ToLocalTime().Date; + } + + private static readonly string[] s_weekdays = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]; + private StatisticsMode _mode; + private Dictionary _all; + private Dictionary _user; + } + public class StatisticsReport { + public StatisticsMode Mode { get; } public int Total { get; set; } = 0; public List Authors { get; set; } = new(); - public List Series { get; set; } = new(); - public List XAxes { get; set; } = new(); - public List YAxes { get; set; } = new(); - public StatisticsAuthor SelectedAuthor { get => _selectedAuthor; set => ChangeAuthor(value); } public StatisticsReport(StatisticsMode mode, DateTime start) { - _mode = mode; - - YAxes.Add(new Axis() - { - TextSize = 10, - MinLimit = 0, - SeparatorsPaint = new SolidColorPaint(new SKColor(0x40808080)) { StrokeThickness = 1 } - }); + Mode = mode; if (mode == StatisticsMode.ThisWeek) { - for (int i = 0; i < 7; i++) - _mapSamples.Add(start.AddDays(i), 0); + _minSampleTime = start; + _maxSampleTime = start.AddDays(6); - XAxes.Add(new DateTimeAxis(TimeSpan.FromDays(1), v => WEEKDAYS[(int)v.DayOfWeek]) { TextSize = 10 }); + for (int i = 0; i < 7; i++) + _all.Add(start.AddDays(i), 0); } else if (mode == StatisticsMode.ThisMonth) { var now = DateTime.Now; var maxDays = DateTime.DaysInMonth(now.Year, now.Month); + _minSampleTime = start; + _maxSampleTime = start.AddDays(maxDays - 1); 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 - { - XAxes.Add(new DateTimeAxis(TimeSpan.FromDays(30), v => $"{v:yyyy/MM}") { TextSize = 10 }); + _all.Add(start.AddDays(i), 0); } } @@ -71,15 +117,24 @@ public void AddCommit(DateTime time, User author) Total++; DateTime normalized; - if (_mode == StatisticsMode.ThisWeek || _mode == StatisticsMode.ThisMonth) + if (Mode == StatisticsMode.ThisWeek || Mode == StatisticsMode.ThisMonth) + { normalized = time.Date; + } else - normalized = new DateTime(time.Year, time.Month, 1).ToLocalTime(); + { + normalized = new DateTime(time.Year, time.Month, 1).ToLocalTime().Date; + + if (normalized < _minSampleTime) + _minSampleTime = normalized; + if (normalized > _maxSampleTime) + _maxSampleTime = normalized; + } - if (_mapSamples.TryGetValue(normalized, out var vs)) - _mapSamples[normalized] = vs + 1; + if (_all.TryGetValue(normalized, out var vs)) + _all[normalized] = vs + 1; else - _mapSamples.Add(normalized, 1); + _all.Add(normalized, 1); if (_mapUsers.TryGetValue(author, out var vu)) _mapUsers[author] = vu + 1; @@ -95,10 +150,9 @@ public void AddCommit(DateTime time, User author) } else { - _mapUserSamples.Add(author, new Dictionary - { - { normalized, 1 } - }); + var added = new Dictionary(); + added.Add(normalized, 1); + _mapUserSamples.Add(author, added); } } @@ -107,76 +161,30 @@ public void Complete() foreach (var kv in _mapUsers) Authors.Add(new StatisticsAuthor(kv.Key, kv.Value)); - Authors.Sort((l, r) => r.Count - l.Count); - - var samples = new List(); - foreach (var kv in _mapSamples) - samples.Add(new DateTimePoint(kv.Key, kv.Value)); - - Series.Add( - new ColumnSeries() - { - Values = samples, - Stroke = null, - Fill = null, - Padding = 1, - } - ); - _mapUsers.Clear(); - _mapSamples.Clear(); - } - - public void ChangeColor(uint color) - { - _fillColor = color; - - var fill = new SKColor(color); - - if (Series.Count > 0 && Series[0] is ColumnSeries total) - total.Fill = new SolidColorPaint(_selectedAuthor == null ? fill : fill.WithAlpha(51)); - - if (Series.Count > 1 && Series[1] is ColumnSeries user) - user.Fill = new SolidColorPaint(fill); - } - - public void ChangeAuthor(StatisticsAuthor author) - { - if (author == _selectedAuthor) - return; + Authors.Sort((l, r) => r.Count - l.Count); - _selectedAuthor = author; - Series.RemoveRange(1, Series.Count - 1); - if (author == null || !_mapUserSamples.TryGetValue(author.User, out var userSamples)) + foreach (var kv in _all) { - ChangeColor(_fillColor); - return; + if (kv.Value > _maxSampleValue) + _maxSampleValue = kv.Value; } + } - var samples = new List(); - foreach (var kv in userSamples) - samples.Add(new DateTimePoint(kv.Key, kv.Value)); - - Series.Add( - new ColumnSeries() - { - Values = samples, - Stroke = null, - Fill = null, - Padding = 1, - } - ); - - ChangeColor(_fillColor); + public StatisticsSamples GetSamples(StatisticsAuthor withUser) + { + var samples = new StatisticsSamples(Mode, _minSampleTime, _maxSampleTime, _all, _maxSampleValue); + if (withUser != null && _mapUserSamples.TryGetValue(withUser.User, out var userSamples)) + samples.WithUser(userSamples); + return samples; } - private static readonly string[] WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]; - private StatisticsMode _mode; + private DateTime _minSampleTime = DateTime.MaxValue; + private DateTime _maxSampleTime = DateTime.MinValue; + private int _maxSampleValue = 0; + private Dictionary _all = new(); private Dictionary _mapUsers = new(); - private Dictionary _mapSamples = new(); private Dictionary> _mapUserSamples = new(); - private StatisticsAuthor _selectedAuthor = null; - private uint _fillColor = 255; } public class Statistics @@ -207,7 +215,7 @@ public void AddCommit(string author, double timestamp) _users.Add(email, user); } - var time = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime(); + var time = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime().Date; if (time >= _thisWeekStart) Week.AddCommit(time, user); diff --git a/src/Models/TextMateHelper.cs b/src/Models/TextMateHelper.cs index 38c0aaa72..5bb50da69 100644 --- a/src/Models/TextMateHelper.cs +++ b/src/Models/TextMateHelper.cs @@ -29,6 +29,8 @@ public static class GrammarUtility new ExtraGrammar("source.vue", [".vue"], "vue.json"), ]; + private static readonly Dictionary s_cachedRawGrammars = new(); + public static string GetScope(string file, RegistryOptions reg) { var extension = Path.GetExtension(file); @@ -53,6 +55,12 @@ public static string GetScope(string file, RegistryOptions reg) public static IRawGrammar GetGrammar(string scopeName, RegistryOptions reg) { + if (string.IsNullOrEmpty(scopeName)) + return null; + + if (s_cachedRawGrammars.TryGetValue(scopeName, out var cached)) + return cached; + foreach (var grammar in s_extraGrammars) { if (grammar.Scope.Equals(scopeName, StringComparison.OrdinalIgnoreCase)) @@ -62,7 +70,9 @@ public static IRawGrammar GetGrammar(string scopeName, RegistryOptions reg) try { - return GrammarReader.ReadGrammarSync(new StreamReader(asset)); + var raw = GrammarReader.ReadGrammarSync(new StreamReader(asset)); + s_cachedRawGrammars.Add(scopeName, raw); + return raw; } catch { @@ -71,7 +81,9 @@ public static IRawGrammar GetGrammar(string scopeName, RegistryOptions reg) } } - return reg.GetGrammar(scopeName); + var fallback = reg.GetGrammar(scopeName); + s_cachedRawGrammars.Add(scopeName, fallback); + return fallback; } private record ExtraGrammar(string Scope, List Extensions, string File) @@ -88,11 +100,21 @@ public class RegistryOptionsWrapper(ThemeName defaultTheme) : IRegistryOptions public IRawTheme GetTheme(string scopeName) => _backend.GetTheme(scopeName); public IRawTheme GetDefaultTheme() => _backend.GetDefaultTheme(); - public IRawTheme LoadTheme(ThemeName name) => _backend.LoadTheme(name); public ICollection GetInjections(string scopeName) => _backend.GetInjections(scopeName); public IRawGrammar GetGrammar(string scopeName) => GrammarUtility.GetGrammar(scopeName, _backend); public string GetScope(string filename) => GrammarUtility.GetScope(filename, _backend); + public IRawTheme LoadTheme(ThemeName name) + { + if (s_cachedTheme.TryGetValue(name, out var cached)) + return cached; + + var loaded = _backend.LoadTheme(name); + s_cachedTheme.Add(name, loaded); + return loaded; + } + + private static readonly Dictionary s_cachedTheme = new(); private readonly RegistryOptions _backend = new(defaultTheme); } @@ -122,7 +144,7 @@ public static void SetGrammarByFileName(TextMate.Installation installation, stri if (reg.LastScope != scope) { reg.LastScope = scope; - installation.SetGrammar(reg.GetScope(filePath)); + installation.SetGrammar(scope); GC.Collect(); } } diff --git a/src/Models/ThemeOverrides.cs b/src/Models/ThemeOverrides.cs index 531cbccdd..c80576dc8 100644 --- a/src/Models/ThemeOverrides.cs +++ b/src/Models/ThemeOverrides.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; - using Avalonia.Media; namespace SourceGit.Models @@ -9,7 +8,6 @@ public class ThemeOverrides public Dictionary BasicColors { get; set; } = new Dictionary(); public double GraphPenThickness { get; set; } = 2; public double OpacityForNotMergedCommits { get; set; } = 0.5; - public bool UseMicaOnWindows11 { get; set; } = true; public List GraphColors { get; set; } = new List(); } } diff --git a/src/Models/User.cs b/src/Models/User.cs index 15a45762b..3d6c82d56 100644 --- a/src/Models/User.cs +++ b/src/Models/User.cs @@ -4,16 +4,11 @@ namespace SourceGit.Models { public class User { - public static readonly User Invalid = new User(); + public static readonly User Invalid = new User(string.Empty); public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; - public User() - { - // Only used by User.Invalid - } - public User(string data) { var parts = data.Split('±', 2); @@ -22,17 +17,6 @@ public User(string data) Name = parts[0]; Email = parts[1].TrimStart('<').TrimEnd('>'); - _hash = data.GetHashCode(); - } - - public override bool Equals(object obj) - { - return obj is User other && Name == other.Name && Email == other.Email; - } - - public override int GetHashCode() - { - return _hash; } public static User FindOrAdd(string data) @@ -46,6 +30,5 @@ public override string ToString() } private static ConcurrentDictionary _caches = new ConcurrentDictionary(); - private readonly int _hash; } } diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index e411cbcef..b03d166b9 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -6,7 +6,6 @@ using Avalonia; using Avalonia.Controls; -using Avalonia.Platform; namespace SourceGit.Native { @@ -22,32 +21,17 @@ public void SetupWindow(Window window) { if (OS.UseSystemWindowFrame) { - window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.Default; window.ExtendClientAreaToDecorationsHint = false; + window.WindowDecorations = WindowDecorations.Full; } else { - window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome; window.ExtendClientAreaToDecorationsHint = true; + window.WindowDecorations = WindowDecorations.None; window.Classes.Add("custom_window_frame"); } } - public void HideSelf() - { - // Do Nothing. Never used. - } - - public void HideOtherApplications() - { - // Do Nothing. Never used. - } - - public void ShowAllApplications() - { - // Do Nothing. Never used. - } - public string GetDataDir() { // AppImage supports portable mode diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 6431d771f..7607b9239 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -1,31 +1,19 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Avalonia; using Avalonia.Controls; -using Avalonia.Platform; namespace SourceGit.Native { [SupportedOSPlatform("macOS")] internal class MacOS : OS.IBackend { - [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_getClass")] - public static extern IntPtr objc_getClass(string name); - - [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "sel_registerName")] - public static extern IntPtr sel_registerName(string name); - - [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] - public static extern IntPtr objc_msgSend(IntPtr receiver, IntPtr selector); - - [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] - public static extern IntPtr objc_msgSendWithArg(IntPtr receiver, IntPtr selector, IntPtr arg); - public void SetupApp(AppBuilder builder) { builder.With(new MacOSPlatformOptions() @@ -53,41 +41,8 @@ public void SetupApp(AppBuilder builder) public void SetupWindow(Window window) { - window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome; window.ExtendClientAreaToDecorationsHint = true; - } - - public void HideSelf() - { - IntPtr nsApplicationClass = objc_getClass("NSApplication"); - IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); - IntPtr nsApp = objc_msgSend(nsApplicationClass, nsSharedApplicationSelector); - IntPtr nsMethodSelector = sel_registerName("hide:"); - IntPtr nsDelegateSelector = sel_registerName("delegate"); - IntPtr nsDelegate = objc_msgSend(nsApp, nsDelegateSelector); - objc_msgSendWithArg(nsApp, nsMethodSelector, nsDelegate); - } - - public void HideOtherApplications() - { - IntPtr nsApplicationClass = objc_getClass("NSApplication"); - IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); - IntPtr nsApp = objc_msgSend(nsApplicationClass, nsSharedApplicationSelector); - IntPtr nsMethodSelector = sel_registerName("hideOtherApplications:"); - IntPtr nsDelegateSelector = sel_registerName("delegate"); - IntPtr nsDelegate = objc_msgSend(nsApp, nsDelegateSelector); - objc_msgSendWithArg(nsApp, nsMethodSelector, nsDelegate); - } - - public void ShowAllApplications() - { - IntPtr nsApplicationClass = objc_getClass("NSApplication"); - IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); - IntPtr nsApp = objc_msgSend(nsApplicationClass, nsSharedApplicationSelector); - IntPtr nsMethodSelector = sel_registerName("unhideAllApplications:"); - IntPtr nsDelegateSelector = sel_registerName("delegate"); - IntPtr nsDelegate = objc_msgSend(nsApp, nsDelegateSelector); - objc_msgSendWithArg(nsApp, nsMethodSelector, nsDelegate); + window.WindowDecorations = WindowDecorations.Full; } public string GetDataDir() @@ -157,4 +112,175 @@ public void OpenWithDefaultEditor(string file) Process.Start("open", file.Quoted()); } } + + [SupportedOSPlatform("macOS")] + public static class MacOSUtilities + { + [StructLayout(LayoutKind.Sequential)] + public struct CGPoint + { + public double X; + public double Y; + + public CGPoint(double x, double y) + { + X = x; + Y = y; + } + + public override int GetHashCode() + { + return HashCode.Combine(X, Y); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + if (obj is not CGPoint point) + return false; + + return X == point.X && Y == point.Y; + } + + public static bool operator ==(CGPoint left, CGPoint right) => left.Equals(right); + public static bool operator !=(CGPoint left, CGPoint right) => !left.Equals(right); + } + + [StructLayout(LayoutKind.Sequential)] + public struct CGSize + { + public double Width; + public double Height; + + public override int GetHashCode() + { + return HashCode.Combine(Width, Height); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + if (obj is not CGSize size) + return false; + + return Width == size.Width && Height == size.Height; + } + + public static bool operator ==(CGSize left, CGSize right) => left.Equals(right); + public static bool operator !=(CGSize left, CGSize right) => !left.Equals(right); + } + + [StructLayout(LayoutKind.Sequential)] + public struct CGRect + { + public CGPoint Origin; + public CGSize Size; + + public override int GetHashCode() + { + return HashCode.Combine(Origin, Size); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + if (obj is not CGRect rect) + return false; + + return Origin == rect.Origin && Size == rect.Size; + } + + public static bool operator ==(CGRect left, CGRect right) => left.Equals(right); + public static bool operator !=(CGRect left, CGRect right) => !left.Equals(right); + } + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_getClass")] + public static extern IntPtr objc_getClass(string name); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "sel_registerName")] + public static extern IntPtr sel_registerName(string name); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend")] + public static extern IntPtr objc_msgSend_IntPtr(IntPtr receiver, IntPtr selector); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend")] + public static extern IntPtr objc_msgSend_IntPtr_Int(IntPtr receiver, IntPtr selector, int arg); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend")] + public static extern void objc_msgSend_Void_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend")] + public static extern void objc_msgSend_Void_Point(IntPtr receiver, IntPtr selector, CGPoint arg); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend_stret")] + public static extern void objc_msgSendStrect_Rect(out CGRect rect, IntPtr receiver, IntPtr selector); + + [DllImport("/usr/lib/libobjc.A.dylib", EntryPoint = "objc_msgSend")] + public static extern CGRect objc_msgSend_Rect(IntPtr receiver, IntPtr selector); + + private static readonly IntPtr s_selStandardWindowButton = sel_registerName("standardWindowButton:"); + private static readonly IntPtr s_selFrame = sel_registerName("frame"); + private static readonly IntPtr s_selSetFrameOrigin = sel_registerName("setFrameOrigin:"); + + public static void AdjustTrafficLightsForThickTitleBar(Window window) + { + IntPtr nsWindow = window.TryGetPlatformHandle()?.Handle ?? IntPtr.Zero; + if (nsWindow == IntPtr.Zero) + return; + + IntPtr nsCloseBtn = objc_msgSend_IntPtr_Int(nsWindow, s_selStandardWindowButton, 0); + IntPtr nsMinBtn = objc_msgSend_IntPtr_Int(nsWindow, s_selStandardWindowButton, 1); + IntPtr nsZoomBtn = objc_msgSend_IntPtr_Int(nsWindow, s_selStandardWindowButton, 2); + if (nsCloseBtn == IntPtr.Zero || nsMinBtn == IntPtr.Zero || nsZoomBtn == IntPtr.Zero) + return; + + // For Intel CPU, we need to use `objc_msgSend_stret` to get the `CGRect` struct, while for Apple Silicon, we can directly use `objc_msgSend`. + if (RuntimeInformation.ProcessArchitecture == Architecture.X64) + { + objc_msgSendStrect_Rect(out var frame, nsCloseBtn, s_selFrame); + if (Math.Abs(frame.Origin.X - 14) <= 0.5 || Math.Abs(frame.Origin.Y - 2) <= 0.5) + return; + } + else + { + CGRect frame = objc_msgSend_Rect(nsCloseBtn, s_selFrame); + if (Math.Abs(frame.Origin.X - 14) <= 0.5 || Math.Abs(frame.Origin.Y - 2) <= 0.5) + return; + } + + objc_msgSend_Void_Point(nsCloseBtn, s_selSetFrameOrigin, new(14, 2)); + objc_msgSend_Void_Point(nsMinBtn, s_selSetFrameOrigin, new(14 + 20, 2)); + objc_msgSend_Void_Point(nsZoomBtn, s_selSetFrameOrigin, new(14 + 40, 2)); + } + + public static void HideSelf() + { + IntPtr nsApplicationClass = objc_getClass("NSApplication"); + IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); + IntPtr nsApp = objc_msgSend_IntPtr(nsApplicationClass, nsSharedApplicationSelector); + IntPtr nsMethodSelector = sel_registerName("hide:"); + IntPtr nsDelegateSelector = sel_registerName("delegate"); + IntPtr nsDelegate = objc_msgSend_IntPtr(nsApp, nsDelegateSelector); + objc_msgSend_Void_IntPtr(nsApp, nsMethodSelector, nsDelegate); + } + + public static void HideOtherApplications() + { + IntPtr nsApplicationClass = objc_getClass("NSApplication"); + IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); + IntPtr nsApp = objc_msgSend_IntPtr(nsApplicationClass, nsSharedApplicationSelector); + IntPtr nsMethodSelector = sel_registerName("hideOtherApplications:"); + IntPtr nsDelegateSelector = sel_registerName("delegate"); + IntPtr nsDelegate = objc_msgSend_IntPtr(nsApp, nsDelegateSelector); + objc_msgSend_Void_IntPtr(nsApp, nsMethodSelector, nsDelegate); + } + + public static void ShowAllApplications() + { + IntPtr nsApplicationClass = objc_getClass("NSApplication"); + IntPtr nsSharedApplicationSelector = sel_registerName("sharedApplication"); + IntPtr nsApp = objc_msgSend_IntPtr(nsApplicationClass, nsSharedApplicationSelector); + IntPtr nsMethodSelector = sel_registerName("unhideAllApplications:"); + IntPtr nsDelegateSelector = sel_registerName("delegate"); + IntPtr nsDelegate = objc_msgSend_IntPtr(nsApp, nsDelegateSelector); + objc_msgSend_Void_IntPtr(nsApp, nsMethodSelector, nsDelegate); + } + } } diff --git a/src/Native/OS.cs b/src/Native/OS.cs index c445e60c4..f2e7e38da 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -18,10 +18,6 @@ public interface IBackend void SetupApp(AppBuilder builder); void SetupWindow(Window window); - void HideSelf(); - void HideOtherApplications(); - void ShowAllApplications(); - string GetDataDir(); string FindGitExecutable(); string FindTerminal(Models.ShellOrTerminal shell); @@ -152,21 +148,6 @@ public static void SetupForWindow(Window window) _backend.SetupWindow(window); } - public static void HideSelf() - { - _backend.HideSelf(); - } - - public static void HideOtherApplications() - { - _backend.HideOtherApplications(); - } - - public static void ShowAllApplications() - { - _backend.ShowAllApplications(); - } - public static void LogException(Exception ex) { if (ex == null) diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 35b8aba66..1253c5e19 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -9,26 +9,12 @@ using Avalonia; using Avalonia.Controls; -using Avalonia.Platform; -using Avalonia.Threading; namespace SourceGit.Native { [SupportedOSPlatform("windows")] internal class Windows : OS.IBackend { - [StructLayout(LayoutKind.Sequential)] - internal struct MARGINS - { - public int cxLeftWidth; - public int cxRightWidth; - public int cyTopHeight; - public int cyBottomHeight; - } - - [DllImport("dwmapi.dll")] - private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins); - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = false)] private static extern bool PathFindOnPath([In, Out] StringBuilder pszFile, [In] string[] ppszOtherDirs); @@ -43,39 +29,18 @@ internal struct MARGINS public void SetupApp(AppBuilder builder) { - // Fix drop shadow issue on Windows 10 - if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000)) - { - Window.WindowStateProperty.Changed.AddClassHandler((w, _) => FixWindowFrameOnWin10(w)); - Control.LoadedEvent.AddClassHandler((w, _) => FixWindowFrameOnWin10(w)); - } + // Do nothing for now. } public void SetupWindow(Window window) { - window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome; + window.WindowDecorations = WindowDecorations.BorderOnly; window.ExtendClientAreaToDecorationsHint = true; - window.BorderThickness = new Thickness(1); - } - - public void HideSelf() - { - // Do Nothing. Never used. - } - - public void HideOtherApplications() - { - // Do Nothing. Never used. - } - - public void ShowAllApplications() - { - // Do Nothing. Never used. } public string GetDataDir() { - var execFile = Process.GetCurrentProcess().MainModule!.FileName; + var execFile = Environment.ProcessPath; var portableDir = Path.Combine(Path.GetDirectoryName(execFile)!, "data"); if (Directory.Exists(portableDir)) return portableDir; @@ -227,21 +192,6 @@ public void OpenWithDefaultEditor(string file) } #region HELPER_METHODS - private void FixWindowFrameOnWin10(Window w) - { - // Schedule the DWM frame extension to run in the next render frame - // to ensure proper timing with the window initialization sequence - Dispatcher.UIThread.Post(() => - { - var platformHandle = w.TryGetPlatformHandle(); - if (platformHandle == null) - return; - - var margins = new MARGINS { cxLeftWidth = 1, cxRightWidth = 1, cyTopHeight = 1, cyBottomHeight = 1 }; - DwmExtendFrameIntoClientArea(platformHandle.Handle, ref margins); - }, DispatcherPriority.Render); - } - private List GenerateVSProjectLaunchOptions(string path) { var root = new DirectoryInfo(path); diff --git a/src/Resources/Fonts/JetBrainsMono-Bold.ttf b/src/Resources/Fonts/JetBrainsMono-Bold.ttf deleted file mode 100644 index 8c93043de..000000000 Binary files a/src/Resources/Fonts/JetBrainsMono-Bold.ttf and /dev/null differ diff --git a/src/Resources/Fonts/JetBrainsMono-Italic.ttf b/src/Resources/Fonts/JetBrainsMono-Italic.ttf deleted file mode 100644 index ccc9d6a5b..000000000 Binary files a/src/Resources/Fonts/JetBrainsMono-Italic.ttf and /dev/null differ diff --git a/src/Resources/Fonts/JetBrainsMono-Regular.ttf b/src/Resources/Fonts/JetBrainsMono-Regular.ttf deleted file mode 100644 index dff66cc50..000000000 Binary files a/src/Resources/Fonts/JetBrainsMono-Regular.ttf and /dev/null differ diff --git a/src/Resources/Fonts/JetBrainsMonoNL-Bold.ttf b/src/Resources/Fonts/JetBrainsMonoNL-Bold.ttf new file mode 100644 index 000000000..f78f84fb4 Binary files /dev/null and b/src/Resources/Fonts/JetBrainsMonoNL-Bold.ttf differ diff --git a/src/Resources/Fonts/JetBrainsMonoNL-Italic.ttf b/src/Resources/Fonts/JetBrainsMonoNL-Italic.ttf new file mode 100644 index 000000000..4e9c3802d Binary files /dev/null and b/src/Resources/Fonts/JetBrainsMonoNL-Italic.ttf differ diff --git a/src/Resources/Fonts/JetBrainsMonoNL-Regular.ttf b/src/Resources/Fonts/JetBrainsMonoNL-Regular.ttf new file mode 100644 index 000000000..70d2ec9e2 Binary files /dev/null and b/src/Resources/Fonts/JetBrainsMonoNL-Regular.ttf differ diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index bf55d8d20..48b847e4c 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -34,6 +34,7 @@ M896 811l-128 0c-23 0-43-19-43-43 0-23 19-43 43-43l107 0c13 0 21-9 21-21L896 107c0-13-9-21-21-21L448 85c-13 0-21 9-21 21l0 21c0 23-19 43-43 43-23 0-43-19-43-43L341 85c0-47 38-85 85-85l469 0c47 0 85 38 85 85l0 640C981 772 943 811 896 811zM683 299l0 640c0 47-38 85-85 85L128 1024c-47 0-85-38-85-85L43 299c0-47 38-85 85-85l469 0C644 213 683 252 683 299zM576 299 149 299c-13 0-21 9-21 21l0 597c0 13 9 21 21 21l427 0c13 0 21-9 21-21L597 320C597 307 589 299 576 299z M339 297c17-23 25-51 25-83 2-42-12-79-43-108S255 62 215 65c-32 0-60 8-84 25s-42 39-54 67-15 56-10 86 19 55 40 76c21 21 47 35 76 41v303c-30 6-55 20-76 41-21 21-35 47-40 76-5 30-2 58 10 86s30 50 54 67 52 25 83 25 59-8 84-25c25-17 45-39 57-67 6-19 10-39 10-61 0-30-8-57-25-83-21-34-52-55-92-64v-299l25-6c28-13 50-32 67-57zm-45 471c8 15 12 30 11 46-1 16-6 31-16 46-10 15-23 25-40 32s-34 8-51 5-32-11-46-24-22-28-24-45c-6-28-1-53 18-75s41-33 68-33c17 0 32 4 46 13 14 8 25 20 33 35zM167 288c-15-11-26-24-33-41-7-17-10-34-6-51 3-17 11-32 24-45s28-21 46-25 36-3 53 5c17 7 30 18 40 32 10 14 15 29 16 46 1 17-3 33-11 48-8 15-20 27-33 35-14 8-29 13-46 13s-33-5-48-16zm615 45c2-19-1-38-10-57-11-28-29-50-54-67s-53-25-83-25h-111l76-76-45-41-127 127v41l127 127 45-41-76-76h111c23 0 44 8 62 25 18 17 27 38 27 64v89h57V332zm0 449H960v-61H782V542h-61v178H543v61h178v178h61V781z M280 145l243 341 0-0 45 63-0 0 79 110a143 143 0 11-36 75l-88-123-92 126c1 4 1 9 1 13l0 5a143 143 0 11-36-95l82-113L221 188l60-43zm473 541a70 70 0 100 140 70 70 0 000-140zm-463 0a70 70 0 100 140 70 70 0 000-140zM772 145l59 43-232 319-45-63L772 145z + M853 137h-102V102h-68v34H341V102h-68v34h-102C133 137 102 167 102 205v68h819V205c0-38-31-68-68-68zM102 341v512C102 891 133 922 171 922h683C891 922 922 891 922 853v-512H102zM444 819h-68V512H307v-68h137V819zm273-273a102 102 0 01-30 72l-97 97 0 0a34 34 0 00-10 24v12H717V819H512v-80a102 102 0 0130-72l97-97a34 34 0 0010-24h0C649 527 633 512 614 512s-34 15-34 34H512c0-57 46-102 102-102s102 46 102 102h-0 0z M128 183C128 154 154 128 183 128h521c30 0 55 26 55 55v38c0 17-17 34-34 34s-34-17-34-34v-26H196v495h26c17 0 34 17 34 34s-17 34-34 34h-38c-30 0-55-26-55-55V183zM380 896h-34c-26 0-47-21-47-47v-90h68V828h64V896H380c4 0 0 0 0 0zM759 828V896h90c26 0 47-21 47-47v-90h-68V828h-68zM828 435H896V346c0-26-21-47-47-47h-90v68H828v68zM435 299v68H367V439H299V346C299 320 320 299 346 299h90zM367 649H299v-107h68v107zM546 367V299h107v68h-107zM828 546H896v107h-68v-107zM649 828V896h-107v-68h107zM730 508v188c0 17-17 34-34 34h-188c-17 0-34-17-34-34s17-34 34-34h102l-124-124c-13-13-13-34 0-47 13-13 34-13 47 0l124 124V512c0-17 17-34 34-34 21-4 38 9 38 30z M889 0H135c-32 0-59 26-59 59v906c0 32 26 59 59 59h753c32 0 59-26 59-59v-906c1-33-26-59-58-59zm-165 177c31 0 56 25 56 56s-25 56-56 56-56-25-56-56 25-56 56-56zm-212 0c31 0 56 25 56 56S543 288 512 288s-56-25-56-56S481 177 512 177zm-212 0c31 0 56 25 56 56s-25 56-56 56-56-25-56-56 25-56 56-56zm209 606H285c-25 0-44-20-44-44 0-25 20-44 44-44h224c25 0 44 20 44 44 0 24-20 44-44 44zm230-212H285c-25 0-44-20-44-44 0-25 20-44 44-44h453c25 0 44 20 44 44 1 24-20 44-44 44z M854 307 611 73c-6-6-14-9-22-9H296c-4 0-8 4-8 8v56c0 4 4 8 8 8h277l219 211V824c0 4 4 8 8 8h56c4 0 8-4 8-8V330c0-9-4-17-10-23zM553 201c-6-6-14-9-23-9H192c-18 0-32 14-32 32v704c0 18 14 32 32 32h512c18 0 32-14 32-32V397c0-9-3-17-9-23L553 201zM568 753c0 4-3 7-8 7h-225c-4 0-8-3-8-7v-42c0-4 3-7 8-7h225c4 0 8 3 8 7v42zm0-220c0 4-3 7-8 7H476v85c0 4-3 7-7 7h-42c-4 0-7-3-7-7V540h-85c-4 0-8-3-8-7v-42c0-4 3-7 8-7H420v-85c0-4 3-7 7-7h42c4 0 7 3 7 7V484h85c4 0 8 3 8 7v42z @@ -65,6 +66,7 @@ M884 159l-18-18a43 43 0 00-38-12l-235 43a166 166 0 00-101 60L400 349a128 128 0 00-148 47l-120 171a21 21 0 005 29l17 12a128 128 0 00178-32l27-38 124 124-38 27a128 128 0 00-32 178l12 17a21 21 0 0029 5l171-120a128 128 0 0047-148l117-92A166 166 0 00853 431l43-235a43 43 0 00-12-38zm-177 249a64 64 0 110-90 64 64 0 010 90zm-373 312a21 21 0 010 30l-139 139a21 21 0 01-30 0l-30-30a21 21 0 010-30l139-139a21 21 0 0130 0z M525 0C235 0 0 235 0 525c0 232 150 429 359 498 26 5 36-11 36-25 0-12-1-54-1-97-146 31-176-63-176-63-23-61-58-76-58-76-48-32 3-32 3-32 53 3 81 54 81 54 47 80 123 57 153 43 4-34 18-57 33-70-116-12-239-57-239-259 0-57 21-104 54-141-5-13-23-67 5-139 0 0 44-14 144 54 42-11 87-17 131-17s90 6 131 17C756 203 801 217 801 217c29 72 10 126 5 139 34 37 54 83 54 141 0 202-123 246-240 259 19 17 36 48 36 97 0 70-1 127-1 144 0 14 10 30 36 25 209-70 359-266 359-498C1050 235 814 0 525 0z M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z + M289 477l147 266C582 460 733 198 1014 20c0 93-15 174 4 247 23 93-23 123-82 180-152 144-287 307-427 463-20 22-35 48-47 67L39 625l250-148z M727 641c-78 0-142 55-157 128H256V320h251c16 108 108 192 221 192 124 0 224-100 224-224S851 64 727 64c-113 0-205 84-221 192H96c-18 0-32 14-32 32s14 32 32 32h96v482c0 18 14 32 32 32h347c15 73 79 128 157 128 88 0 160-72 160-160s-72-160-160-160zm0 256c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96z M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z M566 585l37-146-145 0-37 146 145 0zM1005 297l-32 128q-4 14-18 14l-187 0-37 146 178 0q9 0 14 7 6 8 3 16l-32 128q-3 14-18 14l-187 0-46 187q-4 14-18 14l-128 0q-9 0-15-7-5-7-3-16l45-178-145 0-46 187q-4 14-18 14l-129 0q-9 0-14-7-5-7-3-16l45-178-178 0q-9 0-14-7-5-7-3-16l32-128q4-14 18-14l187 0 37-146-178 0q-9 0-14-7-6-8-3-16l32-128q3-14 18-14l187 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 145 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 178 0q9 0 14 7 5 7 3 16z @@ -93,6 +95,7 @@ M192 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM864 160H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 480H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 800H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32z M824 645V307c0-56-46-102-102-102h-102V102l-154 154 154 154V307h102v338c-46 20-82 67-82 123 0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123zm-51 195c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72zM384 256c0-72-61-133-133-133-72 0-133 61-133 133 0 56 36 102 82 123v266C154 666 118 712 118 768c0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123V379C348 358 384 312 384 256zM323 768c0 41-31 72-72 72-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72zM251 328c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72z M688 544a48 48 0 110-96 48 48 0 010 96M512 544a48 48 0 110-96 48 48 0 010 96m-176 0a48 48 0 11-0-96A48 48 0 01336 544M805 192H219C186 192 160 219 160 253v471c0 34 26 61 59 61h189c6 0 16 6 18 11l38 72 3 5c11 14 27 23 44 23h0c17 0 33-8 45-23l41-77c2-5 12-11 18-11h190c32 0 59-27 59-61V253C864 219 838 192 805 192 + M544 150H418v-127h127v126zM799 530h-635c-35 0-64-29-64-64v-180c0-35 29-64 64-64h637l119 151-121 157zm-196-210H358v114h247v-114zM416 1021h127v-420H417v420z M0 512M1024 512M512 0M512 1024M64 576h896V448H64z M896 64H128C96 64 64 96 64 128v768c0 32 32 64 64 64h768c32 0 64-32 64-64V128c0-32-32-64-64-64z m-64 736c0 16-17 32-32 32H224c-18 0-32-12-32-32V224c0-16 16-32 32-32h576c15 0 32 16 32 32v576zM512 384c-71 0-128 57-128 128s57 128 128 128 128-57 128-128-57-128-128-128z M0 512M1024 512M512 0M512 1024M813 448c-46 0-83 37-83 83 0 46 37 83 83 83 46 0 83-37 83-83 0-46-37-83-83-83zM211 448C165 448 128 485 128 531c0 46 37 83 83 83 46 0 83-37 83-83 0-46-37-83-83-83zM512 448c-46 0-83 37-83 83 0 46 37 83 83 83 46 0 83-37 83-83C595 485 558 448 512 448z @@ -111,7 +114,6 @@ M563 555c0 28-23 51-51 51-28 0-51-23-51-51L461 113c0-28 23-51 51-51s51 23 51 51L563 555 563 555zM85 535c0-153 81-287 201-362 24-15 55-8 70 16C371 214 363 245 340 260 248 318 187 419 187 535c0 180 146 325 325 325 180-0 325-146 325-325 0-119-64-223-160-280-24-14-32-46-18-70 14-24 46-32 70-18 125 74 210 211 210 367 0 236-191 427-427 427C276 963 85 772 85 535 M277 85a149 149 0 00-43 292v230a32 32 0 0064 0V555h267A160 160 0 00725 395v-12a149 149 0 10-64-5v17a96 96 0 01-96 96H299V383A149 149 0 00277 85zM228 720a32 32 0 00-37-52 150 150 0 00-53 68 32 32 0 1060 23 85 85 0 0130-39zm136-52a32 32 0 00-37 52 86 86 0 0130 39 32 32 0 1060-23 149 149 0 00-53-68zM204 833a32 32 0 10-55 32 149 149 0 0063 58 32 32 0 0028-57 85 85 0 01-36-33zm202 32a32 32 0 00-55-32 85 85 0 01-36 33 32 32 0 0028 57 149 149 0 0063-58z M912 382l-32-94-184 75L708 160H607l12 202-184-75-32 94 193 53-133 150 78 61 116-168L773 646l78-61-133-150zM256 769m-71 0a71 71 0 10141 0 71 71 0 10-141 0Z - m224 154a166 166 0 00-166 166v192a166 166 0 00166 166h64v-76h-64a90 90 0 01-90-90v-192a90 90 0 0190-90h320a90 90 0 0190 90v192a90 90 0 01-90 90h-128v77h128a166 166 0 00166-167v-192a166 166 0 00-166-166h-320zm166 390a90 90 0 0190-90h128v-76h-128a166 166 0 00-166 166v192a166 166 0 00166 166h320a166 166 0 00166-166v-192a166 166 0 00-166-166h-64v77h64a90 90 0 0190 90v192a90 90 0 01-90 90h-320a90 90 0 01-90-90v-192z M512 128M706 302a289 289 0 00-173 44 27 27 0 1029 46 234 234 0 01125-36c23 0 45 3 66 9 93 28 161 114 161 215C914 704 813 805 687 805H337C211 805 110 704 110 580c0-96 61-178 147-210C282 263 379 183 495 183a245 245 0 01210 119z M364 512h67v108h108v67h-108v108h-67v-108h-108v-67h108v-108zm298-64A107 107 0 01768 555C768 614 720 660 660 660h-108v-54h-108v-108h-94v108h-94c4-21 22-47 44-51l-1-12a75 75 0 0171-75a128 128 0 01239-7a106 106 0 0153-14z M115 386l19 33c17 29 44 50 76 60l116 33c34 10 58 41 58 77v80c0 22 12 42 32 52s32 30 32 52v78c0 31 30 54 60 45 32-9 57-35 65-68l6-22c8-34 30-63 61-80l16-9c30-17 48-49 48-83v-17c0-25-10-50-28-68l-8-8c-18-18-42-28-68-28H514c-22 0-44-6-64-17l-69-39c-9-5-15-13-18-22-6-19 2-40 20-49l12-6c13-7 29-8 43-3l46 15c16 5 34-1 44-15 9-14 8-33-2-46l-27-33c-20-24-20-59 1-83l31-37c18-21 20-50 7-73l-5-8c-7-0-14-1-21-1-186 0-343 122-396 290zM928 512c0-74-19-143-53-203L824 330c-31 13-48 48-37 80l34 101c7 21 24 37 45 42l58 15c2-18 4-36 4-55zM0 512a512 512 0 111024 0 512 512 0 11-1024 0z @@ -124,6 +126,7 @@ M155 143h715v81H155V143zm358 94 358 369H662l1 278H363V605H155l358-369z M702 677 590 565a148 148 0 10-25 27L676 703zm-346-200a115 115 0 11115 115A115 115 0 01355 478z M928 500a21 21 0 00-19-20L858 472a11 11 0 01-9-9c-1-6-2-13-3-19a11 11 0 015-12l46-25a21 21 0 0010-26l-8-22a21 21 0 00-24-13l-51 10a11 11 0 01-12-6c-3-6-6-11-10-17a11 11 0 011-13l34-39a21 21 0 001-28l-15-18a20 20 0 00-27-4l-45 27a11 11 0 01-13-1c-5-4-10-9-15-12a11 11 0 01-3-12l19-49a21 21 0 00-9-26l-20-12a21 21 0 00-27 6L650 193a9 9 0 01-11 3c-1-1-12-5-20-7a11 11 0 01-7-10l1-52a21 21 0 00-17-22l-23-4a21 21 0 00-24 14L532 164a11 11 0 01-11 7h-20a11 11 0 01-11-7l-17-49a21 21 0 00-24-15l-23 4a21 21 0 00-17 22l1 52a11 11 0 01-8 11c-5 2-15 6-19 7c-4 1-8 0-12-4l-33-40A21 21 0 00313 146l-20 12A21 21 0 00285 184l19 49a11 11 0 01-3 12c-5 4-10 8-15 12a11 11 0 01-13 1L228 231a21 21 0 00-27 4L186 253a21 21 0 001 28L221 320a11 11 0 011 13c-3 5-7 11-10 17a11 11 0 01-12 6l-51-10a21 21 0 00-24 13l-8 22a21 21 0 0010 26l46 25a11 11 0 015 12l0 3c-1 6-2 11-3 16a11 11 0 01-9 9l-51 8A21 21 0 0096 500v23A21 21 0 00114 544l51 8a11 11 0 019 9c1 6 2 13 3 19a11 11 0 01-5 12l-46 25a21 21 0 00-10 26l8 22a21 21 0 0024 13l51-10a11 11 0 0112 6c3 6 6 11 10 17a11 11 0 01-1 13l-34 39a21 21 0 00-1 28l15 18a20 20 0 0027 4l45-27a11 11 0 0113 1c5 4 10 9 15 12a11 11 0 013 12l-19 49a21 21 0 009 26l20 12a21 21 0 0027-6L374 832c3-3 7-5 10-4c7 3 12 5 20 7a11 11 0 018 10l-1 52a21 21 0 0017 22l23 4a21 21 0 0024-14l17-50a11 11 0 0111-7h20a11 11 0 0111 7l17 49a21 21 0 0020 15a19 19 0 004 0l23-4a21 21 0 0017-22l-1-52a11 11 0 018-10c8-3 13-5 18-7l1 0c6-2 9 0 11 3l34 41A21 21 0 00710 878l20-12a21 21 0 009-26l-18-49a11 11 0 013-12c5-4 10-8 15-12a11 11 0 0113-1l45 27a21 21 0 0027-4l15-18a21 21 0 00-1-28l-34-39a11 11 0 01-1-13c3-5 7-11 10-17a11 11 0 0112-6l51 10a21 21 0 0024-13l8-22a21 21 0 00-10-26l-46-25a11 11 0 01-5-12l0-3c1-6 2-11 3-16a11 11 0 019-9l51-8a21 21 0 0018-21v-23zm-565 188a32 32 0 01-51 5a270 270 0 011-363a32 32 0 0151 6l91 161a32 32 0 010 31zM512 782a270 270 0 01-57-6a32 32 0 01-20-47l92-160a32 32 0 0127-16h184a32 32 0 0130 41c-35 109-137 188-257 188zm15-328L436 294a32 32 0 0121-47a268 268 0 0155-6c120 0 222 79 257 188a32 32 0 01-30 41h-184a32 32 0 01-28-16z + M622 718v137q0 9-7 16t-16 7H462q-9 0-16-7t-7-16v-137q0-9 7-16t16-7h137q9 0 16 7t7 16zm181-343q0 31-9 58t-20 44-31 34-33 25-35 20q-23 13-39 37t-16 38q0 10-7 19t-16 9H459q-9 0-15-11T439 626v-26q0-47 37-89T558 449q34-15 48-32t14-43q0-24-27-42T532 313q-37 0-62 17-20 14-61 66-7 9-18 9-7 0-14-5L283 329q-7-6-9-14t3-16q91-152 265-152 46 0 92 18t83 47 61 73 23 91z M900 287c40 69 60 144 60 225s-20 156-60 225c-40 69-94 123-163 163-69 40-144 60-225 60s-156-20-225-60c-69-40-123-94-163-163C84 668 64 593 64 512s20-156 60-225 94-123 163-163c69-40 144-60 225-60s156 20 225 60 123 94 163 163zM762 512c0-9-3-16-9-22L578 315l-44-44c-6-6-13-9-22-9s-16 3-22 9l-44 44-176 176c-6 6-9 13-9 22s3 16 9 22l44 44c6 6 13 9 22 9s16-3 22-9l92-92v269c0 9 3 16 9 22 6 6 13 9 22 9h62c8 0 16-3 22-9 6-6 9-13 9-22V486l92 92c6 6 13 9 22 9 8 0 16-3 22-9l44-44c6-6 9-13 9-22z M512 939C465 939 427 900 427 853 427 806 465 768 512 768 559 768 597 806 597 853 597 900 559 939 512 939M555 85 555 555 747 363 807 423 512 719 217 423 277 363 469 555 469 85 555 85Z M961 320 512 577 63 320 512 62l449 258zM512 628 185 442 63 512 512 770 961 512l-123-70L512 628zM512 821 185 634 63 704 512 962l449-258L839 634 512 821z diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 049895775..f28efaa1e 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -27,7 +27,6 @@ Verwende AI, um Commit-Nachrichten zu generieren SourceGit minimieren Alles anzeigen - Patch-Datei: Wähle die anzuwendende .patch-Datei Ignoriere Leerzeichen-Änderungen Patch anwenden @@ -51,10 +50,10 @@ Bisect Abbrechen Schlecht - Bisecting. Ist der aktuelle HEAD gut oder schlecht? Gut Überspringen - Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken. + Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken. + Bisecting. Ist der aktuelle HEAD gut oder schlecht? Blame Blame auf vorheriger Revision Leerzeichen-Änderungen ignorieren @@ -153,7 +152,6 @@ Interaktives Rebase von ${0}$ auf ${1}$ Umformulieren… Squash in den Vorgänger… - Merge in ${0}$ hinein Merge… Push ${0}$ zu ${1}$ Rebase ${0}$ auf ${1}$ @@ -465,7 +463,6 @@ $1, $2, … Werte der Eingabe-Steuerelemente AUTOR AUTOR-ZEITPUNKT COMMIT-ZEITPUNKT - COMMIT-ZEITPUNKT VERLAUF & COMMIT-NACHRICHT SHA {0} COMMITS AUSGEWÄHLT @@ -616,7 +613,6 @@ $1, $2, … Werte der Eingabe-Steuerelemente Aktiviere kompakte Ordner im Änderungsbaum Sprache Commit-Historie - Zeige Autor-Zeitpunkt anstatt Commit-Zeitpunkt Standardmäßig ‚ÄNDERUNGEN‘-Ansicht anzeigen Standardmäßig Registerkarte ‚ÄNDERUNGEN‘ in Commit-Details anzeigen Zeige Nachfolger in den Commit-Details @@ -872,7 +868,6 @@ $1, $2, … Werte der Eingabe-Steuerelemente Benutzerdefinierte Aktion Lösche ${0}$… Lösche ausgewählte {0} Tags… - Merge ${0}$ in ${1}$ hinein… Pushe ${0}$… Submodule aktualisieren Alle Submodule diff --git a/src/Resources/Locales/el_GR.axaml b/src/Resources/Locales/el_GR.axaml new file mode 100644 index 000000000..999ce1695 --- /dev/null +++ b/src/Resources/Locales/el_GR.axaml @@ -0,0 +1,1017 @@ + + + + + + Σχετικά + Αναθεώρηση πηγαίου κώδικα: + Σχετικά με το SourceGit + Ημερομηνία έκδοσης: {0} + Σημειώσεις έκδοσης + Ελεύθερο & ανοιχτού κώδικα γραφικό περιβάλλον για το Git + Προσθήκη αρχείου(-ων) στα αγνοούμενα + Μοτίβο: + Αρχείο αποθήκευσης: + Προσθήκη Worktree + Τοποθεσία: + Διαδρομή για αυτό το worktree. Υποστηρίζεται σχετική διαδρομή. + Όνομα κλάδου: + Προαιρετικό. Προεπιλογή είναι το όνομα του φακέλου προορισμού. + Παρακολούθηση κλάδου: + Παρακολούθηση απομακρυσμένου κλάδου + Τι να γίνει checkout: + Δημιουργία νέου κλάδου + Υπάρχων κλάδος + Βοηθός AI + ΜΟΝΤΕΛΟ + ΕΠΑΝΑΔΗΜΙΟΥΡΓΙΑ + Χρήση AI για δημιουργία μηνύματος commit + Χρήση + Απόκρυψη SourceGit + Απόκρυψη άλλων + Εμφάνιση όλων + Τριμερής συγχώνευση (3-Way) + Επιλέξτε αρχείο .patch για εφαρμογή + Αγνόηση αλλαγών κενών χαρακτήρων + Εφαρμογή Patch + Κενά: + Εφαρμογή Stash + Διαγραφή μετά την εφαρμογή + Επαναφορά των αλλαγών του index + Stash: + Αρχειοθέτηση... + Αποθήκευση αρχείου σε: + Επιλέξτε διαδρομή για το αρχείο + Αναθεώρηση: + Αρχειοθέτηση + SourceGit Askpass + Εισαγωγή κωδικής φράσης: + ΑΡΧΕΙΑ ΠΟΥ ΘΕΩΡΟΥΝΤΑΙ ΑΜΕΤΑΒΛΗΤΑ + ΚΑΝΕΝΑ ΑΡΧΕΙΟ ΔΕΝ ΘΕΩΡΕΙΤΑΙ ΑΜΕΤΑΒΛΗΤΟ + Φόρτωση εικόνας... + Ανανέωση + ΤΟ ΔΥΑΔΙΚΟ ΑΡΧΕΙΟ ΔΕΝ ΥΠΟΣΤΗΡΙΖΕΤΑΙ!!! + Bisect + Ματαίωση + Κακό + Καλό + Παράλειψη + Εκτέλεση bisect. Σημειώστε το τρέχον commit ως καλό ή κακό και κάντε checkout σε άλλο. + Εκτέλεση bisect. Το τρέχον HEAD είναι καλό ή κακό; + Blame + Blame στην προηγούμενη αναθεώρηση + Αγνόηση αλλαγών κενών χαρακτήρων + ΤΟ BLAME ΣΕ ΑΥΤΟ ΤΟ ΑΡΧΕΙΟ ΔΕΝ ΥΠΟΣΤΗΡΙΖΕΤΑΙ!!! + Checkout ${0}$... + Σύγκριση των 2 επιλεγμένων κλάδων + Σύγκριση με... + Σύγκριση με το HEAD + Σύγκριση με ${0}$ + Αντιγραφή ονόματος κλάδου + Δημιουργία PR... + Δημιουργία PR για το upstream ${0}$... + Προσαρμοσμένη ενέργεια + Διαγραφή ${0}$... + Διαγραφή {0} επιλεγμένων κλάδων + Επεξεργασία περιγραφής για ${0}$... + Fast-Forward στο ${0}$ + Fetch ${0}$ στο ${1}$... + Git Flow - Ολοκλήρωση ${0}$ + Διαδραστικό rebase του ${0}$ πάνω στο ${1}$ + Συγχώνευση ${0}$ στο ${1}$... + Συγχώνευση {0} επιλεγμένων κλάδων στον τρέχοντα + Pull ${0}$ + Pull ${0}$ στο ${1}$... + Push ${0}$ + Rebase του ${0}$ πάνω στο ${1}$... + Μετονομασία ${0}$... + Επαναφορά ${0}$ στο ${1}$... + Μετάβαση στο ${0}$ (worktree) + Ορισμός κλάδου παρακολούθησης... + {0} commit μπροστά + {0} commit μπροστά, {1} commit πίσω + {0} commit πίσω + Μη έγκυρο + ΑΠΟΜΑΚΡΥΣΜΕΝΟ + ΚΑΤΑΣΤΑΣΗ + ΠΑΡΑΚΟΛΟΥΘΗΣΗ + URL + WORKTREE + ΑΚΥΡΟ + Επαναφορά στη γονική αναθεώρηση + Επαναφορά σε αυτή την αναθεώρηση + Δημιουργία μηνύματος commit + Συγχώνευση (ενσωματωμένη) + Συγχώνευση (εξωτερική) + Επαναφορά αρχείου(-ων) στο ${0}$ + ΑΛΛΑΓΗ ΤΡΟΠΟΥ ΕΜΦΑΝΙΣΗΣ + Εμφάνιση ως λίστα αρχείων και φακέλων + Εμφάνιση ως λίστα διαδρομών + Εμφάνιση ως δέντρο αρχείων + Αλλαγή URL της υπομονάδας + Υπομονάδα: + URL: + Checkout κλάδου + Checkout commit + Commit: + Προειδοποίηση: Με το checkout σε commit, το HEAD θα αποσυνδεθεί (detached) + Τοπικές αλλαγές: + Κλάδος: + Το τρέχον HEAD περιέχει commit που δεν συνδέονται με κανέναν κλάδο/ετικέτα! Θέλετε να συνεχίσετε; + Οι ακόλουθες υπομονάδες πρέπει να ενημερωθούν:{0}Θέλετε να τις ενημερώσετε; + Checkout & Fast-Forward + Fast-Forward στο: + Checkout κλάδου από Stash + Νέος κλάδος: + Stash: + Cherry-Pick + Προσθήκη πηγής στο μήνυμα commit + Commit: + Commit όλων των αλλαγών + Κύρια γραμμή: + Συνήθως δεν μπορείτε να κάνετε cherry-pick μια συγχώνευση, επειδή δεν γνωρίζετε ποια πλευρά της συγχώνευσης πρέπει να θεωρηθεί η κύρια γραμμή. Αυτή η επιλογή επιτρέπει στο cherry-pick να αναπαράγει την αλλαγή σε σχέση με τον καθορισμένο γονέα. + Εκκαθάριση Stashes + Πρόκειται να εκκαθαρίσετε όλα τα stashes. Είστε σίγουροι ότι θέλετε να συνεχίσετε; + Κλωνοποίηση απομακρυσμένου αποθετηρίου + Επιπλέον παράμετροι: + Πρόσθετα ορίσματα για την κλωνοποίηση του αποθετηρίου. Προαιρετικό. + Σελιδοδείκτης: + Ομάδα: + Τοπικό όνομα: + Όνομα αποθετηρίου. Προαιρετικό. + Γονικός φάκελος: + Αρχικοποίηση & ενημέρωση υπομονάδων + URL αποθετηρίου: + ΚΛΕΙΣΙΜΟ + Επεξεργαστής + Κλάδοι + Κλάδοι & Ετικέτες + Προσαρμοσμένες ενέργειες αποθετηρίου + Αρχεία αναθεώρησης + Checkout commit + Cherry-Pick commit + Cherry-Pick ... + Σύγκριση με το HEAD + Σύγκριση με το Worktree + Συγγραφέας + Ώρα συγγραφέα + Μήνυμα + Committer + Ώρα committer + SHA + Θέμα + Προσαρμοσμένη ενέργεια + Διαδραστικό rebase + Απόρριψη (Drop)... + Επεξεργασία... + Fixup στον γονέα... + Διαδραστικό rebase του ${0}$ πάνω στο ${1}$ + Επαναδιατύπωση... + Squash στον γονέα... + Συγχώνευση ... + Push ${0}$ στο ${1}$ + Rebase του ${0}$ πάνω στο ${1}$ + Επαναφορά ${0}$ στο ${1}$ + Αναίρεση commit + Αποθήκευση ως Patch... + ΑΛΛΑΓΕΣ + αλλαγμένο(-α) αρχείο(-α) + Αναζήτηση αλλαγών... + Σύμπτυξη λεπτομερειών + ΑΡΧΕΙΑ + Αρχείο LFS + Αναζήτηση αρχείων... + Υπομονάδα + ΠΛΗΡΟΦΟΡΙΕΣ + ΣΥΓΓΡΑΦΕΑΣ + ΑΠΟΓΟΝΟΙ + COMMITTER + Έλεγχος refs που περιέχουν αυτό το commit + ΤΟ COMMIT ΠΕΡΙΕΧΕΤΑΙ ΣΕ + Αντιγραφή email + Αντιγραφή ονόματος + Αντιγραφή ονόματος & email + Εμφανίζονται μόνο οι πρώτες 100 αλλαγές. Δείτε όλες τις αλλαγές στην καρτέλα ΑΛΛΑΓΕΣ. + Κλειδί: + ΜΗΝΥΜΑ + ΓΟΝΕΙΣ + REFS + SHA + Υπογράφων: + Άνοιγμα στον περιηγητή + ΣΤΗΛΗ + Εισαγάγετε το μήνυμα commit. Χρησιμοποιήστε μια κενή γραμμή για να διαχωρίσετε το θέμα από την περιγραφή! + ΘΕΜΑ + Σύγκριση + ΑΛΛΑΓΕΣ + COMMITS + COMMITS ΜΟΝΟ ΑΡΙΣΤΕΡΑ + COMMITS ΜΟΝΟ ΔΕΞΙΑ + Συμβουλή: Μπορείτε να κάνετε cherry-pick τα επιλεγμένα commits αν η άλλη πλευρά είναι το HEAD (μέσω του μενού περιβάλλοντος). + Ρύθμιση αποθετηρίου + ΠΡΟΤΥΠΟ COMMIT + Ενσωματωμένες παράμετροι: + + ${branch_name} Όνομα τρέχοντος τοπικού κλάδου. + ${files_num} Πλήθος αλλαγμένων αρχείων + ${files} Διαδρομές αλλαγμένων αρχείων + ${files:N} Έως N διαδρομές αλλαγμένων αρχείων + ${pure_files} Όπως το ${files}, αλλά μόνο καθαρά ονόματα αρχείων + ${pure_files:N} Όπως το ${files:N}, αλλά χωρίς φακέλους + Περιεχόμενο προτύπου: + Όνομα προτύπου: + ΠΡΟΣΑΡΜΟΣΜΕΝΗ ΕΝΕΡΓΕΙΑ + Ορίσματα: + Ενσωματωμένες παράμετροι: + + ${REPO} Διαδρομή του αποθετηρίου + ${REMOTE} Επιλεγμένο remote ή το remote του επιλεγμένου κλάδου + ${BRANCH} Επιλεγμένος κλάδος, χωρίς το τμήμα ${REMOTE} για απομακρυσμένους κλάδους + ${BRANCH_FRIENDLY_NAME} Φιλικό όνομα του επιλεγμένου κλάδου, περιέχει το τμήμα ${REMOTE} για απομακρυσμένους κλάδους + ${SHA} Hash του επιλεγμένου commit + ${TAG} Επιλεγμένη ετικέτα + ${FILE} Επιλεγμένο αρχείο, σε σχέση με τη ρίζα του αποθετηρίου + $1, $2 ... Τιμές των στοιχείων εισόδου + Εκτελέσιμο αρχείο: + Στοιχεία εισόδου: + Επεξεργασία + Όνομα: + Εμβέλεια: + Κλάδος + Commit + Αρχείο + Απομακρυσμένο + Αποθετήριο + Ετικέτα + Αναμονή για έξοδο της ενέργειας + Διεύθυνση email + Διεύθυνση email + GIT + Ερώτηση πριν την αυτόματη ενημέρωση υπομονάδων + Αυτόματο fetch από τα απομακρυσμένα + Λεπτό(-ά) + Τύποι Conventional Commit + Προεπιλεγμένο απομακρυσμένο + Προτιμώμενος τρόπος συγχώνευσης + ΣΥΣΤΗΜΑ ΠΑΡΑΚΟΛΟΥΘΗΣΗΣ ΖΗΤΗΜΑΤΩΝ + Προσθήκη κανόνα Azure DevOps + Προσθήκη κανόνα Gerrit Change-Id Commit + Προσθήκη κανόνα Gitee Issue + Προσθήκη κανόνα Gitee Pull Request + Προσθήκη κανόνα GitHub + Προσθήκη κανόνα GitLab Issue + Προσθήκη κανόνα GitLab Merge Request + Προσθήκη κανόνα Jira + Νέος κανόνας + Κανονική έκφραση ζητήματος: + Όνομα κανόνα: + Κοινή χρήση αυτού του κανόνα στο αρχείο .issuetracker + URL αποτελέσματος: + Χρησιμοποιήστε $1, $2 για πρόσβαση στις τιμές των ομάδων της κανονικής έκφρασης. + AI + Προτιμώμενη υπηρεσία: + Αν οριστεί η «Προτιμώμενη υπηρεσία», το SourceGit θα τη χρησιμοποιεί μόνο σε αυτό το αποθετήριο. Διαφορετικά, αν υπάρχουν περισσότερες από μία διαθέσιμες υπηρεσίες, θα εμφανίζεται μενού για να επιλέξετε μία. + HTTP Proxy + HTTP proxy που χρησιμοποιεί αυτό το αποθετήριο + Όνομα χρήστη + Όνομα χρήστη για αυτό το αποθετήριο + Επεξεργασία στοιχείων προσαρμοσμένης ενέργειας + Τιμή όταν επιλεγεί: + Όταν είναι επιλεγμένο, αυτή η τιμή θα χρησιμοποιείται στα ορίσματα της γραμμής εντολών + Περιγραφή: + Προεπιλογή: + Είναι φάκελος: + Ετικέτα: + Επιλογές: + Χρησιμοποιήστε το '|' ως διαχωριστικό για τις επιλογές + Μορφοποιητής συμβολοσειράς: + Προαιρετικό. Χρησιμοποιείται για μορφοποίηση της συμβολοσειράς εξόδου. Αγνοείται όταν η είσοδος είναι κενή. Χρησιμοποιήστε το `${VALUE}` για να αναπαραστήσετε τη συμβολοσειρά εισόδου. + Οι ενσωματωμένες μεταβλητές ${REPO}, ${REMOTE}, ${BRANCH}, ${BRANCH_FRIENDLY_NAME}, ${SHA}, ${FILE}, και ${TAG} παραμένουν διαθέσιμες εδώ + Τύπος: + Χρήση φιλικού ονόματος: + Χώροι εργασίας + Χρώμα + Όνομα + Επαναφορά καρτελών κατά την εκκίνηση + ΣΥΝΕΧΕΙΑ + Εντοπίστηκε κενό commit! Θέλετε να συνεχίσετε (--allow-empty); + ΠΡΟΣΘΗΚΗ ΟΛΩΝ & COMMIT + ΠΡΟΣΘΗΚΗ ΕΠΙΛΕΓΜΕΝΩΝ & COMMIT + Εντοπίστηκε κενό commit! Θέλετε να συνεχίσετε (--allow-empty) ή να γίνει αυτόματη προσθήκη στο ευρετήριο και μετά commit; + Απαιτείται επανεκκίνηση + Πρέπει να επανεκκινήσετε την εφαρμογή για να εφαρμοστούν οι αλλαγές. + Βοηθός Conventional Commit + Breaking Change: + Ζήτημα που κλείνει: + Λεπτομέρειες αλλαγών: + Εμβέλεια: + Σύντομη περιγραφή: + Τύπος αλλαγής: + Αντιγραφή + Αντιγραφή όλου του κειμένου + Αντιγραφή πλήρους διαδρομής + Αντιγραφή διαδρομής + Δημιουργία κλάδου... + Με βάση: + Checkout του κλάδου που δημιουργήθηκε + Τοπικές αλλαγές: + Όνομα νέου κλάδου: + Εισαγάγετε όνομα κλάδου. + Δημιουργία τοπικού κλάδου + Αντικατάσταση υπάρχοντος κλάδου + Δημιουργία ετικέτας... + Νέα ετικέτα στο: + Υπογραφή GPG + Μήνυμα ετικέτας: + Προαιρετικό. + Όνομα ετικέτας: + Προτεινόμενη μορφή: v1.0.0-alpha + Push σε όλα τα απομακρυσμένα μετά τη δημιουργία + Δημιουργία ετικέτας + Είδος: + επισημειωμένη + ελαφριά + Κρατήστε Ctrl για άμεση εκκίνηση + Αποκοπή + Απόρριψη + Καμία ενέργεια + Stash & επανεφαρμογή + Απο-αρχικοποίηση υπομονάδας + Εξαναγκασμός απο-αρχικοποίησης ακόμη κι αν περιέχει τοπικές αλλαγές. + Υπομονάδα: + Διαγραφή κλάδου + Κλάδος: + Πρόκειται να διαγράψετε έναν απομακρυσμένο κλάδο!!! + Διαγραφή και του απομακρυσμένου κλάδου ${0}$ + Διαγραφή πολλαπλών κλάδων + Προσπαθείτε να διαγράψετε πολλούς κλάδους ταυτόχρονα. Βεβαιωθείτε ότι ελέγξατε ξανά πριν προχωρήσετε! + Διαγραφή πολλαπλών ετικετών + Διαγραφή τους από τα απομακρυσμένα + Προσπαθείτε να διαγράψετε πολλές ετικέτες ταυτόχρονα. Βεβαιωθείτε ότι ελέγξατε ξανά πριν προχωρήσετε! + Διαγραφή απομακρυσμένου + Απομακρυσμένο: + Διαδρομή: + Στόχος: + Όλα τα παιδιά θα αφαιρεθούν από τη λίστα. + Αυτό θα το αφαιρέσει μόνο από τη λίστα, όχι από τον δίσκο! + Επιβεβαίωση διαγραφής ομάδας + Επιβεβαίωση διαγραφής αποθετηρίου + Διαγραφή υπομονάδας + Διαδρομή υπομονάδας: + Διαγραφή ετικέτας + Ετικέτα: + Διαγραφή από τα απομακρυσμένα αποθετήρια + ΔΥΑΔΙΚΟ DIFF + Άλλαξε η λειτουργία αρχείου (file mode) + Πρώτη διαφορά + Αγνόηση αλλαγών κενών χαρακτήρων + ΑΝΑΜΕΙΞΗ + ΔΙΑΦΟΡΑ + ΔΙΠΛΑ-ΔΙΠΛΑ + ΣΑΡΩΣΗ + Τελευταία διαφορά + ΑΛΛΑΓΗ ΑΝΤΙΚΕΙΜΕΝΟΥ LFS + ΝΕΟ + Επόμενη διαφορά + ΚΑΜΙΑ ΑΛΛΑΓΗ Ή ΜΟΝΟ ΑΛΛΑΓΕΣ EOL + ΠΑΛΙΟ + Προηγούμενη διαφορά + Αποθήκευση ως Patch + Εμφάνιση κρυφών συμβόλων + Diff δίπλα-δίπλα + ΥΠΟΜΟΝΑΔΑ + ΔΙΑΓΡΑΦΗΚΕ + ΝΕΟ + + {0} μη υποβληθείσες αλλαγές + Εναλλαγή + Επισήμανση σύνταξης + Αναδίπλωση γραμμών + Άνοιγμα στο εργαλείο συγχώνευσης + Εμφάνιση όλων των γραμμών + Μείωση αριθμού ορατών γραμμών + Αύξηση αριθμού ορατών γραμμών + ΕΠΙΛΕΞΤΕ ΑΡΧΕΙΟ ΓΙΑ ΠΡΟΒΟΛΗ ΑΛΛΑΓΩΝ + Ιστορικό φακέλου + Έχει τοπικές αλλαγές + Αναντιστοιχία με το upstream + Ήδη ενημερωμένο + Απόρριψη αλλαγών + Όλες οι τοπικές αλλαγές στο αντίγραφο εργασίας. + Αλλαγές: + Συμπερίληψη αγνοούμενων αρχείων + Συμπερίληψη τροποποιημένων/διαγραμμένων αρχείων + Συμπερίληψη μη παρακολουθούμενων αρχείων + {0} αλλαγές θα απορριφθούν + Δεν μπορείτε να αναιρέσετε αυτή την ενέργεια!!! + Επεξεργασία περιγραφής κλάδου + Στόχος: + Σελιδοδείκτης: + Νέο όνομα: + Στόχος: + Επεξεργασία επιλεγμένης ομάδας + Επεξεργασία επιλεγμένου αποθετηρίου + Στόχος: + Αυτό το αποθετήριο + Fetch + Fetch από όλα τα απομακρυσμένα + Εξαναγκασμός αντικατάστασης τοπικών refs + Fetch χωρίς ετικέτες + Απομακρυσμένο: + Fetch απομακρυσμένων αλλαγών + Θεώρηση ως αμετάβλητο + Προσαρμοσμένη ενέργεια + Απόρριψη... + Απόρριψη {0} αρχείων... + Επίλυση με χρήση ${0}$ + Αποθήκευση ως Patch... + Προσθήκη στο ευρετήριο + Προσθήκη {0} αρχείων στο ευρετήριο + Stash... + Stash {0} αρχείων... + Αφαίρεση από το ευρετήριο + Αφαίρεση {0} αρχείων από το ευρετήριο + Χρήση δικού μου (checkout --ours) + Χρήση δικού τους (checkout --theirs) + Ιστορικό αρχείου + ΑΛΛΑΓΗ + ΠΕΡΙΕΧΟΜΕΝΟ + Git-Flow + Κλάδος ανάπτυξης: + Feature: + Πρόθεμα Feature: + FLOW - Ολοκλήρωση Feature + FLOW - Ολοκλήρωση Hotfix + FLOW - Ολοκλήρωση Release + Στόχος: + Squash κατά τη συγχώνευση + Hotfix: + Πρόθεμα Hotfix: + Αρχικοποίηση Git-Flow + Διατήρηση κλάδου + Κλάδος παραγωγής: + Release: + Πρόθεμα Release: + Έναρξη Feature... + FLOW - Έναρξη Feature + Έναρξη Hotfix... + FLOW - Έναρξη Hotfix + Εισαγάγετε όνομα + Έναρξη Release... + FLOW - Έναρξη Release + Πρόθεμα ετικέτας έκδοσης: + Git LFS + Προσθήκη μοτίβου παρακολούθησης... + Το μοτίβο είναι όνομα αρχείου + Προσαρμοσμένο μοτίβο: + Προσθήκη μοτίβου παρακολούθησης στο Git LFS + Fetch + Εκτελέστε `git lfs fetch` για να κατεβάσετε αντικείμενα Git LFS. Αυτό δεν ενημερώνει το αντίγραφο εργασίας. + Fetch αντικειμένων LFS + Εγκατάσταση hooks του Git LFS + Εμφάνιση κλειδωμάτων + Δεν υπάρχουν κλειδωμένα αρχεία + Κλείδωμα + Εμφάνιση μόνο των δικών μου κλειδωμάτων + Κλειδώματα LFS + Ξεκλείδωμα + Ξεκλείδωμα όλων των δικών μου κλειδωμάτων + Είστε σίγουροι ότι θέλετε να ξεκλειδώσετε όλα τα κλειδωμένα σας αρχεία; + Εξαναγκασμός ξεκλειδώματος + Εκκαθάριση + Εκτελέστε `git lfs prune` για να διαγράψετε παλιά αρχεία LFS από την τοπική αποθήκευση + Pull + Εκτελέστε `git lfs pull` για να κατεβάσετε όλα τα αρχεία Git LFS για το τρέχον ref & checkout + Pull αντικειμένων LFS + Push + Push των μεγάλων αρχείων που βρίσκονται σε αναμονή προς το endpoint του Git LFS + Push αντικειμένων LFS + Απομακρυσμένο: + Παρακολούθηση αρχείων με όνομα '{0}' + Παρακολούθηση όλων των αρχείων *{0} + Επιλογή commit + ΙΣΤΟΡΙΚΟ + ΣΥΓΓΡΑΦΕΑΣ + ΩΡΑ ΣΥΓΓΡΑΦΕΑ + ΩΡΑ COMMIT + ΓΡΑΦΗΜΑ & ΘΕΜΑ + SHA + ΕΠΙΣΗΜΑΝΣΕΙΣ ΣΤΟ ΓΡΑΦΗΜΑ + Όλα + Μόνο ο τρέχων κλάδος + Τρέχων κλάδος & επιλεγμένα commits + Μόνο τα επιλεγμένα commits + ΕΠΙΛΕΓΜΕΝΑ {0} COMMITS + ΕΜΦΑΝΙΣΗ ΣΤΗΛΩΝ + Κρατήστε 'Ctrl' ή 'Shift' για να επιλέξετε πολλαπλά commits. + Κρατήστε ⌘ ή ⇧ για να επιλέξετε πολλαπλά commits. + ΣΥΜΒΟΥΛΕΣ: + Άνοιγμα σε ξεχωριστό παράθυρο + Λεπτομέρειες commit + Σύγκριση αναθεωρήσεων + Αναφορά συντομεύσεων πληκτρολογίου + ΚΑΘΟΛΙΚΑ + Κλωνοποίηση νέου αποθετηρίου + Κλείσιμο τρέχουσας καρτέλας + Μετάβαση στην επόμενη καρτέλα + Μετάβαση στην προηγούμενη καρτέλα + Δημιουργία νέας καρτέλας + Άνοιγμα τοπικού αποθετηρίου + Άνοιγμα διαλόγου Προτιμήσεων + Εμφάνιση αναπτυσσόμενου μενού χώρων εργασίας + Εναλλαγή ενεργής καρτέλας + Μεγέθυνση/σμίκρυνση + ΑΠΟΘΕΤΗΡΙΟ + Commit των αλλαγών στο ευρετήριο + Commit και push των αλλαγών στο ευρετήριο + Προσθήκη όλων των αλλαγών στο ευρετήριο και commit + Δημιουργία νέου κλάδου + Fetch, ξεκινά άμεσα + Λειτουργία πίνακα ελέγχου (Προεπιλογή) + Μετάβαση στον απόγονο του επιλεγμένου commit + Μετάβαση στον γονέα του επιλεγμένου commit + Άνοιγμα παλέτας εντολών + Λειτουργία αναζήτησης commit + Pull, ξεκινά άμεσα + Push, ξεκινά άμεσα + Εξαναγκασμός επαναφόρτωσης αυτού του αποθετηρίου + Ανάπτυξη/σύμπτυξη πίνακα λεπτομερειών στο `ΙΣΤΟΡΙΚΟ` + Μετάβαση στις 'ΤΟΠΙΚΕΣ ΑΛΛΑΓΕΣ' + Μετάβαση στο 'ΙΣΤΟΡΙΚΟ' + Μετάβαση στα 'STASHES' + Απόρριψη + Προσθήκη στο ευρετήριο + Αφαίρεση από το ευρετήριο + Αρχικοποίηση αποθετηρίου + Θέλετε να εκτελέσετε την εντολή `git init` σε αυτή τη διαδρομή; + Το άνοιγμα του αποθετηρίου απέτυχε. Αιτία: + Διαδρομή: + Cherry-Pick σε εξέλιξη. + Επεξεργασία commit + Συγχώνευση σε εξέλιξη. + Συγχώνευση + Rebase σε εξέλιξη. + Σταμάτησε στο + Αναίρεση σε εξέλιξη. + Αναίρεση commit + Διαδραστικό rebase + Stash & επανεφαρμογή τοπικών αλλαγών + Παράκαμψη του pre-rebase hook + Πάνω στο: + Σύρετε και αφήστε για αναδιάταξη των commits + Κλάδος-στόχος: + Αντιγραφή συνδέσμου + Άνοιγμα στον περιηγητή + Εντολές + ΣΦΑΛΜΑ + ΕΙΔΟΠΟΙΗΣΗ + Άνοιγμα αποθετηρίων + Καρτέλες + Χώροι εργασίας + Συγχώνευση κλάδου + Προσαρμογή μηνύματος συγχώνευσης + Στο: + Τρόπος συγχώνευσης: + Πηγή: + Έλεγχος για συγχώνευση... + Η συγχώνευση μπορεί να γίνει χωρίς συγκρούσεις + Παρουσιάστηκε άγνωστο σφάλμα κατά τον έλεγχο για συγχώνευση + Η συγχώνευση θα προκαλέσει συγκρούσεις + Πρώτα το δικό μου, μετά το δικό τους + Πρώτα το δικό τους, μετά το δικό μου + ΧΡΗΣΗ ΚΑΙ ΤΩΝ ΔΥΟ + Όλες οι συγκρούσεις επιλύθηκαν + Απομένουν {0} συγκρούσεις + ΔΙΚΟ ΜΟΥ + Επόμενη σύγκρουση + Προηγούμενη σύγκρουση + ΑΠΟΤΕΛΕΣΜΑ + ΑΠΟΘΗΚΕΥΣΗ & ΠΡΟΣΘΗΚΗ + ΔΙΚΟ ΤΟΥΣ + Συγκρούσεις συγχώνευσης + Απόρριψη μη αποθηκευμένων αλλαγών; + ΧΡΗΣΗ ΔΙΚΟΥ ΜΟΥ + ΧΡΗΣΗ ΔΙΚΟΥ ΤΟΥΣ + ΑΝΑΙΡΕΣΗ + Συγχώνευση (πολλαπλή) + Commit όλων των αλλαγών + Στρατηγική: + Στόχοι: + Μετακίνηση υπομονάδας + Μετακίνηση σε: + Υπομονάδα: + Μετακίνηση κόμβου αποθετηρίου + Επιλέξτε γονικό κόμβο για: + Όνομα: + ΟΧΙ + Το Git ΔΕΝ έχει ρυθμιστεί. Μεταβείτε στις [Προτιμήσεις] και ρυθμίστε το πρώτα. + Άνοιγμα + Προεπιλεγμένος επεξεργαστής (συστήματος) + Άνοιγμα φακέλου αποθήκευσης δεδομένων + Άνοιγμα αρχείου + Άνοιγμα σε εξωτερικό εργαλείο συγχώνευσης + Άνοιγμα τοπικού αποθετηρίου + Σελιδοδείκτης: + Ομάδα: + Φάκελος: + Προαιρετικό. + Δημιουργία νέας καρτέλας + Κλείσιμο καρτέλας + Κλείσιμο άλλων καρτελών + Κλείσιμο καρτελών στα δεξιά + Αντιγραφή διαδρομής αποθετηρίου + Επεξεργασία + Μετακίνηση σε χώρο εργασίας + Ανανέωση + Αποθετήρια + Επικόλληση + {0} ημέρες πριν + 1 ώρα πριν + {0} ώρες πριν + Μόλις τώρα + Τον προηγούμενο μήνα + Πέρυσι + {0} λεπτά πριν + {0} μήνες πριν + {0} χρόνια πριν + Χθες + Προτιμήσεις + AI + Επιπλέον prompt (χρησιμοποιήστε `-` για να απαριθμήσετε τις απαιτήσεις σας) + Κλειδί API + Μοντέλο + Αυτόματη ανάκτηση διαθέσιμων model-ids + Όνομα + Η τιμή που εισήχθη είναι το όνομα για φόρτωση του κλειδιού API από το ENV + Διακομιστής + ΕΜΦΑΝΙΣΗ + Προεπιλεγμένη γραμματοσειρά + Πλάτος tab επεξεργαστή + Μέγεθος γραμματοσειράς + Προεπιλογή + Επεξεργαστής + Γραμματοσειρά σταθερού πλάτους + Θέμα + Παρακάμψεις θέματος + Χρήση μπαρών κύλισης αυτόματης απόκρυψης + Χρήση σταθερού πλάτους καρτελών στη γραμμή τίτλου + Χρήση εγγενούς πλαισίου παραθύρου + ΕΡΓΑΛΕΙΟ DIFF/MERGE + Ορίσματα Diff + Διαθέσιμες μεταβλητές: $LOCAL, $REMOTE + Ορίσματα Merge + Διαθέσιμες μεταβλητές: $BASE, $LOCAL, $REMOTE, $MERGED + Διαδρομή εγκατάστασης + Εισαγάγετε τη διαδρομή του εργαλείου diff/merge + Εργαλείο + ΓΕΝΙΚΑ + Έλεγχος για ενημερώσεις κατά την εκκίνηση + Μορφή ημερομηνίας + Ενεργοποίηση συμπαγών φακέλων στο δέντρο αλλαγών + Γλώσσα + Commits ιστορικού + Εμφάνιση της σελίδας `ΤΟΠΙΚΕΣ ΑΛΛΑΓΕΣ` από προεπιλογή + Εμφάνιση της καρτέλας `ΑΛΛΑΓΕΣ` στις λεπτομέρειες commit από προεπιλογή + Εμφάνιση απογόνων στις λεπτομέρειες commit + Εμφάνιση σχετικού χρόνου στο γράφημα commit + Εμφάνιση ετικετών στο γράφημα commit + Μήκος οδηγού θέματος + 24ωρη μορφή + Χρήση συμπαγών ονομάτων κλάδων στο γράφημα commit + Δημιουργία προεπιλεγμένου avatar τύπου Github + GIT + Ενεργοποίηση αυτόματου CRLF + Προεπιλεγμένος φάκελος κλωνοποίησης + Email χρήστη + Καθολικό email χρήστη git + Εκκαθάριση νεκρών κλάδων μετά το fetch + Αγνόηση CR στο τέλος γραμμής στο diff κειμένου + Απαιτείται Git (>= 2.25.1) από αυτή την εφαρμογή + Διαδρομή εγκατάστασης + Ενεργοποίηση επαλήθευσης HTTP SSL + Χρήση git-credential-libsecret αντί για git-credential-manager + Όνομα χρήστη + Καθολικό όνομα χρήστη git + Stash & επανεφαρμογή αλλαγών από προεπιλογή κατά το checkout ή τη συγχώνευση κλάδων + Έκδοση Git + ΥΠΟΓΡΑΦΗ GPG + Υπογραφή GPG στα commit + Μορφή GPG + Διαδρομή εγκατάστασης προγράμματος + Εισαγάγετε τη διαδρομή του εγκατεστημένου προγράμματος gpg + Υπογραφή GPG στις ετικέτες + Κλειδί υπογραφής χρήστη + Κλειδί υπογραφής gpg του χρήστη + ΕΝΣΩΜΑΤΩΣΗ + SHELL/ΤΕΡΜΑΤΙΚΟ + Ορίσματα + Χρησιμοποιήστε το '.' για να υποδείξετε τον φάκελο εργασίας + Διαδρομή + Shell/Τερματικό + Εκκαθάριση απομακρυσμένου + Στόχος: + Εκκαθάριση Worktrees + Εκκαθάριση πληροφοριών worktree στο `$GIT_COMMON_DIR/worktrees` + Pull + Απομακρυσμένος κλάδος: + Στο: + Τοπικές αλλαγές: + Απομακρυσμένο: + Pull (Fetch & Merge) + Χρήση rebase αντί για συγχώνευση + Push + Βεβαιωθείτε ότι έχει γίνει push στις υπομονάδες + Εξαναγκασμένο push + Τοπικός κλάδος: + ΝΕΟ + Απομακρυσμένο: + Αναθεώρηση: + Push αναθεώρησης σε απομακρυσμένο + Push αλλαγών σε απομακρυσμένο + Απομακρυσμένος κλάδος: + Ορισμός ως κλάδου παρακολούθησης + Push όλων των ετικετών + Push ετικέτας σε απομακρυσμένο + Push σε όλα τα απομακρυσμένα + Απομακρυσμένο: + Ετικέτα: + Push σε ΝΕΟ κλάδο + Εισαγάγετε το όνομα του νέου απομακρυσμένου κλάδου: + Έξοδος + Rebase τρέχοντος κλάδου + Stash & επανεφαρμογή τοπικών αλλαγών + Παράκαμψη του pre-rebase hook + Πάνω στο: + Έλεγχος για rebase ... + Το rebase μπορεί να γίνει χωρίς συγκρούσεις + Παρουσιάστηκε άγνωστο σφάλμα κατά τον έλεγχο για rebase + Το rebase θα προκαλέσει συγκρούσεις + Προσθήκη απομακρυσμένου + Επεξεργασία απομακρυσμένου + Όνομα: + Όνομα απομακρυσμένου + URL αποθετηρίου: + URL απομακρυσμένου αποθετηρίου git + Αντιγραφή URL + Προσαρμοσμένη ενέργεια + Διαγραφή... + Επεξεργασία... + Ενεργοποίηση αυτόματου Fetch + Fetch + Άνοιγμα στον περιηγητή + Εκκαθάριση + Επιβεβαίωση αφαίρεσης Worktree + Ενεργοποίηση της επιλογής `--force` + Στόχος: + Μετονομασία κλάδου + Νέο όνομα: + Μοναδικό όνομα για αυτόν τον κλάδο + Κλάδος: + ΜΑΤΑΙΩΣΗ + Αυτόματο fetch αλλαγών από τα απομακρυσμένα... + Ταξινόμηση + Κατά ημερομηνία committer + Κατά όνομα + Εκκαθάριση (GC & Prune) + Εκτέλεση της εντολής `git gc` για αυτό το αποθετήριο. + Εκκαθάριση όλων + Εκκαθάριση + Ρύθμιση αυτού του αποθετηρίου + ΣΥΝΕΧΕΙΑ + Προσαρμοσμένες ενέργειες + Καμία προσαρμοσμένη ενέργεια + Πίνακας ελέγχου + Απόρριψη όλων των αλλαγών + Άνοιγμα στον περιηγητή αρχείων + Αναζήτηση κλάδων/ετικετών/υπομονάδων + Ορατότητα στο γράφημα + Μη ορισμένο + Απόκρυψη στο γράφημα commit + Φιλτράρισμα στο γράφημα commit + ΔΙΑΤΑΞΗ + Οριζόντια + Κάθετη + ΣΕΙΡΑ COMMITS + Ημερομηνία commit + Τοπολογικά + ΤΟΠΙΚΟΙ ΚΛΑΔΟΙ + Περισσότερες επιλογές... + Μετάβαση στο HEAD + Δημιουργία κλάδου + ΕΚΚΑΘΑΡΙΣΗ ΕΙΔΟΠΟΙΗΣΕΩΝ + Άνοιγμα ως φάκελος + Άνοιγμα σε {0} + Άνοιγμα σε εξωτερικά εργαλεία + ΑΠΟΜΑΚΡΥΣΜΕΝΑ + Προσθήκη απομακρυσμένου + ΕΠΙΛΥΣΗ + Αναζήτηση commit + Συγγραφέας + Committer + Περιεχόμενο + Μήνυμα + Διαδρομή + SHA + Τρέχων κλάδος + Μόνο commits με αναφορές + Μόνο πρώτος γονέας + ΕΜΦΑΝΙΣΗ ΣΗΜΑΙΩΝ + Εμφάνιση χαμένων commits + Εμφάνιση υπομονάδων ως δέντρο + Εμφάνιση ετικετών ως δέντρο + ΠΑΡΑΛΕΙΨΗ + Στατιστικά + ΥΠΟΜΟΝΑΔΕΣ + Προσθήκη υπομονάδας + Ενημέρωση υπομονάδας + ΕΤΙΚΕΤΕΣ + Νέα ετικέτα + Κατά ημερομηνία δημιουργίας + Κατά όνομα + Ταξινόμηση + Άνοιγμα στο τερματικό + Προβολή καταγραφών + Επίσκεψη '{0}' στον περιηγητή + WORKTREES + Προσθήκη Worktree + Εκκαθάριση + URL αποθετηρίου Git + Επαναφορά τρέχοντος κλάδου σε αναθεώρηση + Τρόπος επαναφοράς: + Μετακίνηση σε: + Τρέχων κλάδος: + Επαναφορά κλάδου (χωρίς checkout) + Μετακίνηση σε: + Κλάδος: + Εμφάνιση στον περιηγητή αρχείων + Αναίρεση commit + Commit: + Commit των αλλαγών αναίρεσης + Εκτελείται. Παρακαλώ περιμένετε... + ΑΠΟΘΗΚΕΥΣΗ + Αποθήκευση ως... + Το patch αποθηκεύτηκε με επιτυχία! + Σάρωση αποθετηρίων + Ριζικός φάκελος: + Σάρωση άλλου προσαρμοσμένου φακέλου + Έλεγχος για ενημερώσεις... + Είναι διαθέσιμη νέα έκδοση αυτού του λογισμικού: + Τρέχουσα έκδοση: + Ο έλεγχος για ενημερώσεις απέτυχε! + Λήψη + Παράλειψη αυτής της έκδοσης + Ημερομηνία έκδοσης νέας έκδοσης: + Ενημέρωση λογισμικού + Δεν υπάρχουν διαθέσιμες ενημερώσεις αυτή τη στιγμή. + Ορισμός κλάδου υπομονάδας + Υπομονάδα: + Τρέχων: + Αλλαγή σε: + Προαιρετικό. Όταν είναι κενό, ορίζεται στην προεπιλογή. + Ορισμός κλάδου παρακολούθησης + Κλάδος: + Κατάργηση upstream + Upstream: + Αντιγραφή SHA + Μετάβαση σε + Ιδιωτικό κλειδί SSH: + Διαδρομή αποθήκευσης ιδιωτικού κλειδιού SSH + ΕΝΑΡΞΗ + Stash + Συμπερίληψη μη παρακολουθούμενων αρχείων + Μήνυμα: + Προαιρετικό. Μήνυμα αυτού του stash + Λειτουργία: + Μόνο τα αρχεία στο ευρετήριο + Θα γίνουν stash τόσο οι αλλαγές στο ευρετήριο όσο και αυτές εκτός ευρετηρίου των επιλεγμένων αρχείων!!! + Stash τοπικών αλλαγών + Εφαρμογή + Εφαρμογή αλλαγών + Checkout νέου κλάδου + Αντιγραφή μηνύματος + Απόρριψη + Αποθήκευση ως Patch... + Απόρριψη Stash + Απόρριψη: + STASHES + ΑΛΛΑΓΕΣ + STASHES + Στατιστικά + ΕΠΙΣΚΟΠΗΣΗ + ΜΗΝΑΣ + ΕΒΔΟΜΑΔΑ + ΣΥΓΓΡΑΦΕΙΣ: + COMMITS: + ΥΠΟΜΟΝΑΔΕΣ + Προσθήκη υπομονάδας + ΚΛΑΔΟΣ + Κλάδος + Σχετική διαδρομή + Απο-αρχικοποίηση + Fetch ένθετων υπομονάδων + Ιστορικό + Μετακίνηση... + Άνοιγμα αποθετηρίου + Σχετική διαδρομή: + Σχετικός φάκελος για την αποθήκευση αυτής της υπομονάδας. + Διαγραφή + Ορισμός κλάδου + Αλλαγή URL + ΚΑΤΑΣΤΑΣΗ + τροποποιημένη + μη αρχικοποιημένη + η αναθεώρηση άλλαξε + μη συγχωνευμένη + Ενημέρωση + URL + Λεπτομέρειες αλλαγής υπομονάδας + ΑΝΟΙΓΜΑ ΛΕΠΤΟΜΕΡΕΙΩΝ + ΟΚ + ΔΗΜΙΟΥΡΓΟΣ ΕΤΙΚΕΤΑΣ + ΩΡΑ + Σύγκριση 2 ετικετών + Σύγκριση με... + Σύγκριση με το HEAD + Μήνυμα + Όνομα + Δημιουργός ετικέτας + Αντιγραφή ονόματος ετικέτας + Προσαρμοσμένη ενέργεια + Διαγραφή ${0}$... + Διαγραφή {0} επιλεγμένων ετικετών... + Push ${0}$... + Ενημέρωση υπομονάδων + Όλες οι υπομονάδες + Αρχικοποίηση όπου χρειάζεται + Υπομονάδα: + Ενημέρωση στον απομακρυσμένο κλάδο παρακολούθησης της υπομονάδας + URL: + Καταγραφές + ΕΚΚΑΘΑΡΙΣΗ ΟΛΩΝ + Αντιγραφή + Διαγραφή + Προειδοποίηση + Σελίδα υποδοχής + Δημιουργία ομάδας + Δημιουργία υπο-ομάδας + Κλωνοποίηση αποθετηρίου + Διαγραφή + ΥΠΟΣΤΗΡΙΖΕΤΑΙ ΜΕΤΑΦΟΡΑ & ΑΠΟΘΕΣΗ ΦΑΚΕΛΟΥ. ΥΠΟΣΤΗΡΙΖΕΤΑΙ ΠΡΟΣΑΡΜΟΣΜΕΝΗ ΟΜΑΔΟΠΟΙΗΣΗ. + Επεξεργασία + Μετακίνηση σε άλλη ομάδα + Άνοιγμα όλων των αποθετηρίων + Άνοιγμα αποθετηρίου + Άνοιγμα τερματικού + Επανασάρωση αποθετηρίων στον προεπιλεγμένο φάκελο κλωνοποίησης + Αναζήτηση αποθετηρίων... + ΤΟΠΙΚΕΣ ΑΛΛΑΓΕΣ + Git Ignore + Αγνόηση όλων των αρχείων *{0} + Αγνόηση αρχείων *{0} στον ίδιο φάκελο + Αγνόηση μη παρακολουθούμενων αρχείων σε αυτόν τον φάκελο + Αγνόηση μόνο αυτού του αρχείου + Τροποποίηση + Μπορείτε να προσθέσετε αυτό το αρχείο στο ευρετήριο τώρα. + Εκκαθάριση ιστορικού + Είστε σίγουροι ότι θέλετε να εκκαθαρίσετε όλο το ιστορικό μηνυμάτων commit; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί. + COMMIT + COMMIT & PUSH + Πρότυπο/Ιστορικό + Ενεργοποίηση συμβάντος κλικ + Commit (Επεξεργασία) + Προσθήκη όλων των αλλαγών στο ευρετήριο και commit + Δημιουργείτε commit σε αποσυνδεδεμένο (detached) HEAD. Θέλετε να συνεχίσετε; + Έχετε προσθέσει στο ευρετήριο {0} αρχείο(-α) αλλά εμφανίζονται μόνο {1} αρχείο(-α) ({2} αρχεία είναι φιλτραρισμένα). Θέλετε να συνεχίσετε; + ΕΝΤΟΠΙΣΤΗΚΑΝ ΣΥΓΚΡΟΥΣΕΙΣ + ΣΥΓΧΩΝΕΥΣΗ + Συγχώνευση με εξωτερικό εργαλείο + ΑΝΟΙΓΜΑ ΟΛΩΝ ΤΩΝ ΣΥΓΚΡΟΥΣΕΩΝ ΣΕ ΕΞΩΤΕΡΙΚΟ ΕΡΓΑΛΕΙΟ ΣΥΓΧΩΝΕΥΣΗΣ + ΟΙ ΣΥΓΚΡΟΥΣΕΙΣ ΑΡΧΕΙΩΝ ΕΠΙΛΥΘΗΚΑΝ + ΧΡΗΣΗ ΔΙΚΟΥ ΜΟΥ + ΧΡΗΣΗ ΔΙΚΟΥ ΤΟΥΣ + ΣΥΜΠΕΡΙΛΗΨΗ ΜΗ ΠΑΡΑΚΟΛΟΥΘΟΥΜΕΝΩΝ ΑΡΧΕΙΩΝ + ΔΕΝ ΥΠΑΡΧΟΥΝ ΠΡΟΣΦΑΤΑ ΜΗΝΥΜΑΤΑ ΕΙΣΟΔΟΥ + ΔΕΝ ΥΠΑΡΧΟΥΝ ΠΡΟΤΥΠΑ COMMIT + Χωρίς έλεγχο + Επαναφορά συγγραφέα + Προσυπογραφή + ΣΤΟ ΕΥΡΕΤΗΡΙΟ + ΑΦΑΙΡΕΣΗ + ΑΦΑΙΡΕΣΗ ΟΛΩΝ + ΕΚΤΟΣ ΕΥΡΕΤΗΡΙΟΥ + ΠΡΟΣΘΗΚΗ + ΠΡΟΣΘΗΚΗ ΟΛΩΝ + ΠΡΟΒΟΛΗ ΑΡΧΕΙΩΝ ΠΟΥ ΘΕΩΡΟΥΝΤΑΙ ΑΜΕΤΑΒΛΗΤΑ + Πρότυπο: ${0}$ + ΧΩΡΟΣ ΕΡΓΑΣΙΑΣ: + Ρύθμιση χώρων εργασίας... + WORKTREE + ΚΛΑΔΟΣ + Αντιγραφή διαδρομής + HEAD + Κλείδωμα + Άνοιγμα + ΔΙΑΔΡΟΜΗ + Αφαίρεση + Ξεκλείδωμα + ΝΑΙ + diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index a80b66c59..5e9f844fc 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -27,9 +27,11 @@ Hide Others Show All 3-Way Merge - Patch File: Select .patch file to apply Ignore whitespace changes + Source: + File + Clipboard Apply Patch Whitespace: Apply Stash @@ -51,10 +53,12 @@ Bisect Abort Bad - Bisecting. Is current HEAD good or bad? Good Skip - Bisecting. Mark current commit as good or bad and checkout another one. + Bisecting. Please checkout another one then mark it as good or bad. + Bisecting. Mark current commit as bad or checkout another one then mark it as bad. + Bisecting. Mark current commit as good or bad and checkout another one. + Bisecting. Is current HEAD good or bad? Blame Blame on Previous Revision Ignore whitespace changes @@ -151,8 +155,10 @@ Compare with HEAD Compare with Worktree Author + Author Time Message Committer + Committer Time SHA Subject Custom Action @@ -163,7 +169,6 @@ Interactively Rebase ${0}$ on ${1}$ Reword... Squash into Parent... - Merge to ${0}$ Merge ... Push ${0}$ to ${1}$ Rebase ${0}$ on ${1}$ @@ -248,6 +253,7 @@ Minute(s) Conventional Commit Types Default Remote + Enable `--recursive` when auto-updating submodules Preferred Merge Mode ISSUE TRACKER Add Azure DevOps Rule @@ -305,6 +311,7 @@ Type of Change: Copy Copy All Text + Copy as Patch Copy Full Path Copy Path Create Branch... @@ -358,6 +365,7 @@ Tag: Delete from remote repositories BINARY DIFF + EMPTY FILE File Mode Changed First Difference Ignore Whitespace Changes @@ -489,7 +497,6 @@ AUTHOR AUTHOR TIME COMMIT TIME - DATE TIME GRAPH & SUBJECT SHA HIGHLIGHTS IN GRAPH @@ -569,6 +576,10 @@ Into: Merge Option: Source: + Testing for merge... + Merge can be done without conflicts + Unknown error occurs while testing for merge + Merge will cause conflicts First Mine, then Theirs First Theirs, then Mine USE BOTH @@ -662,7 +673,6 @@ Enable compact folders in changes tree Language History Commits - Show author time instead of commit time in graph Show `LOCAL CHANGES` page by default Show `CHANGES` tab in commit detail by default Show children in the commit details @@ -670,6 +680,7 @@ Show tags in commit graph Subject Guide Length 24-Hours + Use compact branch names in commit graph Generate Github style default avatar GIT Enable Auto CRLF @@ -734,6 +745,10 @@ Stash & reapply local changes Bypass the pre-rebase hook On: + Testing for rebase ... + Rebase can be done without conflicts + Unknown error occurs while testing for rebase + Rebase will cause conflicts Add Remote Edit Remote Name: @@ -927,12 +942,12 @@ Custom Action Delete ${0}$... Delete selected {0} tags... - Merge ${0}$ into ${1}$... Push ${0}$... Update Submodules All submodules Initialize as needed Submodule: + Update nested submodules Update to submodule's remote tracking branch URL: Logs diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index fd31af8d6..1edbb78a6 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -31,7 +31,6 @@ Ocultar Otros Mostrar Todo Merge a 3 vías (3-Way) - Archivo del Parche: Seleccionar archivo .patch para aplicar Ignorar cambios de espacios en blanco Aplicar Parche @@ -55,10 +54,10 @@ Bisect Abortar Malo - Bisecting. ¿Es el HEAD actual bueno o malo? Bueno Saltar - Bisecting. Marcar el commit actual como bueno o malo y revisar otro. + Bisecting. Marcar el commit actual como bueno o malo y revisar otro. + Bisecting. ¿Es el HEAD actual bueno o malo? Blame Blame sobre la Revisión Previa Ignorar cambios de espacios en blanco @@ -155,8 +154,10 @@ Comparar con HEAD Comparar con Worktree Autor + Fecha/Hora del Autor Mensaje Committer + Fecha/Hora del Committer SHA Asunto Acción personalizada @@ -167,7 +168,6 @@ Hacer Rebase interactivamente ${0}$ en ${1}$ Reescribir... Squash en el Padre... - Merge a ${0}$ Merge ... Push ${0}$ a ${1}$ Rebase ${0}$ en ${1}$ @@ -177,6 +177,7 @@ CAMBIOS archivo(s) modificado(s) Buscar Cambios... + Colapsar detalles ARCHIVOS Archivo LFS Buscar Archivos... @@ -202,6 +203,11 @@ Ingresa el mensaje de commit. ¡Por favor usa una línea en blanco para separar el título y la descripción! ASUNTO Comparar + CAMBIOS + COMMITS + SOLO COMMITS A LA IZQUIERDA + SOLO COMMITS A LA DERECHA + Tips: Puedes hacer cherry-pick a los commits seleccionados si el otro lado está en HEAD (usando el menú contextual). Configurar Repositorio PLANTILLA DE COMMIT Parámetros incorporados: @@ -487,14 +493,21 @@ AUTOR HORA DEL AUTOR FECHA DE COMMIT - FECHA HORA GRÁFICO y ASUNTO SHA + DESTACADOS EN EL GRÁFICO + Todos + Solo la Rama Actual + Rama Actual y los Commits Seleccionados + Solo los Commits Seleccionados {0} COMMITS SELECCIONADOS MOSTRAR COLUMNAS Mantén 'Ctrl' o 'Shift' para seleccionar múltiples commits. Mantén ⌘ o ⇧ para seleccionar múltiples commits. CONSEJOS: + Abrir en una ventana separada + Detalles del Commit + Comparación de Revisiones Referencia de Atajos de Teclado GLOBAL Clonar repositorio nuevo @@ -521,6 +534,7 @@ Pull, empieza directamente Push, empieza directamente Forzar a recargar este repositorio + Expandir/Colapsar el panel de detalles en el `HISTORIAL`/`HISTORY` Cambiar a 'Cambios' Cambiar a 'Historias' Cambiar a 'Stashes' @@ -541,6 +555,7 @@ Haciendo revert del commit Rebase Interactivo Stash y volver a aplicar cambios locales + Saltar el hook de pre-rebase En: Arrastrar y soltar para reordenar commits Rama Objetivo: @@ -557,6 +572,10 @@ En: Opción de Merge: Rama Fuente: + Pruebas para hacer merge... + El merge se puede realizar sin conflictos + Error desconocido ocurrido al probar el merge + Hacer merge causará conflictos Primero Míos, después Suyos Primero Suyos, después Míos USAR AMBOS @@ -619,6 +638,8 @@ OPEN AI Prompt adicional (Usa `-` para listar tus requerimientos) Clave API + Modelo + Traer automáticamente los model-ids disponibles Nombre El valor ingresado es el nombre de la clave API a cargar desde ENV Servidor @@ -648,13 +669,14 @@ Habilitar carpetas compactas en el árbol de cambios Idioma Commits en el historial - Mostrar hora del autor en lugar de la hora del commit en el gráfico Mostrar la página `CAMBIOS LOCALES` por defecto Mostrar pestaña de `CAMBIOS` en los detalles del commit por defecto Mostrar hijos en los detalles de commit + Mostrar hora relativa en el gráfico de commits Mostrar etiquetas en el gráfico de commit Longitud de la guía del asunto 24-Horas + Utilizar nombres de ramas compactos en el gráfico de commits Generar avatar con estilo por defecto de Github GIT Habilitar Auto CRLF @@ -717,7 +739,12 @@ Salir Rebase Rama Actual Stash y volver a aplicar cambios locales + Saltar el hook de pre-rebase En: + Pruebas para hacer rebase ... + El rebase se puede realizar sin conflictos + Error desconocido ocurrido al probar el rebase + Hacer rebase causará conflictos Añadir Remoto Editar Remoto Nombre: @@ -911,7 +938,6 @@ Acción Personalizada Eliminar ${0}$... Eliminar {0} etiquetas seleccionadas... - Merge ${0}$ en ${1}$... Push ${0}$... Actualizar Submódulos Todos los submódulos diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index c59eefacc..9b5d3b002 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -4,7 +4,9 @@ À propos + Révision source : À propos de SourceGit + Date de publication : {0} Notes de Version Client Git Open Source et Gratuit Ajouter le(s) Fichier(s) à Ignorer @@ -24,9 +26,11 @@ Modèle RE-GÉNÉRER Utiliser l'IA pour générer un message de commit + Utiliser Masquer SourceGit + Masquer les autres Tout Afficher - Fichier de patch : + Fusion à 3 voies Selectionner le fichier .patch à appliquer Ignorer les changements d'espaces blancs Appliquer le patch @@ -50,20 +54,26 @@ Bisect Annuler Mauvais - Bisect en cours. Le HEAD actuel est-il bon ou mauvais ? Bon Passer - Bisect en cours. Marquer le commit actuel comme bon ou mauvais et en récupérer un autre. + Bisect en cours. Marquer le commit actuel comme bon ou mauvais et en récupérer un autre. + Bisect en cours. Le HEAD actuel est-il bon ou mauvais ? Blâme Blâmer sur la révision précédente + Ignorer les changements d'espaces LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!! Récupérer ${0}$... + Comparer les 2 branches sélectionnées + Comparer avec... + Comparer avec HEAD + Comparer avec ${0}$ Copier le nom de la branche Créer une PR... Créer une PR pour l'upstream ${0}$... Action personnalisée Supprimer ${0}$... Supprimer {0} branches sélectionnées + Modifier la description de ${0}$... Fast-Forward vers ${0}$ Fetch ${0}$ vers ${1}$... Git Flow - Terminer ${0}$ @@ -91,6 +101,9 @@ Réinitialiser à la révision parente Réinitialiser à cette révision Générer un message de commit + Fusion (intégré) + Fusion (externe) + Réinitialiser le(s) fichier(s) à ${0}$ CHANGER LE MODE D'AFFICHAGE Afficher comme liste de dossiers/fichiers Afficher comme liste de chemins @@ -105,8 +118,12 @@ Changements locaux : Branche : Votre HEAD actuel contient un ou plusieurs commits non connectés à une branche/tag ! Voulez-vous continuer ? + Les sous-modules suivants doivent être mis à jour :{0}Voulez-vous les mettre à jour ? Récupérer & Fast-Forward Fast-Forward vers : + Créer une branche depuis le stash + Nouvelle branche : + Stash : Cherry-Pick de ce commit Ajouter la source au message de commit Commit : @@ -118,6 +135,8 @@ Cloner repository distant Paramètres supplémentaires : Arguments additionnels au clônage. Optionnel. + Signet : + Groupe : Nom local : Nom de dépôt. Optionnel. Dossier parent : @@ -125,6 +144,10 @@ URL du dépôt : FERMER Éditeur + Branches + Branches et tags + Actions personnalisées du dépôt + Fichiers de révision Récupérer ce commit Cherry-Pick ce commit Cherry-Pick ... @@ -143,7 +166,6 @@ Rebaser Interactivement ${0}$ sur ${1}$ Reformuler... Squash dans le Parent... - Fusionner dans ${0}$ Fusionner ... Pousser ${0}$ vers ${1}$ Rebaser ${0}$ sur ${1}$ @@ -153,6 +175,7 @@ CHANGEMENTS fichier(s) modifié(s) Rechercher les changements... + Réduire les détails FICHIERS Fichier LFS Rechercher des fichiers... @@ -174,8 +197,15 @@ SHA Signataire : Ouvrir dans le navigateur + COL + Saisissez le message de commit. Utilisez une ligne vide pour séparer le sujet et la description ! SUJET Comparer + CHANGEMENTS + COMMITS + COMMITS UNIQUEMENT À GAUCHE + COMMITS UNIQUEMENT À DROITE + Astuce : vous pouvez cherry-pick les commits sélectionnés si l'autre côté est HEAD (via le menu contextuel). Configurer le dépôt MODÈLE DE COMMIT Paramètres intégrés : @@ -215,6 +245,7 @@ Adresse e-mail Adresse e-mail GIT + Demander avant mise à jour automatique des sous-modules Fetch les dépôts distants automatiquement minute(s) Types de commit conventionnels @@ -251,8 +282,11 @@ Libellé : Options : Utiliser '|' comme délimiteur pour les options + Formateur de chaîne : + Optionnel. Utilisé pour formater la sortie. Ignoré si vide. Utilisez `${VALUE}` pour représenter la chaîne d'entrée. Les variables intégrées ${REPO}, ${REMOTE}, ${BRANCH}, ${BRANCH_FRIENDLY_NAME}, ${SHA}, ${FILE}, et ${TAG} restent disponibles ici Type : + Utiliser le nom convivial : Espaces de travail Couleur Nom @@ -260,6 +294,7 @@ CONTINUER Commit vide détecté ! Voulez-vous continuer (--allow-empty) ? TOUT INDEXER & COMMIT + INDEXER LA SÉLECTION & COMMIT Commit vide détecté ! Voulez-vous continuer (--allow-empty) ou tout indexer puis commit ? Redémarrage Requis Vous devez redémarrer cette application pour appliquer les changements. @@ -345,6 +380,7 @@ SOUS-MODULE SUPPRIMÉ NOUVEAU + + {0} changements non commités Permuter Coloration syntaxique Retour à la ligne @@ -361,9 +397,12 @@ Tous les changements dans la copie de travail. Changements : Inclure les fichiers ignorés + Inclure les fichiers modifiés/supprimés Inclure les fichiers non suivis {0} changements seront rejetés Vous ne pouvez pas annuler cette action !!! + Modifier la description de la branche + Cible : Signet : Nouveau nom : Cible : @@ -378,6 +417,7 @@ Remote : Récupérer les changements distants Présumer inchangé + Action personnalisée Rejeter... Rejeter {0} fichiers... Résoudre en utilisant ${0}$ @@ -446,16 +486,26 @@ Dépôt : Suivre les fichiers appelés '{0}' Suivre tous les fichiers *{0} + Sélectionner un commit Historique AUTEUR HEURE DE L'AUTEUR HEURE DE COMMIT GRAPHE & SUJET SHA + MISE EN ÉVIDENCE AU GRAPHE + Tout + Branche courante uniquement + Branche courante et commits sélectionnés + Commits sélectionnés uniquement {0} COMMITS SÉLECTIONNÉS + AFFICHER LES COLONNES Maintenir 'Ctrl' ou 'Shift' enfoncée pour sélectionner plusieurs commits. Maintenir ⌘ ou ⇧ enfoncée pour sélectionner plusieurs commits. CONSEILS: + Ouvrir dans une fenêtre séparée + Détails du commit + Comparaison de révision Référence des raccourcis clavier GLOBAL Cloner un nouveau dépôt @@ -463,19 +513,26 @@ Aller à la page suivante Aller à la page précédente Créer une nouvelle page + Ouvrir un dépôt local Ouvrir le dialogue des préférences + Afficher le menu des espaces de travail Changer d'onglet actif + Zoom avant/arrière DÉPÔT Commit les changements de l'index Commit et pousser les changements de l'index Ajouter tous les changements et commit + Créer une nouvelle branche Fetch, démarre directement Mode tableau de bord (Défaut) + Aller au commit enfant + Aller au commit parent Ouvrir la palette de commandes Recherche de commit Pull, démarre directement Push, démarre directement Forcer le rechargement du dépôt + Afficher/Masquer le panneau de détails du panneau`HISTORIQUE` Basculer vers 'Changements' Basculer vers 'Historique' Basculer vers 'Stashes' @@ -483,6 +540,8 @@ Indexer Retirer de l'index Initialiser le repository + Voulez-vous exécuter `git init` dans ce dossier ? + Échec de l'ouverture du dépôt. Raison : Chemin : Cherry-Pick en cours. Traitement du commit @@ -494,6 +553,7 @@ Annulation du commit Rebase interactif Stash & réappliquer changements locaux + Contourner le hook de pre-rebase Sur : Glisser-déposer pour réorganiser les commits Branche cible : @@ -510,6 +570,22 @@ Dans : Option de merge: Source: + D'abord les miens, puis les leurs + D'abord les leurs, puis les miens + UTILISER LES DEUX + Tous les conflits sont résolus + {0} conflit(s) restant(s) + MIENS + Conflit suivant + Conflit précédent + RÉSULTAT + SAUVER ET INDEXER + LEURS + Conflits de fusion + Abandonner les modifications non sauvegardées ? + UTILISER LES MIENS + UTILISER LES LEURS + ANNULER Fusionner (Plusieurs) Commit tous les changement Stratégie: @@ -520,11 +596,17 @@ Déplacer le noeud du repository Sélectionnier le noeud parent pour : Nom : + NON Git n'a PAS été configuré. Veuillez d'abord le faire dans le menu Préférence. Ouvrir Éditeur par défaut (Système) Ouvrir le dossier AppData + Ouvrir un fichier Ouvrir dans l'outil de fusion + Ouvrir un dépôt local + Signet : + Groupe : + Dossier : Optionnel. Créer un nouvel onglet Fermer l'onglet @@ -532,6 +614,8 @@ Fermer les onglets à droite Copier le chemin vers le dépôt Éditer + Se déplacer vers l'espace de travail + Actualiser Dépôts Coller il y a {0} jours @@ -546,7 +630,10 @@ Hier Préférences IA + Prompt supplémentaire (utilisez `-` pour lister vos exigences) Clé d'API + Modèle + Récupérer automatiquement les modèles disponibles Nom La valeur saisie est le nom pour charger la clé API depuis l'ENV Serveur @@ -563,6 +650,10 @@ Utiliser des onglets de taille fixe dans la barre de titre Utiliser un cadre de fenêtre natif OUTIL DIFF/MERGE + Arguments de diff + Variables disponibles : $LOCAL, $REMOTE + Arguments de merge + Variables disponibles : $BASE, $LOCAL, $REMOTE, $MERGED Chemin d'installation Saisir le chemin d'installation de l'outil diff/merge Outil @@ -572,12 +663,13 @@ Activer les dossiers compacts dans l'arborescence des changements Language Historique de commits - Afficher l'heure de l'auteur au lieu de l'heure de validation dans le graphique Afficher la page 'CHANGEMENTS LOCAUX' par défaut Afficher l'onglet 'CHANGEMENTS' dans les détails du commit par défaut Afficher les enfants dans les détails du commit + Afficher le temps relatif dans le graphe de commits Afficher les tags dans le graphique des commits Guide de longueur du sujet + Format 24 heures Générer un avatar par défaut de style GitHub GIT Activer auto CRLF @@ -592,6 +684,7 @@ Utiliser git-credential-libsecret au lieu de git-credential-manager Nom d'utilisateur Nom d'utilisateur global + Utiliser stash & réappliquer par défaut lors des checkout/merge Version de Git SIGNATURE GPG Signature GPG de commit @@ -603,6 +696,8 @@ Clé de signature GPG de l'utilisateur INTEGRATION SHELL/TERMINAL + Arguments + Utilisez '.' pour représenter le répertoire de travail Chemin Shell/Terminal Élaguer une branche distant @@ -637,6 +732,7 @@ Quitter Rebase la branche actuelle Stash & réappliquer changements locaux + Contourner le hook de pre-rebase Sur : Ajouter dépôt distant Modifier dépôt distant @@ -648,6 +744,7 @@ Action personnalisée Supprimer... Editer... + Activer l'auto-fetch Fetch Ouvrir dans le navigateur Elaguer @@ -690,10 +787,12 @@ Naviguer vers le HEAD Créer une branche EFFACER LES NOTIFICATIONS + Ouvrir comme dossier Ouvrir dans {0} Ouvrir dans un outil externe DEPOTS DISTANTS AJOUTER DEPOT DISTANT + RÉSOUDRE Rechercher un commit Auteur Committer @@ -745,9 +844,11 @@ Scanner un autre répertoire personnalisé Rechercher des mises à jour... Une nouvelle version du logiciel est disponible : + Version actuelle : La vérification de mise à jour à échouée ! Télécharger Passer cette version + Date de la nouvelle version : Mise à jour du logiciel Il n'y a pas de mise à jour pour le moment. Définir la Branche du Sous-module @@ -773,6 +874,8 @@ Les modifications indexées et non-indexées des fichiers sélectionnés seront stockées!!! Stash les changements locaux Appliquer + Appliquer les changements + Créer une branche Copier le Message Effacer Sauver comme Patch... @@ -809,9 +912,14 @@ non fusionné Mettre à jour URL + Détails des changements du sous-module + OUVRIR LES DÉTAILS OK TAGUEUR HEURE + Comparer 2 tags + Comparer avec... + Comparer avec HEAD Message Nom Tagueur @@ -819,7 +927,6 @@ Action personnalisée Supprimer ${0}$... Supprimer les {0} tags sélectionnés... - Fusionner ${0}$ dans ${1}$... Pousser ${0}$... Actualiser les sous-modules Tous les sous-modules @@ -864,6 +971,8 @@ Vous êtes en train de créer un commit sur un HEAD détaché. Voulez-vous continuer ? Vous avez indexé {0} fichier(s) mais seulement {1} fichier(s) sont affichés ({2} fichiers sont filtrés). Voulez-vous continuer ? CONFLITS DÉTECTÉS + FUSIONNER + Fusion avec un outil externe OUVRIR TOUS LES CONFLITS DANS L'OUTIL DE FUSION EXTERNE LES CONFLITS DE FICHIER SONT RÉSOLUS UTILISER LES MIENS @@ -885,9 +994,13 @@ ESPACE DE TRAVAIL : Configurer les espaces de travail... WORKTREE + BRANCHE Copier le chemin + HEAD Verrouiller Ouvrir + CHEMIN Supprimer Déverrouiller + OUI diff --git a/src/Resources/Locales/he_IL.axaml b/src/Resources/Locales/he_IL.axaml new file mode 100644 index 000000000..03d14f41b --- /dev/null +++ b/src/Resources/Locales/he_IL.axaml @@ -0,0 +1,1006 @@ + + + + + + אודות + Source Revision: + אודות SourceGit + תאריך שחרור: {0} + הערות שחרור + לקוח Git גרפי, חופשי ובקוד פתוח + הוסף קבצים ל־Ignore + תבנית: + קובץ אחסון: + הוסף Worktree + מיקום: + נתיב ל־worktree זה. נתיב יחסי נתמך. + שם Branch: + לא חובה. ברירת המחדל היא שם תיקיית היעד. + Branch למעקב: + מעקב אחר branch מרוחק + מה לבצע לו checkout: + צור Branch חדש + Branch קיים + עוזר AI + מודל + צור מחדש + שימוש ב־AI ליצירת הודעת commit + שימוש + הסתר SourceGit + הסתר אחרים + הצג הכול + 3-Way Merge + בחר קובץ .patch להחלה + התעלמות משינויי whitespace + החל Patch + Whitespace: + החל Stash + מחק לאחר ההחלה + שחזר שינויי ה־index + Stash: + ארכב... + שמור ארכיון אל: + בחר נתיב לקובץ הארכיון + Revision: + ארכב + SourceGit Askpass + הזן passphrase: + קבצים בהנחת assume-unchanged + אין קבצים בהנחת assume-unchanged + טען תמונה... + רענן + קובץ בינארי אינו נתמך!!! + Bisect + ביטול + פגום (Bad) + תקין (Good) + דלג + מתבצע Bisect. יש לסמן את ה־commit הנוכחי כתקין או כפגום ולבצע checkout לאחר. + מתבצע Bisect. האם ה־HEAD הנוכחי תקין או פגום? + Blame + Blame ל־revision הקודם + התעלמות משינויי whitespace + לא ניתן לבצע Blame על קובץ מסוג זה!!! + Checkout ל־${0}$... + השווה בין 2 ה־branches שנבחרו + השווה עם... + השווה עם HEAD + השווה עם ${0}$ + העתק שם ה־Branch + צור PR... + צור PR ל־upstream ${0}$... + פעולה מותאמת אישית + מחק ${0}$... + מחק {0} ה־branches שנבחרו + ערוך תיאור ל־${0}$... + Fast-Forward אל ${0}$ + Fetch של ${0}$ אל ${1}$... + Git Flow - סיים ${0}$ + Interactive Rebase של ${0}$ על ${1}$ + Merge של ${0}$ אל ${1}$... + Merge של {0} ה־branches שנבחרו אל הנוכחי + Pull ${0}$ + Pull של ${0}$ אל ${1}$... + Push ${0}$ + Rebase של ${0}$ על ${1}$... + שנה שם ${0}$... + Reset של ${0}$ אל ${1}$... + עבור אל ${0}$ (worktree) + הגדר Tracking Branch... + {0} commits לפני + {0} commits לפני, {1} commits אחרי + {0} commits אחרי + לא תקין + REMOTE + סטטוס + TRACKING + URL + WORKTREE + ביטול + Checkout ל־revision של ההורה + Checkout ל־revision זה + צור הודעת commit + Merge (מובנה) + Merge (כלי חיצוני) + Reset של הקבצים אל ${0}$ + שנה מצב תצוגה + הצג כרשימת קבצים ותיקיות + הצג כרשימת נתיבים + הצג כעץ מערכת קבצים + שנה ה־URL של Submodule + Submodule: + URL: + Checkout של Branch + Checkout של Commit + Commit: + אזהרה: ביצוע checkout ל־commit יגרום ל־HEAD להפוך ל־detached + שינויים מקומיים: + Branch: + ה־HEAD הנוכחי מכיל commits שאינם מקושרים לאף branch או tag! האם להמשיך? + יש לעדכן את ה־submodules הבאים:{0}לעדכן אותם? + Checkout ו־Fast-Forward + Fast-Forward אל: + Checkout של Branch מתוך Stash + Branch חדש: + Stash: + Cherry-Pick + הוסף המקור להודעת ה־commit + Commits: + צור commit לכל השינויים + Mainline: + בדרך כלל לא ניתן לבצע cherry-pick ל־merge מכיוון שאין דרך לדעת איזה צד של ה־merge צריך להיחשב כ־mainline. אפשרות זו מאפשרת ל־cherry-pick לשחזר את השינוי ביחס להורה שצוין. + נקה Stashes + פעולה זו תנקה את כל ה־stashes. להמשיך? + שכפל מאגר מרוחק + פרמטרים נוספים: + ארגומנטים נוספים ל־clone. לא חובה. + סימנייה: + קבוצה: + שם מקומי: + שם המאגר. לא חובה. + תיקיית אב: + אתחול ועדכון submodules + URL של המאגר: + סגור + עורך + Branches + Branches ו־Tags + פעולות מותאמות של המאגר + קבצי Revision + Checkout של Commit + Cherry-Pick של Commit + Cherry-Pick ... + השווה עם HEAD + השווה עם ה־Worktree + Author + הודעה + Committer + SHA + Subject + פעולה מותאמת אישית + Interactive Rebase + Drop... + Edit... + Fixup לתוך ההורה... + Interactive Rebase של ${0}$ על ${1}$ + Reword... + Squash לתוך ההורה... + Merge ... + Push של ${0}$ אל ${1}$ + Rebase של ${0}$ על ${1}$ + Reset של ${0}$ אל ${1}$ + Revert של Commit + שמור כ־Patch... + שינויים + קבצים שונו + חיפוש בשינויים... + כיווץ הפרטים + קבצים + קובץ LFS + חיפוש קבצים... + Submodule + מידע + AUTHOR + צאצאים + COMMITTER + בדוק refs המכילים את ה־commit הזה + ה־COMMIT כלול ב־ + העתק דוא"ל + העתק שם + העתק שם ודוא"ל + מוצגים רק 100 השינויים הראשונים. כל השינויים זמינים בלשונית CHANGES. + מפתח: + הודעה + הורים + REFS + SHA + חותם: + פתח בדפדפן + עמודה + הזן הודעת commit. יש להפריד בין subject לתיאור באמצעות שורה ריקה! + SUBJECT + השווה + שינויים + COMMITS + COMMITS בצד שמאל בלבד + COMMITS בצד ימין בלבד + טיפ: ניתן לבצע cherry-pick ל־commits שנבחרו אם הצד השני הוא HEAD (דרך תפריט ההקשר). + הגדרות מאגר + תבנית COMMIT + פרמטרים מובנים: + + ${branch_name} שם ה־local branch הנוכחי. + ${files_num} מספר הקבצים ששונו + ${files} נתיבי הקבצים ששונו + ${files:N} עד N נתיבים של קבצים ששונו + ${pure_files} כמו ${files}, אך רק שמות קבצים נקיים + ${pure_files:N} כמו ${files:N}, אך ללא תיקיות + תוכן התבנית: + שם התבנית: + פעולה מותאמת אישית + ארגומנטים: + פרמטרים מובנים: + + ${REPO} נתיב המאגר + ${REMOTE} ה־remote שנבחר או ה־remote של ה־branch שנבחר + ${BRANCH} ה־branch שנבחר, ללא חלק ה־${REMOTE} עבור branches מרוחקים + ${BRANCH_FRIENDLY_NAME} שם ידידותי של ה־branch שנבחר, כולל את חלק ה־${REMOTE} עבור branches מרוחקים + ${SHA} ה־hash של ה־commit שנבחר + ${TAG} ה־tag שנבחר + ${FILE} הקובץ שנבחר, יחסי לשורש המאגר + $1, $2 ... ערכי שדות קלט + קובץ הרצה: + שדות קלט: + ערוך + שם: + תחום: + Branch + Commit + קובץ + Remote + מאגר + Tag + המתן לסיום הפעולה + כתובת דוא"ל + כתובת דוא"ל + GIT + לבקש אישור לפני עדכון אוטומטי של submodules + Fetch אוטומטי מ־remotes + דקות + סוגי Conventional Commit + Remote ברירת מחדל + מצב Merge מועדף + ISSUE TRACKER + הוסף כלל Azure DevOps + הוסף כלל Gerrit Change-Id Commit + הוסף כלל Gitee Issue + הוסף כלל Gitee Pull Request + הוסף כלל GitHub + הוסף כלל GitLab Issue + הוסף כלל GitLab Merge Request + הוסף כלל Jira + כלל חדש + ביטוי Regex לזיהוי Issue: + שם הכלל: + שיתוף כלל זה בקובץ .issuetracker + URL התוצאה: + השתמש ב־$1, $2 לגישה לערכי קבוצות ה־regex. + AI + שירות מועדף: + אם מוגדר 'שירות מועדף', SourceGit ישתמש רק בו במאגר זה. אחרת, אם זמינים מספר שירותים, יוצג תפריט הקשר לבחירת אחד מהם. + HTTP Proxy + HTTP proxy לשימוש המאגר הזה + שם משתמש + שם משתמש למאגר זה + ערוך שדות קלט של פעולה מותאמת אישית + ערך כאשר מסומן: + כאשר מסומן, ערך זה ישמש בארגומנטים של שורת הפקודה + תיאור: + ברירת מחדל: + תיקייה: + תווית: + אפשרויות: + השתמש ב־'|' כמפריד בין אפשרויות + String Formatter: + לא חובה. משמש לעיצוב מחרוזת הפלט. מתעלם כאשר הקלט ריק. השתמש ב־`${VALUE}` לייצוג מחרוזת הקלט. + המשתנים המובנים ${REPO}, ${REMOTE}, ${BRANCH}, ${BRANCH_FRIENDLY_NAME}, ${SHA}, ${FILE}, ו־${TAG} זמינים גם כאן + סוג: + שימוש בשם ידידותי: + סביבות עבודה + צבע + שם + שחזר לשוניות בעת ההפעלה + המשך + זוהה commit ריק! האם להמשיך (--allow-empty)? + Stage לכל ו־Commit + Stage לנבחרים ו־Commit + זוהה commit ריק! האם להמשיך (--allow-empty) או לבצע stage אוטומטי ואז commit? + נדרשת הפעלה מחדש + יש להפעיל את האפליקציה מחדש כדי להחיל את השינויים. + עוזר Conventional Commit + Breaking Change: + Issue שנסגר: + פירוט השינויים: + תחום: + תיאור קצר: + סוג השינוי: + העתק + העתק כל הטקסט + העתק נתיב מלא + העתק נתיב + צור Branch... + מבוסס על: + בצע checkout ל־branch שייווצר + שינויים מקומיים: + שם ה־Branch החדש: + הזן שם branch. + צור Branch מקומי + דריסת branch קיים + צור Tag... + Tag חדש על: + חתימת GPG + הודעת Tag: + לא חובה. + שם Tag: + פורמט מומלץ: v1.0.0-alpha + Push לכל ה־remotes לאחר היצירה + צור Tag + סוג: + annotated + lightweight + החזק Ctrl להפעלה ישירה + גזור + השלך + לא לעשות דבר + Stash והחלה מחדש + ביטול אתחול של Submodule + לכפות ביטול אתחול גם אם יש בו שינויים מקומיים. + Submodule: + מחק Branch + Branch: + פעולה זו תמחק branch מרוחק!!! + למחוק גם את ה־branch המרוחק ${0}$ + מחק מספר Branches + פעולה זו תמחק מספר branches בו זמנית. בדוק היטב לפני הביצוע! + מחק מספר Tags + מחק גם מה־remotes + פעולה זו תמחק מספר tags בו זמנית. בדוק היטב לפני הביצוע! + מחק Remote + Remote: + נתיב: + יעד: + כל הצאצאים יוסרו מהרשימה. + פעולה זו רק תסיר מהרשימה, לא תמחק מהדיסק! + אישור מחיקת קבוצה + אישור מחיקת מאגר + מחק Submodule + נתיב Submodule: + מחק Tag + Tag: + מחק גם ממאגרים מרוחקים + DIFF בינארי + הרשאות הקובץ שונו + ההבדל הראשון + התעלמות משינויי Whitespace + מיזוג + הבדל + זה לצד זה + החלקה + ההבדל האחרון + שינוי אובייקט LFS + חדש + ההבדל הבא + אין שינויים או רק שינויי EOL + ישן + ההבדל הקודם + שמור כ־Patch + הצג סמלים מוסתרים + Diff זה לצד זה + SUBMODULE + נמחק + חדש + + {0} שינויים שלא בוצע להם commit + החלף + הדגשת תחביר + גלישת שורות + פתח בכלי Merge + הצג כל השורות + הקטנת מספר השורות הנראות + הגדלת מספר השורות הנראות + בחר קובץ להצגת השינויים + היסטוריית תיקייה + קיימים שינויים מקומיים + אינו תואם ל־upstream + כבר מעודכן + השלך שינויים + כל השינויים המקומיים ב־working copy. + שינויים: + כולל קבצים שב־ignore + כולל קבצים ששונו או נמחקו + כולל קבצים untracked + {0} שינויים יושלכו + לא ניתן לבטל פעולה זו!!! + ערוך תיאור ה־Branch + יעד: + סימנייה: + שם חדש: + יעד: + ערוך הקבוצה שנבחרה + ערוך המאגר שנבחר + יעד: + מאגר זה + Fetch + Fetch מכל ה־remotes + כפה דריסה של refs מקומיים + Fetch ללא tags + Remote: + Fetch של שינויים מרוחקים + Assume unchanged + פעולה מותאמת אישית + השלך... + השלך של {0} קבצים... + פתור באמצעות ${0}$ + שמור כ־Patch... + Stage + Stage של {0} קבצים + Stash... + Stash של {0} קבצים... + Unstage + Unstage של {0} קבצים + שימוש בשלי (checkout --ours) + שימוש בשלהם (checkout --theirs) + היסטוריית קובץ + שנה + תוכן + Git-Flow + Branch לפיתוח: + Feature: + קידומת Feature: + FLOW - סיים Feature + FLOW - סיים Hotfix + FLOW - סיים Release + יעד: + Squash בעת ה־merge + Hotfix: + קידומת Hotfix: + אתחול Git-Flow + השארת ה־branch + Branch ייצור: + Release: + קידומת Release: + התחל Feature... + FLOW - התחל Feature + התחל Hotfix... + FLOW - התחל Hotfix + הזן שם + התחל Release... + FLOW - התחל Release + קידומת Version Tag: + Git LFS + הוסף תבנית למעקב... + התבנית היא שם קובץ + תבנית מותאמת אישית: + הוסף תבנית למעקב ב־Git LFS + Fetch + הרץ `git lfs fetch` להורדת אובייקטי Git LFS. אינה מעדכנת את ה־working copy. + Fetch של אובייקטי LFS + התקן hooks של Git LFS + הצג Locks + אין קבצים נעולים + נעל + הצג הנעילות שלי בלבד + LFS Locks + שחרר נעילה + שחרר כל הנעילות שלי + האם לשחרר את כל הקבצים שנעלת? + שחרר נעילה בכוח + Prune + הרץ `git lfs prune` למחיקת קבצי LFS ישנים מהאחסון המקומי + Pull + הרץ `git lfs pull` להורדת כל קבצי Git LFS עבור ה־ref הנוכחי וביצוע checkout + Pull של אובייקטי LFS + Push + Push של קבצים גדולים בתור אל endpoint של Git LFS + Push של אובייקטי LFS + Remote: + מעקב אחר קבצים בשם '{0}' + מעקב אחר כל הקבצים *{0} + בחר Commit + היסטוריה + AUTHOR + זמן AUTHOR + זמן COMMIT + גרף ו־SUBJECT + SHA + הדגשות בגרף + הכול + ה־Branch הנוכחי בלבד + ה־Branch הנוכחי ו־Commits שנבחרו + Commits שנבחרו בלבד + נבחרו {0} COMMITS + הצג עמודות + החזק 'Ctrl' או 'Shift' לבחירת מספר commits. + החזק ⌘ או ⇧ לבחירת מספר commits. + טיפים: + פתח בחלון נפרד + פרטי Commit + השווה Revisions + קיצורי מקלדת + גלובלי + שכפל מאגר חדש + סגור הלשונית הנוכחית + עבור ללשונית הבאה + עבור ללשונית הקודמת + צור לשונית חדשה + פתח מאגר מקומי + פתח חלון ההעדפות + הצג תפריט נפתח של סביבת העבודה + החלף לשונית פעילה + הגדל/הקטן + מאגר + Commit לשינויים ב־staged + Commit ו־push לשינויים ב־staged + Stage לכל השינויים ו־commit + צור branch חדש + Fetch, מתחיל מיידית + מצב Dashboard (ברירת מחדל) + עבור לצאצא של ה־commit שנבחר + עבור להורה של ה־commit שנבחר + פתח command palette + מצב חיפוש commits + Pull, מתחיל מיידית + Push, מתחיל מיידית + טען את המאגר מחדש בכוח + הרחבה/כיווץ של חלונית הפרטים ב־`HISTORY` + עבור ל־'LOCAL CHANGES' + עבור ל־'HISTORY' + עבור ל־'STASHES' + השלך + Stage + Unstage + אתחול מאגר + האם להריץ `git init` בנתיב זה? + פתיחת המאגר נכשלה. סיבה: + נתיב: + Cherry-Pick בתהליך. + מעבד commit + Merge בתהליך. + מתבצע Merge + Rebase בתהליך. + נעצר ב־ + Revert בתהליך. + מבצע Revert ל־commit + Interactive Rebase + Stash והחלה מחדש של שינויים מקומיים + דלג על pre-rebase hook + על: + גרור כדי לסדר מחדש commits + Branch יעד: + העתק קישור + פתח בדפדפן + פקודות + שגיאה + הודעה + מאגרים פתוחים + לשוניות + סביבות עבודה + Merge של Branch + התאם הודעת merge + אל: + אפשרות Merge: + מקור: + תחילה שלי, אחר כך שלהם + תחילה שלהם, אחר כך שלי + שימוש בשניהם + כל הקונפליקטים נפתרו + נותרו {0} קונפליקטים + שלי + הקונפליקט הבא + הקונפליקט הקודם + תוצאה + שמור ו־Stage + שלהם + קונפליקטי Merge + להשליך שינויים שלא נשמרו? + שימוש בשלי + שימוש בשלהם + ביטול + Merge (מרובה) + Commit לכל השינויים + אסטרטגיה: + יעדים: + העבר Submodule + העבר אל: + Submodule: + העבר רכיב מאגר + בחר רכיב אב עבור: + שם: + לא + Git אינו מוגדר. עבור ל־[העדפות] והגדר אותו תחילה. + פתח + עורך ברירת מחדל (מערכת) + פתח תיקיית אחסון נתונים + פתח קובץ + פתח בכלי Merge חיצוני + פתח מאגר מקומי + סימנייה: + קבוצה: + תיקייה: + לא חובה. + צור לשונית חדשה + סגור לשונית + סגור לשוניות אחרות + סגור לשוניות מימין + העתק נתיב המאגר + ערוך + העבר לסביבת עבודה + רענן + מאגרים + הדבק + לפני {0} ימים + לפני שעה + לפני {0} שעות + הרגע + בחודש שעבר + בשנה שעברה + לפני {0} דקות + לפני {0} חודשים + לפני {0} שנים + אתמול + העדפות + AI + Prompt נוסף (השתמש ב־`-` לרשימת דרישות) + API Key + מודל + Fetch אוטומטי של model-ids זמינים + שם + הערך שהוזן הוא שם משתנה סביבה לטעינת ה־API key + שרת + מראה + גופן ברירת מחדל + רוחב Tab בעורך + גודל גופן + ברירת מחדל + עורך + גופן Monospace + ערכת נושא + דריסות ערכת נושא + שימוש בפסי גלילה המוסתרים אוטומטית + רוחב לשונית קבוע בשורת הכותרת + שימוש במסגרת חלון מקומית + כלי DIFF/MERGE + ארגומנטים ל־Diff + משתנים זמינים: $LOCAL, $REMOTE + ארגומנטים ל־Merge + משתנים זמינים: $BASE, $LOCAL, $REMOTE, $MERGED + נתיב התקנה + הזן נתיב לכלי diff/merge + כלי + כללי + בדוק עדכונים בעת ההפעלה + תבנית תאריך + תיקיות מצומצמות בעץ השינויים + שפה + Commits בהיסטוריה + הצג דף `LOCAL CHANGES` כברירת מחדל + הצג לשונית `CHANGES` בפרטי ה־commit כברירת מחדל + הצג צאצאים בפרטי ה־commit + הצג זמן יחסי בגרף ה־commits + הצג tags בגרף ה־commits + אורך מנחה ל־Subject + 24 שעות + צור אווטאר ברירת מחדל בסגנון GitHub + GIT + הפעל CRLF אוטומטי + תיקיית clone ברירת מחדל + דוא"ל משתמש + דוא"ל משתמש גלובלי של git + Prune ל־branches מתים לאחר fetch + התעלמות מ־CR בסוף שורה ב־diff טקסט + נדרש Git (>= 2.25.1) עבור אפליקציה זו + נתיב התקנה + הפעל אימות HTTP SSL + שימוש ב־git-credential-libsecret במקום git-credential-manager + שם משתמש + שם משתמש גלובלי של git + Stash והחלה מחדש של שינויים כברירת מחדל בעת checkout או merge של branches + גרסת Git + חתימת GPG + חתימת GPG ל־commits + פורמט GPG + נתיב התקנת התוכנה + הזן נתיב לתוכנת gpg מותקנת + חתימת GPG ל־tags + מפתח חתימה של המשתמש + מפתח חתימת gpg של המשתמש + אינטגרציה + SHELL/טרמינל + ארגומנטים + השתמש ב־'.' לציון תיקיית העבודה + נתיב + Shell/טרמינל + Prune Remote + יעד: + Prune Worktrees + Prune למידע על worktrees ב־`$GIT_COMMON_DIR/worktrees` + Pull + Branch מרוחק: + אל: + שינויים מקומיים: + Remote: + Pull (Fetch ו־Merge) + שימוש ב־rebase במקום merge + Push + לוודא ש־submodules בוצע להם push + Force push + Branch מקומי: + חדש + Remote: + Revision: + Push של Revision ל־Remote + Push של שינויים ל־Remote + Branch מרוחק: + הגדר כ־tracking branch + Push לכל ה־tags + Push של Tag ל־Remote + Push לכל ה־remotes + Remote: + Tag: + Push ל־branch חדש + הזן שם ל־branch המרוחק החדש: + יציאה + Rebase של ה־Branch הנוכחי + Stash והחלה מחדש של שינויים מקומיים + דלג על pre-rebase hook + על: + הוסף Remote + ערוך Remote + שם: + שם Remote + URL של המאגר: + URL של מאגר git מרוחק + העתק URL + פעולה מותאמת אישית + מחק... + ערוך... + הפעל Auto-Fetch + Fetch + פתח בדפדפן + Prune + אישור הסרת Worktree + הפעל אפשרות `--force` + יעד: + שנה שם Branch + שם חדש: + שם ייחודי ל־branch זה + Branch: + ביטול + Fetch אוטומטי של שינויים מ־remotes... + מיון + לפי תאריך Committer + לפי שם + נקה (GC ו־Prune) + הרץ `git gc` עבור המאגר. + נקה הכול + נקה + הגדר מאגר זה + המשך + פעולות מותאמות אישית + אין פעולות מותאמות אישית + Dashboard + השלך כל השינויים + פתח בסייר הקבצים + חיפוש Branches/Tags/Submodules + נראות בגרף + לא מוגדר + הסתר בגרף ה־commits + סינון בגרף ה־commits + פריסה + אופקי + אנכי + סדר COMMITS + תאריך Commit + טופולוגי + BRANCHES מקומיים + אפשרויות נוספות... + ניווט אל HEAD + צור Branch + נקה התראות + פתח כתיקייה + פתח ב־{0} + פתח בכלים חיצוניים + REMOTES + הוסף Remote + פתור + חיפוש Commit + Author + Committer + תוכן + הודעה + נתיב + SHA + ב־Branch הנוכחי + Commits מעוטרים בלבד + First-parent בלבד + הצג דגלים + הצג commits אבודים + הצג Submodules כעץ + הצג Tags כעץ + דלג + סטטיסטיקות + SUBMODULES + הוסף Submodule + עדכון Submodule + TAGS + Tag חדש + לפי תאריך צור + לפי שם + מיון + פתח בטרמינל + הצג לוגים + בקר ב־'{0}' בדפדפן + WORKTREES + הוסף Worktree + Prune + URL של מאגר Git + Reset של ה־Branch הנוכחי ל־Revision + מצב Reset: + העבר אל: + Branch נוכחי: + Reset של Branch (ללא Checkout) + העבר אל: + Branch: + הצג בסייר הקבצים + Revert של Commit + Commit: + Commit לשינויי ה־revert + פועל. נא להמתין... + שמור + שמור בשם... + ה־Patch נשמר בהצלחה! + סרוק מאגרים + תיקיית שורש: + סרוק תיקייה מותאמת אישית אחרת + בדוק עדכונים... + גרסה חדשה של התוכנה זמינה: + גרסה נוכחית: + בדוק העדכונים נכשלה! + הורד + דלג על גרסה זו + תאריך שחרור הגרסה החדשה: + עדכון תוכנה + כרגע אין עדכונים זמינים. + הגדר Branch של Submodule + Submodule: + נוכחי: + שנה אל: + לא חובה. אם ריק, יוגדר לברירת המחדל. + הגדר Tracking Branch + Branch: + ביטול upstream + Upstream: + העתק SHA + עבור אל + מפתח SSH פרטי: + נתיב לאחסון מפתח SSH פרטי + התחל + Stash + כולל קבצים untracked + הודעה: + לא חובה. הודעה ל־stash זה + מצב: + קבצים ב־staged בלבד + גם השינויים שב־staged וגם אלו שלא יוכנסו ל־stash עבור הקבצים שנבחרו!!! + Stash לשינויים מקומיים + החל + החל שינויים + Checkout ל־Branch חדש + העתק הודעה + מחק + שמור כ־Patch... + מחק Stash + מחק: + STASHES + שינויים + STASHES + סטטיסטיקות + סקירה כללית + חודש + שבוע + AUTHORS: + COMMITS: + SUBMODULES + הוסף Submodule + BRANCH + Branch + נתיב יחסי + ביטול אתחול + Fetch ל־submodules מקוננים + היסטוריה + העבר אל + פתח מאגר + נתיב יחסי: + תיקייה יחסית לאחסון המודול. + מחק + הגדר Branch + שנה URL + סטטוס + שונה + לא אותחל + ה־revision שונה + unmerged + עדכון + URL + פרטי שינויים ב־Submodule + פתח פרטים + אישור + TAGGER + זמן + השווה בין 2 tags + השווה עם... + השווה עם HEAD + הודעה + שם + Tagger + העתק שם ה־Tag + פעולה מותאמת אישית + מחק ${0}$... + מחק {0} ה־tags שנבחרו... + Push ${0}$... + עדכון Submodules + כל ה־submodules + אתחול לפי הצורך + Submodule: + עדכון ל־remote tracking branch של ה־submodule + URL: + לוגים + נקה הכול + העתק + מחק + אזהרה + דף פתח + צור קבוצה + צור תת־קבוצה + שכפל מאגר + מחק + נתמכת גרירה ושחרור של תיקיות. נתמך קיבוץ מותאם אישית. + ערוך + העבר לקבוצה אחרת + פתח כל המאגרים + פתח מאגר + פתח טרמינל + סרוק מחדש של מאגרים בתיקיית ה־Clone ברירת מחדל + חיפוש מאגרים... + שינויים מקומיים + Git Ignore + התעלמות מכל הקבצים *{0} + התעלמות מקבצי *{0} באותה תיקייה + התעלמות מקבצים untracked בתיקייה זו + התעלמות מקובץ זה בלבד + Amend + ניתן לבצע stage לקובץ זה כעת. + נקה היסטוריה + האם לנקות את כל היסטוריית הודעות ה־commit? לא ניתן לבטל פעולה זו. + COMMIT + COMMIT ו־PUSH + תבנית/היסטוריה + הפעל אירוע לחיצה + Commit (ערוך) + Stage לכל השינויים ו־commit + פעולה זו תיצור commit על HEAD שמצבו detached. האם להמשיך? + ביצעת stage ל־{0} קבצים אך מוצגים רק {1} קבצים ({2} מסוננים החוצה). האם להמשיך? + זוהו קונפליקטים + MERGE + Merge עם כלי חיצוני + פתח כל הקונפליקטים בכלי Merge חיצוני + קונפליקטי הקובץ נפתרו + שימוש בשלי + שימוש בשלהם + כולל קבצים UNTRACKED + אין הודעות שהוזנו לאחרונה + אין תבניות commit + No-Verify + Reset ל־Author + SignOff + STAGED + UNSTAGE + UNSTAGE לכול + UNSTAGED + STAGE + STAGE לכול + הצג ASSUME UNCHANGED + תבנית: ${0}$ + סביבת עבודה: + הגדר סביבות עבודה... + WORKTREE + BRANCH + העתק נתיב + HEAD + נעל + פתח + נתיב + הסר + שחרר נעילה + כן + diff --git a/src/Resources/Locales/id_ID.axaml b/src/Resources/Locales/id_ID.axaml index b3552b1f2..744a00568 100644 --- a/src/Resources/Locales/id_ID.axaml +++ b/src/Resources/Locales/id_ID.axaml @@ -25,7 +25,6 @@ Gunakan AI untuk membuat pesan commit Sembunyikan SourceGit Tampilkan Semua - Berkas Patch: Pilih berkas .patch untuk diterapkan Abaikan perubahan whitespace Terapkan Patch @@ -49,10 +48,10 @@ Bisect Batalkan Buruk - Bisect berjalan. Apakah HEAD saat ini baik atau buruk? Baik Lewati - Bisect berjalan. Tandai commit saat ini sebagai baik atau buruk dan checkout yang lain. + Bisect berjalan. Tandai commit saat ini sebagai baik atau buruk dan checkout yang lain. + Bisect berjalan. Apakah HEAD saat ini baik atau buruk? Blame BLAME PADA BERKAS INI TIDAK DIDUKUNG!!! Checkout ${0}$... @@ -139,7 +138,6 @@ Rebase ${0}$ pada ${1}$ secara Interaktif Reword... Squash ke Parent... - Merge ke ${0}$ Merge ... Push ${0}$ ke ${1}$ Rebase ${0}$ pada ${1}$ @@ -550,7 +548,6 @@ Aktifkan folder kompak di pohon perubahan Bahasa Commit Riwayat - Tampilkan waktu author alih-alih waktu commit di grafik Tampilkan halaman `LOCAL CHANGES` secara default Tampilkan tab `CHANGES` di detail commit secara default Tampilkan children di detail commit @@ -795,7 +792,6 @@ Aksi Kustom Hapus ${0}$... Hapus {0} tag yang dipilih... - Merge ${0}$ ke ${1}$... Push ${0}$... Perbarui Submodule Semua submodule diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 12102bebc..9bc374a3a 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -27,7 +27,6 @@ Usa AI per generare il messaggio di commit Nascondi SourceGit Mostra Tutto - File Patch: Seleziona file .patch da applicare Ignora modifiche agli spazi Applica Patch @@ -51,10 +50,10 @@ Biseca Annulla Cattiva - Bisecando. La HEAD corrente è buona o cattiva? Buona Salta - Bisecando. Marca il commit corrente come buono o cattivo e fai checkout di un altro. + Bisecando. Marca il commit corrente come buono o cattivo e fai checkout di un altro. + Bisecando. La HEAD corrente è buona o cattiva? Attribuisci Attribuisci sulla Revisione Precedente Ignora modifiche agli spazi @@ -152,7 +151,6 @@ Ribasare interattivamente ${0}$ su ${1}$ Riformula... Compatta nel Genitore... - Unisci a ${0}$ Unisci ... Invia ${0}$ a ${1}$ Ribasa ${0}$ su ${1}$ @@ -612,7 +610,6 @@ ${pure_files:N} Come ${files:N}, ma senza cartelle Abilita cartelle compatte nell'albero delle modifiche Lingua Numero massimo di commit nella cronologia - Mostra nel grafico l'orario dell'autore anziché quello del commit Mostra pagina `MODIFICHE LOCALI` per impostazione predefinita Mostra scheda `MODIFICHE` nei dettagli del commit per impostazione predefinita Mostra i figli nei dettagli del commit @@ -866,7 +863,6 @@ ${pure_files:N} Come ${files:N}, ma senza cartelle Azione Personalizzata Elimina ${0}$... Elimina i {0} tag selezionati... - Unisci ${0}$ in ${1}$... Invia ${0}$... Aggiorna Sottomoduli Tutti i sottomoduli diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml index c9eda571a..26bdec35e 100644 --- a/src/Resources/Locales/ja_JP.axaml +++ b/src/Resources/Locales/ja_JP.axaml @@ -27,7 +27,6 @@ AI を使用してコミットメッセージを生成 SourceGit を隠す すべて表示 - パッチファイル: 適用する .patch ファイルを選択 空白文字の変更を無視 パッチを適用 @@ -51,10 +50,10 @@ 問題の発生源を特定 中止 問題あり - 問題の発生源となったコミットを特定しています。現在の HEAD に問題はありませんか? 問題なし スキップ - 問題の発生源となったコミットを特定しています。現在のコミットに問題があるかどうかを調査したあと、別のコミットをチェックアウトしてみてください。 + 問題の発生源となったコミットを特定しています。現在のコミットに問題があるかどうかを調査したあと、別のコミットをチェックアウトしてみてください。 + 問題の発生源となったコミットを特定しています。現在の HEAD に問題はありませんか? 著者の履歴 前のリビジョンの著者の履歴 空白文字の変更を無視 @@ -153,7 +152,6 @@ ${0}$ を ${1}$ で対話式リベース 書き直す... 親コミットに記録付きで統合... - ${0}$ にマージ マージ... ${0}$ を ${1}$ にプッシュ ${0}$ を ${1}$ でリベース @@ -466,7 +464,6 @@ 著者 著者の日時 コミット日時 - 日時 グラフ & コミットのタイトル SHA {0} コミットを選択しました @@ -618,7 +615,6 @@ 変更ツリーのフォルダー階層をまとめる 言語 コミット履歴 - グラフにコミット日時ではなく著者の日時を表示 初めから `ローカルの変更` ページを表示 初めからコミットの詳細の `変更` タブを表示 コミットの詳細に子コミットを表示 @@ -875,7 +871,6 @@ カスタムアクション ${0}$ を削除... 選択した {0} 個のタグを削除... - ${0}$ を ${1}$ にマージ... ${0}$ をプッシュ... サブモジュールを更新 すべてのサブモジュール diff --git a/src/Resources/Locales/ko_KR.axaml b/src/Resources/Locales/ko_KR.axaml index ce07c5975..c73a72373 100644 --- a/src/Resources/Locales/ko_KR.axaml +++ b/src/Resources/Locales/ko_KR.axaml @@ -1,7 +1,12 @@ + + + 정보 + 소스 버전: SourceGit 정보 + 배포일: {0} 릴리스 노트 오픈소스 & 무료 Git GUI 클라이언트 무시할 파일 추가 @@ -21,11 +26,16 @@ 모델 재생성 AI를 사용하여 커밋 메시지 생성 + 사용 SourceGit 숨기기 + 다른 항목 숨기기 모두 보기 - 패치 파일: + 3방향 병합 적용할 .patch 파일을 선택하세요 공백 변경 사항 무시 + 원본: + 파일 + 클립보드 패치 적용 공백: 스태시 적용 @@ -47,16 +57,26 @@ 이진 탐색 중단 나쁨 - 이진 탐색 중. 현재 HEAD가 '좋음' 상태입니까, '나쁨' 상태입니까? 좋음 건너뛰기 - 이진 탐색 중. 현재 커밋을 '좋음' 또는 '나쁨'으로 표시하고 다른 커밋을 체크아웃하세요. + 이진 탐색 중. 현재 커밋을 '좋음' 또는 '나쁨'으로 표시하고 다른 커밋을 체크아웃하세요. + 이진 탐색 중. 현재 HEAD가 '좋음' 상태입니까, '나쁨' 상태입니까? 블레임 - ${0}$ 체크아웃... + 이전 리비전으로 책임 추적 + 공백 변경 무시 + 이 파일은 책임 추적 기능을 지원하지 않습니다 + ${0}$(으)로 체크아웃... + 선택한 두 브랜치 비교하기 + 다음과 비교... + HEAD와 비교 + ${0}$와 비교 브랜치 이름 복사 + PR 생성 + 업스트림 ${0}$에 대한 PR 생성... 사용자 지정 작업 ${0}$ 삭제... 선택한 {0}개의 브랜치 삭제 + ${0}$ 설명 편집... ${0}$(으)로 Fast-Forward ${0}$에서 ${1}$(으)로 Fetch... Git Flow - ${0}$ 완료 @@ -65,7 +85,7 @@ 선택한 {0}개의 브랜치를 현재 브랜치로 병합 ${0}$ Pull ${0}$에서 ${1}$(으)로 Pull... - ${0}$ Push + ${0}$(으)로 Push ${1}$을(를) 기반으로 ${0}$ 리베이스... ${0}$ 이름 바꾸기... ${0}$을(를) ${1}$(으)로 리셋... @@ -84,6 +104,9 @@ 부모 리비전으로 리셋 이 리비전으로 리셋 커밋 메시지 생성 + 병합(내장) + 병합(외부 도구) + 파일을 ${0}$(으)로 되돌리기 표시 모드 변경 파일 및 디렉터리 목록으로 보기 경로 목록으로 보기 @@ -98,8 +121,12 @@ 로컬 변경 사항: 브랜치: 현재 HEAD에 브랜치/태그에 연결되지 않은 커밋이 있습니다! 계속하시겠습니까? + 다음 서브모듈을 업데이트해야 합니다:{0}업데이트하시겠습니까? 체크아웃 & Fast-Forward Fast-Forward 대상: + 스태시에서 브랜치 체크아웃 + 새로운 브랜치: + 스태시: 체리픽 커밋 메시지에 원본 추가 커밋: @@ -111,6 +138,8 @@ 원격 저장소 복제 추가 파라미터: 저장소 복제 시 추가 인수. 선택 사항. + 북마크: + 그룹: 로컬 이름: 저장소 이름. 선택 사항. 상위 폴더: @@ -118,14 +147,20 @@ 저장소 URL: 닫기 에디터 + 브랜치 + 브랜치 & 태그 + 저장소 사용자 지정 작업 + 리비전 파일 커밋 체크아웃 커밋 체리픽 체리픽... HEAD와 비교 워크트리와 비교 작성자 + 작성 시간 메시지 커밋터 + 커밋 시간 SHA 제목 사용자 지정 작업 @@ -133,19 +168,19 @@ 삭제(Drop)... 수정(Edit)... 부모에 합치기(Fixup)... - ${1}$을(를) 기반으로 ${0}$ 대화형 리베이스 + ${1}$을(를) 기반으로 ${0}$(을)를 대화형 리베이스 메시지 수정(Reword)... 부모에 합치기(Squash)... - ${0}$(으)로 병합 병합... ${0}$을(를) ${1}$(으)로 푸시 - ${1}$을(를) 기반으로 ${0}$ 리베이스 + ${1}$을(를) 기반으로 ${0}$(을)를 리베이스 ${0}$을(를) ${1}$(으)로 리셋 커밋 되돌리기 패치로 저장... 변경 사항 변경된 파일 변경 사항 검색... + 세부 정보 접기 파일 LFS 파일 파일 검색... @@ -167,8 +202,15 @@ SHA 서명자: 브라우저에서 열기 + + 커밋 메시지를 입력하세요. 제목과 설명은 빈 줄로 구분하세요! 제목 비교 + 변경점 + 커밋 + 왼쪽에만 있는 커밋 + 오른쪽에만 있는 커밋 + 팁: 반대편이 HEAD인 경우 선택한 커밋을 체리픽할 수 있습니다(컨텍스트 메뉴 사용). 저장소 설정 커밋 템플릿 ${files_num}, ${branch_name}, ${files} 및 ${files:N} (N은 출력할 최대 파일 경로 수)을(를) 사용할 수 있습니다. @@ -176,8 +218,8 @@ 템플릿 이름: 사용자 지정 작업 인수: - 내장 파라미터: - + 내장 파라미터: + ${REPO} 저장소 경로 ${REMOTE} 선택한 원격 또는 선택한 브랜치의 원격 ${BRANCH} 선택한 브랜치 (원격 브랜치의 경우 ${REMOTE} 부분 제외) @@ -201,8 +243,10 @@ 이메일 주소 이메일 주소 GIT + 서브모듈 자동 업데이트 전에 확인 원격 자동 Fetch + Conventional Commit 유형 기본 원격 선호하는 병합 모드 이슈 트래커 @@ -236,7 +280,11 @@ 레이블: 옵션: 옵션 구분자로 '|'를 사용하세요 + 문자열 포매터: + 선택 사항. 출력 문자열 형식 지정에 사용합니다. 입력이 비어 있으면 무시됩니다. 입력 문자열은 `${VALUE}`로 표시하세요. + 여기에서도 내장 변수 ${REPO}, ${REMOTE}, ${BRANCH}, ${BRANCH_FRIENDLY_NAME}, ${SHA}, ${FILE}, ${TAG}를 사용할 수 있습니다 유형: + 표시용 이름 사용: 작업 공간 색상 이름 @@ -244,6 +292,7 @@ 계속 빈 커밋이 감지되었습니다! 계속하시겠습니까 (--allow-empty)? 모두 스테이징 & 커밋 + 선택 항목 스테이징 후 커밋 빈 커밋이 감지되었습니다! 계속하시겠습니까 (--allow-empty) 아니면 모두 스테이징 후 커밋하시겠습니까? 재시작 필요 변경 사항을 적용하려면 앱을 다시 시작해야 합니다. @@ -256,6 +305,7 @@ 변경 유형: 복사 전체 텍스트 복사 + 패치로 복사 전체 경로 복사 경로 복사 브랜치 생성... @@ -281,6 +331,7 @@ Ctrl을 누른 채 클릭하면 바로 시작합니다 잘라내기 폐기 + 아무것도 하지 않기 스태시 & 재적용 서브모듈 초기화 해제 로컬 변경 사항이 있어도 강제로 초기화 해제합니다. @@ -328,6 +379,7 @@ 서브모듈 삭제됨 신규 + 커밋 안 한 변경 사항 + {0}개 전환 구문 강조 줄 바꿈 @@ -344,9 +396,12 @@ 작업 사본의 모든 로컬 변경 사항. 변경 사항: 무시된 파일 포함 + 수정/삭제된 파일 포함 추적하지 않는 파일 포함 {0}개의 변경 사항이 폐기됩니다 이 작업은 되돌릴 수 없습니다!!! + 브랜치 설명 수정 + 대상: 북마크: 새 이름: 대상: @@ -361,6 +416,7 @@ 원격: 원격 변경 사항 Fetch 변경되지 않음으로 간주 + 사용자 지정 작업 폐기... {0}개 파일 폐기... ${0}$을(를) 사용하여 해결 @@ -415,6 +471,8 @@ 내 잠금만 보기 LFS 잠금 잠금 해제 + 내 잠금 모두 해제 + 잠근 파일을 모두 해제하시겠습니까? 강제 잠금 해제 정리 로컬 저장소에서 오래된 LFS 파일을 삭제하려면 `git lfs prune`을 실행하세요 @@ -427,16 +485,26 @@ 원격: '{0}' 이름의 파일 추적 모든 *{0} 파일 추적 + 커밋 선택 히스토리 작성자 작성 시간 커밋 시간 그래프 & 제목 SHA + 그래프 강조 표시 + 모두 + 현재 브랜치만 + 현재 브랜치와 선택한 커밋 + 선택한 커밋만 {0}개 커밋 선택됨 + 표시할 역 'Ctrl' 또는 'Shift' 키를 누른 채로 여러 커밋을 선택하세요. ⌘ 또는 ⇧ 키를 누른 채로 여러 커밋을 선택하세요. 팁: + 별도의 창으로 열기 + 커밋 세부 정보 + 리비전 비교 키보드 단축키 참조 전역 새 저장소 복제 @@ -444,18 +512,26 @@ 다음 탭으로 이동 이전 탭으로 이동 새 탭 만들기 + 로컬 저장소 열기 환경설정 대화상자 열기 + 작업 공간 드롭다운 메뉴 열기 활성 탭 전환 + 확대 / 축소 저장소 스테이징된 변경 사항 커밋 스테이징된 변경 사항 커밋 및 푸시 모든 변경 사항 스테이징 후 커밋 + 브랜치 생성 Fetch (바로 시작) 대시보드 모드 (기본) + 선택한 커밋의 자식으로 이동 + 선택한 커밋의 부모로 이동 + 명령 팔레트 열기 커밋 검색 모드 열기 Pull (바로 시작) 푸시 (바로 시작) 이 저장소 강제 새로고침 + 히스토리에서 세부 정보 패널 펼치기/접기 '변경 사항'으로 전환 '히스토리'로 전환 '스태시'로 전환 @@ -463,6 +539,8 @@ 스테이지 언스테이지 저장소 초기화 + 이 경로에서 `git init` 명령을 실행하시겠습니까? + 저장소를 열지 못했습니다. 원인: 경로: 체리픽 진행 중. 커밋 처리 중 @@ -474,13 +552,16 @@ 커밋 되돌리는 중 대화형 리베이스 로컬 변경 사항 스태시 & 재적용 + pre-rebase 훅 건너뛰기 기준: 드래그 앤 드롭으로 커밋 순서 변경 대상 브랜치: 링크 복사 브라우저에서 열기 + 명령 오류 알림 + 저장소 열기 작업 공간 브랜치 병합 @@ -488,6 +569,26 @@ 대상: 병합 옵션: 소스: + 병합 가능 여부 확인 중... + 충돌 없이 병합할 수 있습니다 + 병합 테스트 중 알 수 없는 오류가 발생했습니다 + 병합 시 충돌이 발생합니다 + 내 변경 먼저, 상대 변경 나중 + 상대 변경 먼저, 내 변경 나중 + 둘 다 사용 + 모든 충돌 해결됨 + 남은 충돌 {0}개 + 내 변경 + 다음 충돌 + 이전 충돌 + 결과 + 저장 후 스테이징 + 상대 변경 + 병합 충돌 + 저장하지 않은 변경사항을 버리시겠습니까? + 내 변경 사용 + 상대 변경 사용 + 실행 취소 병합 (다중) 모든 변경 사항 커밋 전략: @@ -498,9 +599,17 @@ 저장소 노드 이동 상위 노드 선택: 이름: + 아니요 Git이 구성되지 않았습니다. [환경설정]으로 이동하여 먼저 구성하세요. + 열기 + 시스템 기본 편집기 데이터 저장 디렉터리 열기 + 파일 열기 병합 도구에서 열기 + 로컬 저장소 열기 + 북마크: + 그룹: + 폴더: 선택 사항. 새 탭 만들기 탭 닫기 @@ -508,6 +617,8 @@ 오른쪽 탭 닫기 저장소 경로 복사 편집 + 작업 공간으로 이동 + 새로 고침 저장소 붙여넣기 {0}일 전 @@ -522,7 +633,10 @@ 어제 환경설정 AI + 추가 프롬프트(`-`로 요구 사항 나열) API 키 + 모델 + 사용 가능한 모델 ID 자동 가져오기 이름 입력된 값은 환경변수(ENV)에서 API 키를 불러올 이름입니다 서버 @@ -536,8 +650,13 @@ 테마 테마 재정의 스크롤바 자동 숨기기 사용 + 제목 표시줄에서 고정 탭 너비 사용 네이티브 윈도우 프레임 사용 DIFF/MERGE 도구 + 비교 인수 + 사용 가능한 변수: $LOCAL, $REMOTE + 병합 인수 + 사용 가능한 변수: $BASE, $LOCAL, $REMOTE, $MERGED 설치 경로 diff/merge 도구 경로 입력 도구 @@ -547,12 +666,14 @@ 변경 사항 트리에서 폴더 압축 활성화 언어 히스토리 커밋 수 - 그래프에 커밋 시간 대신 작성자 시간 표시 기본으로 `로컬 변경 사항` 페이지 표시 커밋 세부 정보에서 기본으로 `변경 사항` 탭 표시 커밋 세부 정보에 자식 커밋 표시 + 커밋 그래프에 상대 시간 표시 커밋 그래프에 태그 표시 제목 가이드 길이 + 24시간 형식 + 커밋 그래프에서 축약 브랜치 이름 사용 GitHub 스타일 기본 아바타 생성 GIT 자동 CRLF 활성화 @@ -567,6 +688,7 @@ git-credential-manager 대신 git-credential-libsecret 사용 사용자 이름 전역 git 사용자 이름 + 브랜치 체크아웃 또는 병합 시 기본적으로 변경 사항을 스태시한 뒤 다시 적용 Git 버전 GPG 서명 커밋 GPG 서명 @@ -578,6 +700,8 @@ 사용자의 gpg 서명 키 연동 셸/터미널 + 인수 + 작업 디렉터리는 `.`으로 표시하세요 경로 셸/터미널 원격 정리 @@ -607,10 +731,17 @@ 모든 원격에 푸시 원격: 태그: + 새 브랜치로 푸시 + 새 원격 브랜치 이름을 입력하세요: 종료 현재 브랜치 리베이스 로컬 변경 사항 스태시 & 재적용 + pre-rebase 훅 건너뛰기 기준: + 리베이스 가능 여부 확인 중... + 충돌 없이 리베이스할 수 있습니다 + 리베이스 테스트 중 알 수 없는 오류가 발생했습니다 + 리베이스 시 충돌이 발생합니다 원격 추가 원격 편집 이름: @@ -621,6 +752,7 @@ 사용자 지정 작업 삭제... 편집... + 자동 Fetch 사용 Fetch 브라우저에서 열기 정리 @@ -663,10 +795,12 @@ HEAD로 이동 브랜치 생성 알림 지우기 + 폴더로 열기 {0}에서 열기 외부 도구에서 열기 원격 원격 추가 + 해결 커밋 검색 작성자 커밋터 @@ -718,9 +852,11 @@ 다른 사용자 정의 디렉터리 스캔 업데이트 확인... 이 소프트웨어의 새 버전을 사용할 수 있습니다: + 현재 버전: 업데이트 확인 실패! 다운로드 이 버전 건너뛰기 + 새 버전 릴리스 날짜: 소프트웨어 업데이트 현재 사용 가능한 업데이트가 없습니다. 서브모듈 브랜치 설정 @@ -746,6 +882,8 @@ 선택한 파일의 스테이징된 변경 사항과 스테이징되지 않은 변경 사항이 모두 스태시됩니다!!! 로컬 변경 사항 스태시 적용 + 변경 사항 적용 + 새 브랜치 체크아웃 메시지 복사 삭제 패치로 저장... @@ -779,11 +917,17 @@ 수정됨 초기화 안 됨 리비전 변경됨 + 병합되지 않음 업데이트 URL + 서브모듈 변경 상세 + 상세 열기 확인 태그 생성자 시간 + 태그 2개 비교 + 다음과 비교... + HEAD와 비교 메시지 이름 태그 생성자 @@ -791,7 +935,6 @@ 사용자 지정 작업 ${0}$ 삭제... 선택한 {0}개의 태그 삭제... - ${0}$을(를) ${1}$(으)로 병합... ${0}$ 푸시... 서브모듈 업데이트 모든 서브모듈 @@ -836,6 +979,8 @@ 분리된(detached) HEAD에 커밋을 생성하고 있습니다. 계속하시겠습니까? {0}개의 파일을 스테이징했지만 {1}개의 파일만 표시됩니다 ({2}개의 파일은 필터링됨). 계속하시겠습니까? 충돌 감지됨 + 병합 + 외부 도구로 병합 모든 충돌을 외부 병합 도구에서 열기 파일 충돌 해결됨 내 것 사용 @@ -857,9 +1002,13 @@ 작업 공간: 작업 공간 설정... 워크트리 + 브랜치 경로 복사 + HEAD 잠금 열기 + 경로 제거 잠금 해제 + diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 0ed0cd47a..7154093fe 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -27,7 +27,6 @@ Utilizar IA para gerar mensagem de commit Esconder SourceGit Mostrar Todos - Arquivo de Patch: Selecione o arquivo .patch para aplicar Ignorar mudanças de espaço em branco Aplicar Patch @@ -51,10 +50,10 @@ Bisect Abortar Inválido - Bisect. O HEAD atual é válido ou inválido? Válido Pular - Bisect. Marcar o commit atual como válido ou inválido e checar outro commit. + Bisect. Marcar o commit atual como válido ou inválido e checar outro commit. + Bisect. O HEAD atual é válido ou inválido? Blame Ignorar espaços em branco BLAME NESSE ARQUIVO NÃO É SUPORTADO!!! @@ -431,7 +430,6 @@ Verificar atualizações na inicialização Idioma Commits do Histórico - Exibir data do autor em vez da data do commit no gráfico Comprimento do Guia de Assunto GIT Habilitar Auto CRLF @@ -600,7 +598,6 @@ Excluir Submódulo OK Excluir ${0}$... - Mesclar ${0}$ em ${1}$... Enviar ${0}$... Atualizar Submódulos Todos os submódulos diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 5d3ed72ac..2523d5681 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -31,9 +31,11 @@ Скрыть остальные Показать все Трехстороннее слияние - Файл заплатки: Выберите файл .patch для применения Игнорировать изменения пробелов + Источник: + Файл + Буфер обмена Применить заплатку Пробел: Отложить @@ -55,10 +57,10 @@ Раздвоить О Плохая - Раздвоение. Текущая ГОЛОВА (HEAD) хорошая или плохая? Хорошая Пропустить - Раздвоение. Сделать текущую ревизию хорошей или плохой и переключиться на другой. + Раздвоение. Сделать текущую ревизию хорошей или плохой и переключиться на другой. + Раздвоение. Текущая ГОЛОВА (HEAD) хорошая или плохая? Расследование Расследование на предыдущей редакции Игнорировать изменения пробелов @@ -155,8 +157,10 @@ Сравнить c ГОЛОВОЙ (HEAD) Сравнить с рабочим каталогом Автор + Автор (время) Сообщение Ревизор + Ревизор (время) SHA Субъект Пользовательское действие @@ -167,7 +171,6 @@ Интерактивное перемещение ${0}$ в ${1}$ Изменить комментарий... Втиснуть в родительский... - Влить в ${0}$ Влить ... Выложить ${0}$ в ${1}$ Переместить ${0}$ в ${1}$ @@ -203,6 +206,11 @@ Введите сообщение ревизии. Пожалуйста, используйте пустые строки для разделения субъекта и описания! СУБЪЕКТ Сравнить + ИЗМЕНЕНИЯ + РЕВИЗИИ + РЕВИЗИИ ТОЛЬКО СЛЕВА + РЕВИЗИИ ТОЛЬКО СПРАВА + Подсказка: Если другая сторона является ГОЛОВОЙ (используя контекстное меню), вы можете использовать частично выбранные ревизии (cherry-pick). Настройка репозитория ШАБЛОН РЕВИЗИИ Встроенные параметры: @@ -304,6 +312,7 @@ Тип изменения: Копировать Копировать весь текст + Копировать как исправление Копировать полный путь Копировать путь Создать ветку... @@ -488,14 +497,21 @@ АВТОР ВРЕМЯ АВТОРА ВРЕМЯ РЕВИЗИИ - ДАТА И ВРЕМЯ ГРАФ И СУБЪЕКТ SHA + ПОДСВЕТКА В ГРАФЕ + ВСЕ + Только текущая ветка + Текущая ветка и выбранные ревизии + Только выбранные ревизии ВЫБРАНО РЕВИЗИЙ: {0} ПОКАЗЫВАТЬ КОЛОНКИ Удерживайте Ctrl или Shift, чтобы выбрать несколько ревизий. Удерживайте ⌘ или ⇧, чтобы выбрать несколько ревизий. ПОДСКАЗКИ: + Открыть в отдельном окне + Подробности ревизии + Сравнить ревизию Справка по сочетаниям клавиш ГЛОБАЛЬНЫЕ Клонировать репозиторий @@ -522,6 +538,7 @@ Загрузить (pull), запускается сразу Выложить (push), запускается сразу Принудительно перечитать репозиторий + Развернуть/Свернуть панель подробностей в «ИСТОРИИ» Переключить на «Изменения» Переключить на «Историю» Переключить на «Отложенные» @@ -542,6 +559,7 @@ Выполняется отмена Интерактивное перемещение Отложить и применить повторно локальные изменения + Обходной зацеп предварительного перемещения На: Перетаскивайте для переупорядочивания ревизий Целевая ветка: @@ -558,6 +576,10 @@ В: Опции слияния: Источник: + Тестировать на слияние... + Слияние может быть выполнено без конфликтов + Неизвестная ошибка при тестировании слияния + Слияние вызовет конфликты Сначала мои, а потом их Сначала их, а потом мои ИСПОЛЬЗОВАТЬ ОБА @@ -620,6 +642,8 @@ ОТКРЫТЬ ИИ Дополнительная подсказка (Для перечисления ваших требований используйте `-`) Ключ API + Модель + Автоматическое получение доступных идентификаторов моделей Имя: Введённое значение — это имя для загрузки API-ключа из ENV Сервер @@ -649,13 +673,14 @@ Включить компактные каталоги в дереве изменений Язык Максимальная длина истории - Показывать время автора вместо времени ревизии на графике Показывать вкладку «ЛОКАЛЬНЫЕ ИЗМЕНЕНИЯ» по умолчанию Показывать вкладку «Изменения» в сведении ревизии по умолчанию Показать наследника в деталях комментария + Отображение относительного времени на графе ревизии Показывать метки на графике Длина темы ревизии 24-часовой + Использовать компактные имена веток в графе ревизии Создать Github-подобный аватар по умолчанию GIT Включить автозавершение CRLF @@ -718,7 +743,12 @@ Выйти Перемещение текущей ветки Отложить и применить повторно локальные изменения + Обходной зацеп предварительного перемещения На: + Тестировать на перемещение... + Перемещение может быть выполнено без конфликтов + Неизвестная ошибка при тестировании перемещения + Перемещение вызовет конфликты Добавить внешний репозиторий Редактировать внешний репозиторий Имя: @@ -912,7 +942,6 @@ Пользовательское действие Удалить ${0}$... Удалить выбранные метки ({0})... - Влить ${0}$ в ${1}$... Выложить ${0}$... Обновление подмодулей Все подмодули diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml index 53d92c3e1..e7da30851 100644 --- a/src/Resources/Locales/ta_IN.axaml +++ b/src/Resources/Locales/ta_IN.axaml @@ -20,7 +20,6 @@ மாதிரி மறு-உருவாக்கு உறுதிமொழி செய்தியை உருவாக்க செநுவைப் பயன்படுத்து - ஒட்டு கோப்பு: .ஒட்டு இடுவதற்கு கோப்பைத் தேர்ந்தெடு வெள்ளைவெளி மாற்றங்களைப் புறக்கணி ஒட்டு இடு @@ -96,7 +95,6 @@ பணிமரத்துடன் ஒப்பிடுக பாகொவ-வை தனிப்பயன் செயல் - ${0}$ இதற்கு ஒன்றிணை ஒன்றிணை ... உறுதிமொழி திரும்பபெறு ஒட்டாக சேமி... @@ -430,7 +428,6 @@ தேதி வடிவம் மொழி வரலாற்று உறுதிமொழிகள் - வரைபடத்தில் உறுதிமொழி நேரத்திற்குப் பதிலாக ஆசிரியர் நேரத்தைக் காட்டு உறுதிமொழி விவரங்களில் குழந்தைகளைக் காட்டு உறுதிமொழி வரைபடத்தில் குறிச்சொற்களைக் காட்டு பொருள் வழிகாட்டி நீளம் @@ -618,7 +615,6 @@ துணை தொகுதியை நீக்கு சரி நீக்கு ${0}$... - ${0}$ இதை ${1}$ இல் இணை... தள்ளு ${0}$... துணைத்தொகுதிகளைப் புதுப்பி அனைத்து துணைத்தொகுதிகள் diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml index b80e6523d..9193a7d63 100644 --- a/src/Resources/Locales/uk_UA.axaml +++ b/src/Resources/Locales/uk_UA.axaml @@ -20,7 +20,6 @@ Модель ПЕРЕГЕНЕРУВАТИ Використати AI для генерації повідомлення коміту - Файл патчу: Виберіть файл .patch для застосування Ігнорувати зміни пробілів Застосувати Патч @@ -96,7 +95,6 @@ Порівняти з робочим деревом SHA Спеціальна дія - Злиття в ${0}$ Злити ... Скасувати коміт Зберегти як патч... @@ -434,7 +432,6 @@ Формат дати Мова Кількість комітів в історії - Показувати час автора замість часу коміту в графі Показувати дочірні коміти в деталях Показувати теги в графі комітів Довжина лінії-орієнтира для теми @@ -622,7 +619,6 @@ Видалити підмодуль OK Видалити ${0}$... - Злиття ${0}$ в ${1}$... Надіслати ${0}$... Оновити підмодулі Усі підмодулі diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 42fe27a76..12cb561bc 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -31,9 +31,11 @@ 隐藏其他 显示全部 尝试三路合并 - 补丁文件 : 选择补丁文件 忽略空白符号 + 补丁来源 : + 文件 + 剪贴板 应用补丁 空白符号处理 : 应用贮藏 @@ -55,10 +57,12 @@ 二分定位(bisect) 终止 标记错误 - 二分定位进行中。当前提交是 '正确' 还是 '错误' ? 标记正确 无法判定 - 二分定位进行中。请标记当前的提交是 '正确' 还是 '错误',然后检出另一个提交。 + 二分定位进行中。请检出另一个提交并标记其是【正确】还是【错误】 + 二分定位进行中。请标记当前提交为【错误】,或检出另一个提交并标记为【错误】。 + 二分定位进行中。请标记当前的提交是【正确】还是【错误】,然后检出另一个提交。 + 二分定位进行中。当前提交是【正确】还是【错误】? 逐行追溯(blame) 对当前版本的前一版本执行逐行追溯操作 忽略空白符变化 @@ -155,8 +159,10 @@ 与当前HEAD比较 与本地工作树比较 作者 + 修改时间 提交信息 提交者 + 提交时间 提交指纹 主题 自定义操作 @@ -167,7 +173,6 @@ 交互式变基 ${0}$ 到 ${1}$ 修改提交信息... 合并至父提交... - 合并(merge)此提交至 ${0}$ 合并(merge)... 推送(push) ${0}$ 到 ${1}$ 变基(rebase) ${0}$ 到 ${1} @@ -252,6 +257,7 @@ 分钟 自定义规范化提交类型 默认远程 + 自动更新子模块时启用 '--recursive' 选项 默认合并方式 ISSUE追踪 新增匹配Azure DevOps规则 @@ -309,6 +315,7 @@ 类型: 复制 复制全部文本 + 复制为补丁 复制完整路径 复制路径 新建分支 ... @@ -362,6 +369,7 @@ 标签名 : 同时删除远程仓库中的此标签 二进制文件 + 空文件 文件权限已变化 首个差异 忽略空白符号变化 @@ -493,7 +501,6 @@ 作者 修改时间 提交时间 - 日期时间 路线图与主题 提交指纹 高亮分支 @@ -573,6 +580,10 @@ 目标分支 : 合并方式 : 合并目标 : + 检测合并冲突中... + 合并操作不会产生冲突 + 检测合并冲突时出现未知错误 + 合并操作将存在冲突文件 先应用 MINE 后 THEIRS 先应用 THEIRS 后 MINE 应用全部 @@ -666,7 +677,6 @@ 在变更列表树中启用紧凑文件夹模式 显示语言 最大历史提交数 - 在提交路线图中显示修改时间而非提交时间 默认显示【本地更改】页 在提交详情页默认打开【变更对比】标签页 在提交详情页中显示子提交列表 @@ -674,6 +684,7 @@ 在提交路线图中显示标签 SUBJECT字数检测 24小时制 + 在提交路线图中使用精简分支名 生成GitHub风格的默认头像 GIT配置 自动换行转换 @@ -738,6 +749,10 @@ 自动贮藏并恢复本地变更 绕过 pre-rebase 钩子 目标提交 : + 检测变基冲突中 ... + 未检测到文件冲突 + 检测变基冲突时出现未知错误 + 检测到冲突文件 添加远程仓库 编辑远程仓库 远程名 : @@ -931,12 +946,12 @@ 自定义操作 删除 ${0}$... 删除选中 {0} 个标签... - 合并 ${0}$ 到 ${1}$... 推送 ${0}$... 更新子模块 更新所有子模块 如未初始化子模块,先初始化 子模块 : + 递归更新子孙模块 更新到子模块自己的远程踪分支 仓库地址 : 日志列表 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 2002b40eb..5ccc1eb7e 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -31,9 +31,11 @@ 隱藏其他 顯示全部 嘗試三向合併 - 修補檔: 選擇修補檔 忽略空白符號 + 修補檔來源: + 檔案 + 剪貼簿 套用修補檔 空白字元處理: 套用擱置變更 @@ -55,10 +57,12 @@ 二分搜尋 (bisect) 中止 標記為錯誤 - 二分搜尋進行中。目前的提交是「良好」是「錯誤」? 標記為良好 無法確認 - 二分搜尋進行中。請標記目前的提交為「良好」或「錯誤」,然後簽出另一個提交。 + 二分搜尋進行中。請簽出另一個提交,然後標記該提交為「良好」或「錯誤」。 + 二分搜尋進行中。請標記目前的提交為「錯誤」,或簽出另一個提交並標記為「錯誤」。 + 二分搜尋進行中。請標記目前的提交為「良好」或「錯誤」,然後簽出另一個提交。 + 二分搜尋進行中。目前的提交是「良好」是「錯誤」? 逐行溯源 (blame) 對上一個版本執行逐行溯源 忽略空白符號變化 @@ -155,8 +159,10 @@ 與目前 HEAD 比較 與本機工作區比較 作者 + 修改時間 提交訊息 提交者 + 提交時間 提交編號 標題 自訂動作 @@ -167,7 +173,6 @@ 互動式重定基底 ${0}$ 至 ${1}$ 編輯提交訊息... 合併至父提交... - 合併 (merge) 此提交到 ${0}$ 合併 (merge)... 推送(push) ${0}$ 至 ${1}$ 重定基底 (rebase) ${0}$ 至 ${1}$ @@ -252,6 +257,7 @@ 分鐘 自訂約定式提交類型 預設遠端存放庫 + 自動更新子模組時啟用「--recursive」选项 預設合併模式 Issue 追蹤 新增符合 Azure DevOps 規則 @@ -309,6 +315,7 @@ 類型: 複製 複製全部內容 + 複製為修補檔 複製完整路徑 複製路徑 新增分支... @@ -362,6 +369,7 @@ 標籤名稱: 同時刪除遠端存放庫中的此標籤 二進位檔案 + 空檔案 檔案權限已變更 第一個差異 忽略空白符號變化 @@ -493,7 +501,6 @@ 作者 修改時間 提交時間 - 日期時間 路線圖與訊息標題 提交編號 上色分支 @@ -573,6 +580,10 @@ 目標分支: 合併方式: 合併來源: + 偵測合併衝突中... + 合併操作不會產生衝突 + 偵測合併衝突時發生未知錯誤 + 合併操作將存在衝突檔案 先套用我方版本 (ours),再套用對方版本 (theirs) 先套用對方版本 (theirs),再套用我方版本 (ours) 套用兩者 @@ -666,7 +677,6 @@ 在樹狀變更目錄中啟用密集資料夾模式 顯示語言 最大歷史提交數 - 在提交路線圖中顯示修改時間而非提交時間 預設顯示 [本機變更] 頁面 在提交詳細資訊頁面預設顯示 [變更對比] 在提交詳細資訊中顯示後續提交 @@ -674,6 +684,7 @@ 在路線圖中顯示標籤 提交標題字數偵測 24 小時制 + 在提交路線圖中使用簡潔的分支標籤 產生 GitHub 風格的預設頭貼 Git 設定 自動換行轉換 @@ -738,6 +749,10 @@ 自動擱置變更並復原本機變更 繞過 pre-rebase 鉤子 目標提交: + 偵測重定基底衝突中... + 重定基底操作不會產生衝突 + 偵測重定基底衝突時發生未知錯誤 + 重定基底操作將存在衝突檔案 新增遠端存放庫 編輯遠端存放庫 遠端名稱: @@ -931,12 +946,12 @@ 自訂動作 刪除 ${0}$... 刪除所選的 {0} 個標籤... - 合併 ${0}$ 到 ${1}$... 推送 ${0}$... 更新子模組 更新所有子模組 如果子模組尚未初始化,則將其初始化 子模組: + 遞迴更新多層級子模組 更新至子模組的遠端追蹤分支 存放庫網址: 記錄 diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index 29781b45b..bddbdf19d 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -19,45 +19,39 @@ - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - + diff --git a/src/Resources/Themes.axaml b/src/Resources/Themes.axaml index 02f180243..4967a14f6 100644 --- a/src/Resources/Themes.axaml +++ b/src/Resources/Themes.axaml @@ -31,7 +31,7 @@ #0000EE #FFE4E4E4 Black - #FFF0F5F9 + #FFF0F5F9 @@ -42,7 +42,7 @@ #FF2B2B2B #FF1C1C1C #FF8F8F8F - #FFDDDDDD + #FFE0E0E0 #FFFAFAD2 #FF252525 #400078D7 @@ -53,8 +53,8 @@ #FF303030 #FF333333 #FF4F4F4F - #FFDDDDDD - #40F1F1F1 + #FFDFDFDF + #FF9F9F9F #3C000000 #C03A5C3F #C0633F3E @@ -64,7 +64,7 @@ #4DAAFC #FF383838 #FFF0F0F0 - #FF2B2B2B + #FF272727 @@ -99,8 +99,8 @@ - + fonts:Inter#Inter - fonts:SourceGit#JetBrains Mono + fonts:SourceGit#JetBrains Mono NL diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index cc02ea1e3..4a3e5baed 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -1,4 +1,4 @@ - + WinExe net10.0 @@ -48,16 +48,14 @@ - - - - - - + + + + + - @@ -70,3 +68,5 @@ + + diff --git a/src/ViewModels/AddToIgnore.cs b/src/ViewModels/AddToIgnore.cs index a502c1725..c88cf1e7f 100644 --- a/src/ViewModels/AddToIgnore.cs +++ b/src/ViewModels/AddToIgnore.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; @@ -6,6 +7,11 @@ namespace SourceGit.ViewModels { public class AddToIgnore : Popup { + public List StorageFiles + { + get; + } + [Required(ErrorMessage = "Ignore pattern is required!")] public string Pattern { @@ -14,17 +20,23 @@ public string Pattern } [Required(ErrorMessage = "Storage file is required!!!")] - public Models.GitIgnoreFile StorageFile + public Models.GitIgnoreFile SelectedStorageFile { - get; - set; + get => _selectedStorageFile; + set + { + if (SetProperty(ref _selectedStorageFile, value, true)) + Pattern = value.Pattern; + } } public AddToIgnore(Repository repo, string pattern) { _repo = repo; _pattern = pattern; - StorageFile = Models.GitIgnoreFile.Supported[0]; + + StorageFiles = Models.GitIgnoreFile.GetSupported(repo.FullPath, repo.GitDir, pattern); + SelectedStorageFile = StorageFiles[0]; } public override async Task Sure() @@ -32,7 +44,7 @@ public override async Task Sure() using var lockWatcher = _repo.LockWatcher(); ProgressDescription = "Adding Ignored File(s) ..."; - var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir); + var file = _selectedStorageFile.FullPath; if (!File.Exists(file)) { await File.WriteAllLinesAsync(file!, [_pattern]); @@ -52,5 +64,6 @@ public override async Task Sure() private readonly Repository _repo; private string _pattern; + private Models.GitIgnoreFile _selectedStorageFile; } } diff --git a/src/ViewModels/AddWorktree.cs b/src/ViewModels/AddWorktree.cs index a818fdc18..22323306e 100644 --- a/src/ViewModels/AddWorktree.cs +++ b/src/ViewModels/AddWorktree.cs @@ -24,25 +24,31 @@ public bool CreateNewBranch if (SetProperty(ref _createNewBranch, value, true)) { if (value) - SelectedBranch = string.Empty; + SelectedBranch = null; else - SelectedBranch = LocalBranches.Count > 0 ? LocalBranches[0] : string.Empty; + SelectedBranch = LocalBranches.Count > 0 ? LocalBranches[0] : null; } } } - public List LocalBranches + public List LocalBranches { get; private set; } - public string SelectedBranch + public Models.Branch SelectedBranch { get => _selectedBranch; set => SetProperty(ref _selectedBranch, value); } + public string NewBranchName + { + get => _newBranchName; + set => SetProperty(ref _newBranchName, value); + } + public bool SetTrackingBranch { get => _setTrackingBranch; @@ -69,12 +75,12 @@ public AddWorktree(Repository repo) { _repo = repo; - LocalBranches = new List(); + LocalBranches = new List(); RemoteBranches = new List(); foreach (var branch in repo.Branches) { if (branch.IsLocal) - LocalBranches.Add(branch.Name); + LocalBranches.Add(branch); else RemoteBranches.Add(branch); } @@ -109,7 +115,7 @@ public override async Task Sure() using var lockWatcher = _repo.LockWatcher(); ProgressDescription = "Adding worktree ..."; - var branchName = _selectedBranch; + var branchName = GetBranchName(false); var tracking = (_setTrackingBranch && _selectedTrackingBranch != null) ? _selectedTrackingBranch.FriendlyName : string.Empty; var log = _repo.CreateLog("Add Worktree"); @@ -128,18 +134,44 @@ private void AutoSelectTrackingBranch() if (!_setTrackingBranch || RemoteBranches.Count == 0) return; - var name = string.IsNullOrEmpty(_selectedBranch) ? System.IO.Path.GetFileName(_path.TrimEnd('/', '\\')) : _selectedBranch; - var remoteBranch = RemoteBranches.Find(b => b.Name.EndsWith(name, StringComparison.Ordinal)); - if (remoteBranch == null) - remoteBranch = RemoteBranches[0]; + var name = GetBranchName(true); + if (!string.IsNullOrEmpty(name)) + { + var remoteBranch = RemoteBranches.Find(b => b.Name.EndsWith(name, StringComparison.Ordinal)); + if (remoteBranch != null) + { + SelectedTrackingBranch = remoteBranch; + return; + } + } + + SelectedTrackingBranch = RemoteBranches[0]; + } + + private string GetBranchName(bool fallback) + { + do + { + if (!_createNewBranch) + { + if (_selectedBranch != null) + return _selectedBranch.Name; + + break; + } + + if (!string.IsNullOrEmpty(_newBranchName)) + return _newBranchName; + } while (false); - SelectedTrackingBranch = remoteBranch; + return fallback ? System.IO.Path.GetFileName(_path.TrimEnd('/', '\\')) : string.Empty; } private Repository _repo = null; private string _path = string.Empty; private bool _createNewBranch = true; - private string _selectedBranch = string.Empty; + private Models.Branch _selectedBranch = null; + private string _newBranchName = string.Empty; private bool _setTrackingBranch = false; private Models.Branch _selectedTrackingBranch = null; } diff --git a/src/ViewModels/Apply.cs b/src/ViewModels/Apply.cs index 3578c12f2..6d1d001ef 100644 --- a/src/ViewModels/Apply.cs +++ b/src/ViewModels/Apply.cs @@ -1,12 +1,14 @@ -using System.ComponentModel.DataAnnotations; +using System; +using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; +using Avalonia.Input.Platform; + namespace SourceGit.ViewModels { public class Apply : Popup { - [Required(ErrorMessage = "Patch file is required!!!")] [CustomValidation(typeof(Apply), nameof(ValidatePatchFile))] public string PatchFile { @@ -26,22 +28,40 @@ public Models.ApplyWhiteSpaceMode SelectedWhiteSpaceMode set; } + public bool FromClipboard + { + get => _fromClipboard; + set + { + if (SetProperty(ref _fromClipboard, value)) + ValidateProperty(_patchFile, nameof(PatchFile)); + } + } + public bool ThreeWayMerge { get; set; } + public IClipboard Clipboard + { + get; + set; + } = null; + public Apply(Repository repo) { _repo = repo; - SelectedWhiteSpaceMode = Models.ApplyWhiteSpaceMode.Supported[0]; } - public static ValidationResult ValidatePatchFile(string file, ValidationContext _) + public static ValidationResult ValidatePatchFile(string file, ValidationContext ctx) { - if (File.Exists(file)) + if (ctx.ObjectInstance is not Apply apply) + return new ValidationResult("Invalid object instance!!!"); + + if (apply.FromClipboard || File.Exists(file)) return ValidationResult.Success; return new ValidationResult($"File '{file}' can NOT be found!!!"); @@ -52,20 +72,45 @@ public override async Task Sure() using var lockWatcher = _repo.LockWatcher(); ProgressDescription = "Apply patch..."; + var finalPatchFile = _patchFile; + if (_fromClipboard) + { + if (Clipboard == null) + { + _repo.SendNotification("Clipboard service is not available!!!", true); + return false; + } + + var content = await Clipboard.TryGetTextAsync(); + if (string.IsNullOrEmpty(content) || !content.StartsWith("diff --git ", StringComparison.Ordinal)) + { + _repo.SendNotification("There's no valid patch content in clipboard!!!", true); + return false; + } + + finalPatchFile = Path.GetTempFileName(); + File.WriteAllText(finalPatchFile, content); + } + var log = _repo.CreateLog("Apply Patch"); Use(log); var extra = ThreeWayMerge ? "--3way" : string.Empty; - var succ = await new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, extra) + var succ = await new Commands.Apply(_repo.FullPath, finalPatchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, extra) .Use(log) .ExecAsync(); log.Complete(); + + if (_fromClipboard) + File.Delete(finalPatchFile); + return succ; } private readonly Repository _repo = null; private string _patchFile = string.Empty; + private bool _fromClipboard = false; private bool _ignoreWhiteSpace = true; } } diff --git a/src/ViewModels/Clone.cs b/src/ViewModels/Clone.cs index a215d5e28..31917d646 100644 --- a/src/ViewModels/Clone.cs +++ b/src/ViewModels/Clone.cs @@ -161,7 +161,7 @@ public override async Task Sure() if (submodules.Count > 0) await new Commands.Submodule(path) .Use(log) - .UpdateAsync(submodules, true); + .UpdateAsync(submodules, true, true, false); } log.Complete(); diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 25155771c..59204feb2 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -13,52 +13,6 @@ public string Title get; } - public bool IgnoreWhitespace - { - get => Preferences.Instance.IgnoreWhitespaceChangesInDiff; - set - { - if (value != Preferences.Instance.IgnoreWhitespaceChangesInDiff) - { - Preferences.Instance.IgnoreWhitespaceChangesInDiff = value; - OnPropertyChanged(); - LoadContent(); - } - } - } - - public bool ShowEntireFile - { - get => Preferences.Instance.UseFullTextDiff; - set - { - if (value != Preferences.Instance.UseFullTextDiff) - { - Preferences.Instance.UseFullTextDiff = value; - OnPropertyChanged(); - - if (Content is TextDiffContext ctx) - LoadContent(); - } - } - } - - public bool UseSideBySide - { - get => Preferences.Instance.UseSideBySideDiff; - set - { - if (value != Preferences.Instance.UseSideBySideDiff) - { - Preferences.Instance.UseSideBySideDiff = value; - OnPropertyChanged(); - - if (Content is TextDiffContext ctx && ctx.IsSideBySide() != value) - Content = ctx.SwitchMode(); - } - } - } - public string FileModeChange { get => _fileModeChange; @@ -71,6 +25,12 @@ public bool IsTextDiff private set => SetProperty(ref _isTextDiff, value); } + public bool IsIgnoreWhitespaceVisible + { + get => _isIgnoreWhitespaceVisible; + private set => SetProperty(ref _isIgnoreWhitespaceVisible, value); + } + public object Content { get => _content; @@ -91,6 +51,7 @@ public DiffContext(string repo, Models.DiffOption option, DiffContext previous = if (previous != null) { _isTextDiff = previous._isTextDiff; + _isIgnoreWhitespaceVisible = previous._isIgnoreWhitespaceVisible; _content = previous._content; _fileModeChange = previous._fileModeChange; _unifiedLines = previous._unifiedLines; @@ -124,19 +85,26 @@ public void OpenExternalMergeTool() public void CheckSettings() { + var pref = Preferences.Instance; + if (Content is TextDiffContext ctx) { - if ((ShowEntireFile && _info.UnifiedLines != _entireFileLine) || - (!ShowEntireFile && _info.UnifiedLines == _entireFileLine) || - (IgnoreWhitespace != _info.IgnoreWhitespace)) + if ((pref.UseFullTextDiff && _info.UnifiedLines != _entireFileLines) || + (!pref.UseFullTextDiff && _info.UnifiedLines == _entireFileLines) || + (pref.IgnoreWhitespaceChangesInDiff != _info.IgnoreWhitespace)) { LoadContent(); return; } - if (ctx.IsSideBySide() != UseSideBySide) + if (ctx.IsSideBySide() != pref.UseSideBySideDiff) Content = ctx.SwitchMode(); } + else if (Content is Models.NoOrEOLChange) + { + if (pref.IgnoreWhitespaceChangesInDiff != _info.IgnoreWhitespace) + LoadContent(); + } } private void LoadContent() @@ -150,10 +118,12 @@ private void LoadContent() Task.Run(async () => { - var numLines = Preferences.Instance.UseFullTextDiff ? _entireFileLine : _unifiedLines; - var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff; + var pref = Preferences.Instance; + var numLines = pref.UseFullTextDiff ? _entireFileLines : _unifiedLines; + var ignoreWhitespace = pref.IgnoreWhitespaceChangesInDiff; + var ignoreCRAtEOL = pref.IgnoreCRAtEOLInDiff; - var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace) + var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace, ignoreCRAtEOL) .ReadAsync() .ConfigureAwait(false); @@ -262,6 +232,10 @@ private void LoadContent() else rs = latest.LFSDiff; } + else if (IsEmptyFileHash(latest.OldHash) || IsEmptyFileHash(latest.NewHash)) + { + rs = new Models.EmptyFile(); + } else { rs = new Models.NoOrEOLChange(); @@ -274,6 +248,7 @@ private void LoadContent() if (rs is Models.TextDiff cur) { IsTextDiff = true; + IsIgnoreWhitespaceVisible = true; if (Preferences.Instance.UseSideBySideDiff) Content = new TwoSideTextDiff(_option, cur, _content as TextDiffContext); @@ -283,6 +258,7 @@ private void LoadContent() else { IsTextDiff = false; + IsIgnoreWhitespaceVisible = (rs is Models.NoOrEOLChange); Content = rs; } }); @@ -314,6 +290,20 @@ private void LoadContent() }; } + private bool IsEmptyFileHash(string hash) + { + if (string.IsNullOrEmpty(hash)) + return false; + + if (hash.Length == 40) + return hash.Equals(Models.EmptyFile.SHA1, StringComparison.Ordinal); + + if (hash.Length == 64) + return hash.Equals(Models.EmptyFile.SHA256, StringComparison.Ordinal); + + return false; + } + private class Info { public string Argument { get; } @@ -341,12 +331,13 @@ public bool IsSame(Info other) } } - private readonly int _entireFileLine = 999999999; + private readonly int _entireFileLines = 999999999; private readonly string _repo; private readonly Models.DiffOption _option = null; private string _fileModeChange = string.Empty; private int _unifiedLines = 4; private bool _isTextDiff = false; + private bool _isIgnoreWhitespaceVisible = true; private object _content = null; private Info _info = null; } diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 7544003c6..4df2b0fdd 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -44,14 +44,27 @@ public bool IsSHAColumnVisible } } - public bool IsDateTimeColumnVisible + public bool IsAuthorTimeColumnVisible { - get => _repo.UIStates.IsDateTimeColumnVisibleInHistory; + get => _repo.UIStates.IsAuthorTimeColumnVisibleInHistory; set { - if (_repo.UIStates.IsDateTimeColumnVisibleInHistory != value) + if (_repo.UIStates.IsAuthorTimeColumnVisibleInHistory != value) { - _repo.UIStates.IsDateTimeColumnVisibleInHistory = value; + _repo.UIStates.IsAuthorTimeColumnVisibleInHistory = value; + OnPropertyChanged(); + } + } + } + + public bool IsCommitTimeColumnVisible + { + get => _repo.UIStates.IsCommitTimeColumnVisibleInHistory; + set + { + if (_repo.UIStates.IsCommitTimeColumnVisibleInHistory != value) + { + _repo.UIStates.IsCommitTimeColumnVisibleInHistory = value; OnPropertyChanged(); } } @@ -62,6 +75,7 @@ public List Commits get => _commits; set { + GenerateGraph(value, true); if (SetProperty(ref _commits, value)) PostCommitsChanged(); } @@ -82,7 +96,6 @@ public Models.CommitGraphHighlighting GraphHighlighting { _repo.UIStates.GraphHighlighting = value; GenerateGraph(_commits); - OnPropertyChanged(); } } } @@ -92,7 +105,8 @@ public List SelectedCommits get => _selectedCommits; set { - if (SetProperty(ref _selectedCommits, value)) + var oldCount = _selectedCommits.Count; + if (SetProperty(ref _selectedCommits, value) && oldCount + value.Count > 0) PostSelectedCommitsChanged(); } } @@ -151,6 +165,12 @@ public GridLength BottomArea } } + public double AuthorColumnWidth + { + get => _repo.UIStates.AuthorColumnWidth; + set => _repo.UIStates.AuthorColumnWidth = value; + } + public bool IsOpenAsStandaloneVisible { get => DetailContext is CommitDetail or RevisionCompare; @@ -180,21 +200,6 @@ public void NotifyCurrentBranchChanged() OnPropertyChanged(nameof(CurrentBranch)); } - public void GenerateGraph(List commits) - { - var firstParentOnly = _repo.UIStates.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly); - var highlighting = _repo.UIStates.GraphHighlighting; - var extraHeads = new HashSet(); - - if (highlighting >= Models.CommitGraphHighlighting.SelectedCommitsOnly) - { - foreach (var c in _selectedCommits) - extraHeads.Add(c.SHA); - } - - Graph = Models.CommitGraph.Generate(commits, firstParentOnly, highlighting, extraHeads); - } - public Models.BisectState UpdateBisectInfo() { var test = Path.Combine(_repo.GitDir, "BISECT_START"); @@ -204,26 +209,40 @@ public Models.BisectState UpdateBisectInfo() return Models.BisectState.None; } + var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").GetResult(); var info = new Models.Bisect(); + var markedHead = false; var dir = Path.Combine(_repo.GitDir, "refs", "bisect"); if (Directory.Exists(dir)) { var files = new DirectoryInfo(dir).GetFiles(); foreach (var file in files) { + var sha = File.ReadAllText(file.FullName).Trim(); + if (!markedHead) + markedHead = head.Equals(sha, StringComparison.Ordinal); + if (file.Name.StartsWith("bad")) - info.Bads.Add(File.ReadAllText(file.FullName).Trim()); + info.Bads.Add(sha); else if (file.Name.StartsWith("good")) - info.Goods.Add(File.ReadAllText(file.FullName).Trim()); + info.Goods.Add(sha); + else if (file.Name.StartsWith("skip")) + info.Skipped.Add(sha); } } Bisect = info; - if (info.Bads.Count == 0 || info.Goods.Count == 0) - return Models.BisectState.WaitingForRange; - else - return Models.BisectState.Detecting; + if (info.Bads.Count == 0) + return Models.BisectState.WaitingForFirstBad; + + if (markedHead) + return Models.BisectState.WaitingForCheckoutAnother; + + if (info.Goods.Count == 0) + return Models.BisectState.WaitingForFirstGood; + + return Models.BisectState.WaitingForMark; } public void NavigateTo(string commitSHA) @@ -269,6 +288,12 @@ public void NavigateTo(string commitSHA) .ConfigureAwait(false); } + public void CheckoutCommitDetached(Models.Commit c) + { + if (!c.IsCurrentHead && _repo.CanCreatePopup()) + _repo.ShowPopup(new CheckoutCommit(_repo, c)); + } + public async Task CheckoutBranchByDecoratorAsync(Models.Decorator decorator) { if (decorator == null) @@ -485,6 +510,21 @@ private void PostSelectedCommitsChanged() GenerateGraph(_commits); } + private void GenerateGraph(List commits, bool commitsChanged = false) + { + var firstParentOnly = _repo.UIStates.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly); + var highlighting = _repo.UIStates.GraphHighlighting; + var extraHeads = new HashSet(); + + if (highlighting >= Models.CommitGraphHighlighting.SelectedCommitsOnly) + { + foreach (var c in _selectedCommits) + extraHeads.Add(c.SHA); + } + + Graph = Models.CommitGraph.Generate(commits, commitsChanged, firstParentOnly, highlighting, extraHeads); + } + private Repository _repo = null; private CommitDetailSharedData _commitDetailSharedData = null; private bool _isLoading = true; diff --git a/src/ViewModels/InProgressContexts.cs b/src/ViewModels/InProgressContexts.cs index 5854bb6c3..7248cd096 100644 --- a/src/ViewModels/InProgressContexts.cs +++ b/src/ViewModels/InProgressContexts.cs @@ -161,6 +161,10 @@ protected override void OnAborted() var rebaseApplyDir = Path.Combine(_gitDir, "rebase-apply"); if (Directory.Exists(rebaseApplyDir)) Directory.Delete(rebaseApplyDir, true); + + var jobFile = Path.Combine(_gitDir, "sourcegit.interactive_rebase"); + if (File.Exists(jobFile)) + File.Delete(jobFile); } private readonly string _gitDir; diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 5beb3f136..2a765a146 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -50,53 +50,25 @@ public Launcher(string startupRepo) Models.Notification.Raised += DispatchNotification; _ignoreIndexChange = true; + ActiveWorkspace = Preferences.Instance.GetActiveWorkspace(); Pages = new AvaloniaList(); AddNewTab(); - var pref = Preferences.Instance; - ActiveWorkspace = pref.GetActiveWorkspace(); - var repos = ActiveWorkspace.Repositories.ToArray(); foreach (var repo in repos) - { - var node = pref.FindNode(repo) ?? - new RepositoryNode - { - Id = repo, - Name = Path.GetFileName(repo), - Bookmark = 0, - IsRepository = true, - }; - - OpenRepositoryInTab(node, null); - } + OpenRepositoryInTab(repo, null); _ignoreIndexChange = false; - if (TryOpenRepositoryFromPath(startupRepo)) - return; - - if (!string.IsNullOrEmpty(startupRepo)) - { - var test = new Commands.QueryRepositoryRootPath(startupRepo).GetResult(); - if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut)) - { - var node = pref.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), null, false); - Welcome.Instance.Refresh(); - - OpenRepositoryInTab(node, null); - return; - } - } - - var activeIdx = ActiveWorkspace.ActiveIdx; - if (activeIdx > 0 && activeIdx < Pages.Count) + if (!TryOpenRepositoryFromPath(startupRepo)) { - ActivePage = Pages[activeIdx]; - return; + var activeIdx = ActiveWorkspace.ActiveIdx; + if (activeIdx > 0 && activeIdx < Pages.Count) + ActivePage = Pages[activeIdx]; + else + ActivePage = Pages[0]; } - ActivePage = Pages[0]; PostActivePageChanged(); } @@ -112,6 +84,14 @@ public bool TryOpenRepositoryFromPath(string repo) OpenRepositoryInTab(node, null); return true; } + else + { + if (ActivePage is not { Data: Welcome { }, Popup: null }) + AddNewTab(); + + ActivePage.Popup = new Init(ActivePage.Node.Id, repo, null, 0, test.StdErr ?? "Unknown error occurred while opening the repository."); + return true; + } } return false; @@ -149,18 +129,7 @@ public void SwitchWorkspace(Workspace to) var repos = to.Repositories.ToArray(); foreach (var repo in repos) - { - var node = pref.FindNode(repo) ?? - new RepositoryNode - { - Id = repo, - Name = Path.GetFileName(repo), - Bookmark = 0, - IsRepository = true, - }; - - OpenRepositoryInTab(node, null); - } + OpenRepositoryInTab(repo, null); var activeIdx = to.ActiveIdx; if (activeIdx >= 0 && activeIdx < Pages.Count) @@ -230,6 +199,8 @@ public void CloseTab(LauncherPage page) _activeWorkspace.Repositories.Clear(); _activeWorkspace.ActiveIdx = 0; + if (last.Node.IsUnmanaged) + last.Node.SaveMinimalInfo(repo.GitDir); repo.Close(); Welcome.Instance.ClearSearchFilter(); @@ -298,6 +269,21 @@ public void CloseRightTabs() GC.Collect(); } + public void OpenRepositoryInTab(string repo, LauncherPage page) + { + var normalizedPath = repo.Replace('\\', '/').TrimEnd('/'); + var node = Preferences.Instance.FindNode(normalizedPath) ?? new RepositoryNode + { + Id = normalizedPath, + Name = Path.GetFileName(normalizedPath), + Bookmark = 0, + IsRepository = true, + IsUnmanaged = true + }; + + OpenRepositoryInTab(node, null); + } + public void OpenRepositoryInTab(RepositoryNode node, LauncherPage page) { foreach (var one in Pages) @@ -333,6 +319,9 @@ public void OpenRepositoryInTab(RepositoryNode node, LauncherPage page) return; } + if (node.IsUnmanaged) + node.LoadMinimalInfo(gitDir); + var repo = new Repository(isBare, node.Id, gitDir); repo.Open(); @@ -434,6 +423,9 @@ private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace = if (removeFromWorkspace) _activeWorkspace.Repositories.Remove(repo.FullPath); + if (page.Node.IsUnmanaged) + page.Node.SaveMinimalInfo(repo.GitDir); + repo.Close(); } diff --git a/src/ViewModels/LayoutInfo.cs b/src/ViewModels/LayoutInfo.cs index 1b78153aa..f993e242e 100644 --- a/src/ViewModels/LayoutInfo.cs +++ b/src/ViewModels/LayoutInfo.cs @@ -65,17 +65,10 @@ public GridLength CommitDetailFilesLeftWidth set => SetProperty(ref _commitDetailFilesLeftWidth, value); } - public DataGridLength AuthorColumnWidth - { - get => _authorColumnWidth; - set => SetProperty(ref _authorColumnWidth, new DataGridLength(value.Value, DataGridLengthUnitType.Pixel, 0, value.DisplayValue)); - } - private GridLength _repositorySidebarWidth = new GridLength(250, GridUnitType.Pixel); private GridLength _workingCopyLeftWidth = new GridLength(300, GridUnitType.Pixel); private GridLength _stashesLeftWidth = new GridLength(300, GridUnitType.Pixel); private GridLength _commitDetailChangesLeftWidth = new GridLength(256, GridUnitType.Pixel); private GridLength _commitDetailFilesLeftWidth = new GridLength(256, GridUnitType.Pixel); - private DataGridLength _authorColumnWidth = new DataGridLength(120, DataGridLengthUnitType.Pixel, 0, 120); } } diff --git a/src/ViewModels/Merge.cs b/src/ViewModels/Merge.cs index ed7936bfc..35f9567f6 100644 --- a/src/ViewModels/Merge.cs +++ b/src/ViewModels/Merge.cs @@ -1,8 +1,18 @@ using System.IO; using System.Threading.Tasks; +using Avalonia.Threading; namespace SourceGit.ViewModels { + public enum MergeTestingState + { + Disabled = 0, + Testing, + WillCauseConflicts, + UnknownError, + NoConflicts, + } + public class Merge : Popup { public object Source @@ -21,9 +31,7 @@ public Models.MergeMode Mode set { if (SetProperty(ref _mode, value)) - CanEditMessage = _mode == Models.MergeMode.Default || - _mode == Models.MergeMode.FastForward || - _mode == Models.MergeMode.NoFastForward; + CanEditMessage = _mode == Models.MergeMode.Default || _mode == Models.MergeMode.NoFastForward; } } @@ -39,6 +47,12 @@ public bool Edit set; } = false; + public MergeTestingState TestingState + { + get => _testingState; + private set => SetProperty(ref _testingState, value); + } + public Merge(Repository repo, Models.Branch source, string into, bool forceFastForward) { _repo = repo; @@ -47,6 +61,9 @@ public Merge(Repository repo, Models.Branch source, string into, bool forceFastF Source = source; Into = into; Mode = forceFastForward ? Models.MergeMode.FastForward : AutoSelectMergeMode(); + + if (!forceFastForward) + Test(); } public Merge(Repository repo, Models.Commit source, string into) @@ -57,6 +74,8 @@ public Merge(Repository repo, Models.Commit source, string into) Source = source; Into = into; Mode = AutoSelectMergeMode(); + + Test(); } public Merge(Repository repo, Models.Tag source, string into) @@ -67,6 +86,8 @@ public Merge(Repository repo, Models.Tag source, string into) Source = source; Into = into; Mode = AutoSelectMergeMode(); + + Test(); } public override async Task Sure() @@ -127,9 +148,32 @@ private Models.MergeMode AutoSelectMergeMode() return Models.MergeMode.Supported[preferredMergeModeIdx]; } + private void Test() + { + if (Native.OS.GitVersion < Models.GitVersions.TESTING_MERGE) + return; + + TestingState = MergeTestingState.Testing; + + Task.Run(async () => + { + var exitCode = await new Commands.MergeTree(_repo.FullPath, _sourceName, Into) + .GetExitCodeAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => TestingState = exitCode switch + { + 0 => MergeTestingState.NoConflicts, + 1 => MergeTestingState.WillCauseConflicts, + _ => MergeTestingState.UnknownError, + }); + }); + } + private readonly Repository _repo = null; private readonly string _sourceName; private Models.MergeMode _mode = Models.MergeMode.Default; private bool _canEditMessage = true; + private MergeTestingState _testingState = MergeTestingState.Disabled; } } diff --git a/src/ViewModels/MergeConflictEditor.cs b/src/ViewModels/MergeConflictEditor.cs index 5c739ae23..fc9d0f632 100644 --- a/src/ViewModels/MergeConflictEditor.cs +++ b/src/ViewModels/MergeConflictEditor.cs @@ -190,6 +190,9 @@ public async Task SaveAndStageAsync() for (var j = lastLineIdx; j < lines.Length; j++) builder.Append(lines[j]).Append('\n'); + if (builder.Length > 1) + builder.Length--; // Remove extra '\n' + try { // Write merged content to file diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index da7fe3e5d..ce0942d4c 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -193,12 +193,6 @@ public bool Check4UpdatesOnStartup set => SetProperty(ref _check4UpdatesOnStartup, value); } - public bool ShowAuthorTimeInGraph - { - get => _showAuthorTimeInGraph; - set => SetProperty(ref _showAuthorTimeInGraph, value); - } - public bool ShowChildren { get => _showChildren; @@ -217,6 +211,12 @@ public bool ShowTagsInGraph set => SetProperty(ref _showTagsInGraph, value); } + public bool UseCompactBranchNamesInGraph + { + get => _useCompactBranchNamesInGraph; + set => SetProperty(ref _useCompactBranchNamesInGraph, value); + } + public bool UseTwoColumnsLayoutInHistories { get => _useTwoColumnsLayoutInHistories; @@ -243,15 +243,8 @@ public bool UseSyntaxHighlighting public bool IgnoreCRAtEOLInDiff { - get => Models.DiffOption.IgnoreCRAtEOL; - set - { - if (Models.DiffOption.IgnoreCRAtEOL != value) - { - Models.DiffOption.IgnoreCRAtEOL = value; - OnPropertyChanged(); - } - } + get => _ignoreCRAtEOLInDiff; + set => SetProperty(ref _ignoreCRAtEOLInDiff, value); } public bool UseStashAndReapplyByDefault @@ -475,12 +468,6 @@ public string ExternalMergeToolMergeArgs } } - public uint StatisticsSampleColor - { - get => _statisticsSampleColor; - set => SetProperty(ref _statisticsSampleColor, value); - } - public List RepositoryNodes { get; @@ -825,8 +812,8 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private bool _useFixedTabWidth = true; private bool _useAutoHideScrollBars = true; private bool _useGitHubStyleAvatar = true; - private bool _showAuthorTimeInGraph = false; private bool _showChildren = false; + private bool _useCompactBranchNamesInGraph = true; private bool _check4UpdatesOnStartup = true; private double _lastCheckUpdateTime = 0; @@ -837,6 +824,7 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private bool _displayTimeAsPeriodInHistories = false; private bool _useSideBySideDiff = false; private bool _ignoreWhitespaceChangesInDiff = false; + private bool _ignoreCRAtEOLInDiff = true; private bool _useSyntaxHighlighting = false; private bool _enableDiffViewWordWrap = false; private bool _showHiddenSymbolsInDiffView = false; @@ -852,6 +840,5 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private string _gitDefaultCloneDir = string.Empty; private int _shellOrTerminalType = -1; - private uint _statisticsSampleColor = 0xFF00FF00; } } diff --git a/src/ViewModels/Push.cs b/src/ViewModels/Push.cs index 2da3895b7..b4d9029a9 100644 --- a/src/ViewModels/Push.cs +++ b/src/ViewModels/Push.cs @@ -212,11 +212,14 @@ public override async Task Sure() private void AutoSelectBranchByRemote() { + if (_selectedRemote == null || _selectedLocalBranch == null) + return; + // Gather branches. var branches = new List(); foreach (var branch in _repo.Branches) { - if (branch.Remote == _selectedRemote.Name) + if (!branch.IsLocal && _selectedRemote.Name.Equals(branch.Remote, StringComparison.Ordinal)) branches.Add(branch); } @@ -225,7 +228,7 @@ private void AutoSelectBranchByRemote() { foreach (var branch in branches) { - if (_selectedLocalBranch.Upstream == branch.FullName) + if (_selectedLocalBranch.Upstream.Equals(branch.FullName, StringComparison.Ordinal)) { RemoteBranches = branches; SelectedRemoteBranch = branch; @@ -237,7 +240,7 @@ private void AutoSelectBranchByRemote() // Try to find a remote branch with the same name of selected local branch. foreach (var branch in branches) { - if (_selectedLocalBranch.Name == branch.Name) + if (_selectedLocalBranch.Name.Equals(branch.Name, StringComparison.Ordinal)) { RemoteBranches = branches; SelectedRemoteBranch = branch; diff --git a/src/ViewModels/Rebase.cs b/src/ViewModels/Rebase.cs index 1bce556f8..2213a55af 100644 --- a/src/ViewModels/Rebase.cs +++ b/src/ViewModels/Rebase.cs @@ -1,7 +1,18 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; +using Avalonia.Threading; namespace SourceGit.ViewModels { + public enum RebaseTestingState + { + Disabled = 0, + Testing, + WillCauseConflicts, + UnknownError, + NoConflicts, + } + public class Rebase : Popup { public Models.Branch Current @@ -28,6 +39,12 @@ public bool NoVerify set; } + public RebaseTestingState TestingState + { + get => _testingState; + private set => SetProperty(ref _testingState, value); + } + public Rebase(Repository repo, Models.Branch current, Models.Branch on) { _repo = repo; @@ -35,6 +52,8 @@ public Rebase(Repository repo, Models.Branch current, Models.Branch on) Current = current; On = on; AutoStash = true; + + Test(); } public Rebase(Repository repo, Models.Branch current, Models.Commit on) @@ -44,6 +63,8 @@ public Rebase(Repository repo, Models.Branch current, Models.Commit on) Current = current; On = on; AutoStash = true; + + Test(); } public override async Task Sure() @@ -63,7 +84,45 @@ public override async Task Sure() return true; } + private void Test() + { + if (Native.OS.GitVersion < Models.GitVersions.REPLAY) + return; + + var head = Current.Head; + TestingState = RebaseTestingState.Testing; + Task.Run(async () => + { + var mergeBase = await new Commands.MergeBase(_repo.FullPath, head, _revision) + .GetResultAsync() + .ConfigureAwait(false); + + if (string.IsNullOrEmpty(mergeBase)) + { + Dispatcher.UIThread.Post(() => TestingState = RebaseTestingState.UnknownError); + return; + } + else if (head.Equals(mergeBase, StringComparison.Ordinal)) + { + Dispatcher.UIThread.Post(() => TestingState = RebaseTestingState.NoConflicts); + return; + } + + var exitCode = await new Commands.Replay(_repo.FullPath, _revision, $"{mergeBase}..{head}") + .GetExitCodeAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => TestingState = exitCode switch + { + 0 => RebaseTestingState.NoConflicts, + 1 => RebaseTestingState.WillCauseConflicts, + _ => RebaseTestingState.UnknownError, + }); + }); + } + private readonly Repository _repo; private readonly string _revision; + private RebaseTestingState _testingState = RebaseTestingState.Disabled; } } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 289c0e12a..01d702f95 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -806,7 +806,7 @@ public void RefreshAfterCreateBranch(Models.Branch created, bool checkout) locals.Add(b); } - var builder = BuildBranchTree(locals, []); + var builder = BuildBranchTree(locals, [], false); LocalBranchTrees = builder.Locals; RefreshCommits(); @@ -841,7 +841,7 @@ public void RefreshAfterCheckoutBranch(Models.Branch checkouted) locals.Add(b); } - var builder = BuildBranchTree(locals, []); + var builder = BuildBranchTree(locals, [], false); LocalBranchTrees = builder.Locals; CurrentBranch = checkouted; @@ -867,7 +867,7 @@ public void RefreshAfterRenameBranch(Models.Branch b, string newName) locals.Add(branch); } - var builder = BuildBranchTree(locals, []); + var builder = BuildBranchTree(locals, [], false); LocalBranchTrees = builder.Locals; RefreshCommits(); @@ -1204,7 +1204,7 @@ public void RefreshCommits() var builder = new StringBuilder(); builder .Append('-').Append(Preferences.Instance.MaxHistoryCommits).Append(' ') - .Append(_uiStates.BuildHistoryParams()); + .Append(_uiStates.BuildHistoryParams(GitDir)); var commits = await new Commands.QueryCommits(FullPath, builder.ToString()) .GetResultAsync() @@ -1218,7 +1218,6 @@ public void RefreshCommits() if (_histories != null) { _histories.IsLoading = false; - _histories.GenerateGraph(commits); _histories.Commits = commits; BisectState = _histories.UpdateBisectInfo(); @@ -1512,7 +1511,7 @@ public async Task AutoUpdateSubmodulesAsync(Models.ICommandLog log) await new Commands.Submodule(FullPath) .Use(log) - .UpdateAsync(submodules); + .UpdateAsync(submodules, false, _settings.EnableRecursiveWhenAutoUpdatingSubmodules, false); } while (false); } @@ -1524,17 +1523,7 @@ public void OpenSubmodule(string submodule) var root = Path.GetFullPath(Path.Combine(FullPath, submodule)); var normalizedPath = root.Replace('\\', '/').TrimEnd('/'); - - var node = Preferences.Instance.FindNode(normalizedPath) ?? - new RepositoryNode - { - Id = normalizedPath, - Name = Path.GetFileName(normalizedPath), - Bookmark = selfPage.Node.Bookmark, - IsRepository = true, - }; - - App.GetLauncher().OpenRepositoryInTab(node, null); + App.GetLauncher().OpenRepositoryInTab(normalizedPath, null); } public void AddWorktree() @@ -1554,16 +1543,8 @@ public void OpenWorktree(Worktree worktree) if (worktree.IsCurrent) return; - var node = Preferences.Instance.FindNode(worktree.FullPath) ?? - new RepositoryNode - { - Id = worktree.FullPath, - Name = Path.GetFileName(worktree.FullPath), - Bookmark = 0, - IsRepository = true, - }; - - App.GetLauncher().OpenRepositoryInTab(node, null); + var normalizedPath = worktree.FullPath.Replace('\\', '/').TrimEnd('/'); + App.GetLauncher().OpenRepositoryInTab(normalizedPath, null); } public async Task LockWorktreeAsync(Worktree worktree) @@ -1668,7 +1649,7 @@ private LauncherPage GetOwnerPage() return null; } - private BranchTreeNode.Builder BuildBranchTree(List branches, List remotes) + private BranchTreeNode.Builder BuildBranchTree(List branches, List remotes, bool validateExpandedNodes = true) { var builder = new BranchTreeNode.Builder(_uiStates.LocalBranchSortMode, _uiStates.RemoteBranchSortMode); if (string.IsNullOrEmpty(_filter)) @@ -1676,8 +1657,11 @@ private BranchTreeNode.Builder BuildBranchTree(List branches, Lis builder.SetExpandedNodes(_uiStates.ExpandedBranchNodesInSideBar); builder.Run(branches, remotes, false); - foreach (var invalid in builder.InvalidExpandedNodes) - _uiStates.ExpandedBranchNodesInSideBar.Remove(invalid); + if (validateExpandedNodes) + { + foreach (var invalid in builder.InvalidExpandedNodes) + _uiStates.ExpandedBranchNodesInSideBar.Remove(invalid); + } } else { @@ -1901,13 +1885,13 @@ private async Task AutoFetchOnUIThread() await new Commands.Fetch(FullPath, remote).Use(log).RunAsync(); _lastFetchTime = DateTime.Now; - IsAutoFetching = false; } catch { // Ignore all exceptions. } + IsAutoFetching = false; log?.Complete(); } diff --git a/src/ViewModels/RepositoryConfigure.cs b/src/ViewModels/RepositoryConfigure.cs index 06176f437..a76194716 100644 --- a/src/ViewModels/RepositoryConfigure.cs +++ b/src/ViewModels/RepositoryConfigure.cs @@ -101,6 +101,12 @@ public bool AskBeforeAutoUpdatingSubmodules set => _repo.Settings.AskBeforeAutoUpdatingSubmodules = value; } + public bool EnableRecursiveWhenAutoUpdatingSubmodules + { + get => _repo.Settings.EnableRecursiveWhenAutoUpdatingSubmodules; + set => _repo.Settings.EnableRecursiveWhenAutoUpdatingSubmodules = value; + } + public AvaloniaList CommitTemplates { get => _repo.Settings.CommitTemplates; diff --git a/src/ViewModels/RepositoryNode.cs b/src/ViewModels/RepositoryNode.cs index 1f5515b9d..cfee80b8e 100644 --- a/src/ViewModels/RepositoryNode.cs +++ b/src/ViewModels/RepositoryNode.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; @@ -8,6 +9,12 @@ namespace SourceGit.ViewModels { + public class RepositoryNodeMinimalInfo + { + public string FriendlyName { get; set; } = string.Empty; + public int Bookmark { get; set; } = 0; + } + public class RepositoryNode : ObservableObject { public string Id @@ -57,6 +64,13 @@ public bool IsInvalid get => _isRepository && !Directory.Exists(_id); } + [JsonIgnore] + public bool IsUnmanaged + { + get; + set; + } = false; + [JsonIgnore] public int Depth { @@ -170,6 +184,36 @@ public async Task UpdateStatusAsync(bool force, CancellationToken? token) Status = await new Commands.QueryRepositoryStatus(_id).GetResultAsync(); } + public void LoadMinimalInfo(string gitDir) + { + var savedTo = Path.Combine(gitDir, "sourcegit.node"); + if (!File.Exists(savedTo)) + return; + + try + { + var minimalInfo = JsonSerializer.Deserialize(File.ReadAllText(savedTo), JsonCodeGen.Default.RepositoryNodeMinimalInfo); + if (!string.IsNullOrEmpty(minimalInfo.FriendlyName)) + Name = minimalInfo.FriendlyName; + Bookmark = minimalInfo.Bookmark; + } + catch + { + // Ignore any error and just use default values. + } + } + + public void SaveMinimalInfo(string gitDir) + { + var savedTo = Path.Combine(gitDir, "sourcegit.node"); + var minimalInfo = new RepositoryNodeMinimalInfo + { + FriendlyName = Name, + Bookmark = Bookmark + }; + File.WriteAllText(savedTo, JsonSerializer.Serialize(minimalInfo, JsonCodeGen.Default.RepositoryNodeMinimalInfo)); + } + private string _id = string.Empty; private string _name = string.Empty; private bool _isRepository = false; diff --git a/src/ViewModels/Statistics.cs b/src/ViewModels/Statistics.cs index a16c94ecc..6b2f9a270 100644 --- a/src/ViewModels/Statistics.cs +++ b/src/ViewModels/Statistics.cs @@ -1,8 +1,5 @@ using System.Threading.Tasks; - -using Avalonia.Media; using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -15,12 +12,12 @@ public bool IsLoading private set => SetProperty(ref _isLoading, value); } - public int SelectedIndex + public Models.StatisticsMode ViewMode { - get => _selectedIndex; + get => _viewMode; set { - if (SetProperty(ref _selectedIndex, value)) + if (SetProperty(ref _viewMode, value)) RefreshReport(); } } @@ -28,37 +25,23 @@ public int SelectedIndex public Models.StatisticsReport SelectedReport { get => _selectedReport; - private set - { - value?.ChangeAuthor(null); - SetProperty(ref _selectedReport, value); - } + private set => SetProperty(ref _selectedReport, value); } - public uint SampleColor + public Models.StatisticsSamples Samples { - get => Preferences.Instance.StatisticsSampleColor; - set - { - if (value != Preferences.Instance.StatisticsSampleColor) - { - Preferences.Instance.StatisticsSampleColor = value; - OnPropertyChanged(nameof(SampleBrush)); - _selectedReport?.ChangeColor(value); - } - } - } - - public IBrush SampleBrush - { - get => new SolidColorBrush(SampleColor); + get => _samples; + private set => SetProperty(ref _samples, value); } public Statistics(string repo) { Task.Run(async () => { - var result = await new Commands.Statistics(repo, Preferences.Instance.MaxHistoryCommits).ReadAsync().ConfigureAwait(false); + var result = await new Commands.Statistics(repo, Preferences.Instance.MaxHistoryCommits) + .ReadAsync() + .ConfigureAwait(false); + Dispatcher.UIThread.Post(() => { _data = result; @@ -68,25 +51,33 @@ public Statistics(string repo) }); } + public void ChangeAuthor(Models.StatisticsAuthor author) + { + if (SelectedReport == null) + return; + + Samples = SelectedReport.GetSamples(author); + } + private void RefreshReport() { if (_data == null) return; - var report = _selectedIndex switch + SelectedReport = _viewMode switch { - 0 => _data.All, - 1 => _data.Month, + Models.StatisticsMode.All => _data.All, + Models.StatisticsMode.ThisMonth => _data.Month, _ => _data.Week, }; - report.ChangeColor(SampleColor); - SelectedReport = report; + Samples = SelectedReport.GetSamples(null); } private bool _isLoading = true; private Models.Statistics _data = null; + private Models.StatisticsMode _viewMode = Models.StatisticsMode.All; private Models.StatisticsReport _selectedReport = null; - private int _selectedIndex = 0; + private Models.StatisticsSamples _samples = null; } } diff --git a/src/ViewModels/UpdateSubmodules.cs b/src/ViewModels/UpdateSubmodules.cs index af55aba9d..323a60b2d 100644 --- a/src/ViewModels/UpdateSubmodules.cs +++ b/src/ViewModels/UpdateSubmodules.cs @@ -39,6 +39,12 @@ public bool EnableInit set; } = true; + public bool EnableRecursive + { + get; + set; + } = true; + public bool EnableRemote { get; @@ -63,6 +69,8 @@ public UpdateSubmodules(Repository repo, Models.Submodule selected) IsEnableInitVisible = true; HasPreSelectedSubmodule = false; } + + EnableRecursive = _repo.Settings.EnableRecursiveWhenAutoUpdatingSubmodules; } public override async Task Sure() @@ -87,7 +95,7 @@ public override async Task Sure() await new Commands.Submodule(_repo.FullPath) .Use(log) - .UpdateAsync(targets, EnableInit, EnableRemote); + .UpdateAsync(targets, EnableInit, EnableRecursive, EnableRemote); log.Complete(); _repo.MarkSubmodulesDirtyManually(); diff --git a/src/Views/AIAssistant.axaml.cs b/src/Views/AIAssistant.axaml.cs index c49e407f9..e2256a5ff 100644 --- a/src/Views/AIAssistant.axaml.cs +++ b/src/Views/AIAssistant.axaml.cs @@ -2,6 +2,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; +using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; @@ -89,6 +90,8 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang if (change.Property == ContentProperty) Text = Content; + else if (change.Property.Name == nameof(ActualThemeVariant) && change.NewValue != null) + Models.TextMateHelper.SetThemeByApp(_textMate); } private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) diff --git a/src/Views/AddRemote.axaml b/src/Views/AddRemote.axaml index a53cfbe1f..d1e2005d8 100644 --- a/src/Views/AddRemote.axaml +++ b/src/Views/AddRemote.axaml @@ -28,7 +28,7 @@ Height="26" VerticalAlignment="Center" CornerRadius="3" - Watermark="{DynamicResource Text.Remote.Name.Placeholder}" + PlaceholderText="{DynamicResource Text.Remote.Name.Placeholder}" Text="{Binding Name, Mode=TwoWay}"> + ItemsSource="{Binding StorageFiles, Mode=OneWay}" + SelectedItem="{Binding SelectedStorageFile, Mode=TwoWay}"> - - + - + - - + + - + diff --git a/src/Views/AddWorktree.axaml b/src/Views/AddWorktree.axaml index 3419eff8d..6af33c559 100644 --- a/src/Views/AddWorktree.axaml +++ b/src/Views/AddWorktree.axaml @@ -29,7 +29,7 @@ Height="28" CornerRadius="3" Text="{Binding Path, Mode=TwoWay}" - Watermark="{DynamicResource Text.AddWorktree.Location.Placeholder}"> + PlaceholderText="{DynamicResource Text.AddWorktree.Location.Placeholder}"> - + - - - - diff --git a/src/Views/Apply.axaml.cs b/src/Views/Apply.axaml.cs index bf8e4da4d..d0ee20103 100644 --- a/src/Views/Apply.axaml.cs +++ b/src/Views/Apply.axaml.cs @@ -1,3 +1,4 @@ +using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Platform.Storage; @@ -11,6 +12,14 @@ public Apply() InitializeComponent(); } + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + + if (DataContext is ViewModels.Apply vm && TopLevel.GetTopLevel(this) is { } toplevel) + vm.Clipboard = toplevel.Clipboard; + } + private async void SelectPatchFile(object _, RoutedEventArgs e) { var topLevel = TopLevel.GetTopLevel(this); diff --git a/src/Views/Archive.axaml b/src/Views/Archive.axaml index 5751a0e7c..bf9f9bf7a 100644 --- a/src/Views/Archive.axaml +++ b/src/Views/Archive.axaml @@ -58,7 +58,7 @@ x:Name="TxtSaveFile" Height="28" CornerRadius="3" - Watermark="{DynamicResource Text.Archive.File.Placeholder}" + PlaceholderText="{DynamicResource Text.Archive.File.Placeholder}" Text="{Binding SaveFile, Mode=TwoWay}"> - - diff --git a/src/Views/CaptionButtons.axaml.cs b/src/Views/CaptionButtons.axaml.cs index 806d9cb5e..a22591673 100644 --- a/src/Views/CaptionButtons.axaml.cs +++ b/src/Views/CaptionButtons.axaml.cs @@ -1,7 +1,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; -using Avalonia.VisualTree; namespace SourceGit.Views { @@ -23,7 +22,7 @@ public CaptionButtons() private void MinimizeWindow(object _, RoutedEventArgs e) { - var window = this.FindAncestorOfType(); + var window = TopLevel.GetTopLevel(this) as Window; if (window != null) window.WindowState = WindowState.Minimized; @@ -32,7 +31,7 @@ private void MinimizeWindow(object _, RoutedEventArgs e) private void MaximizeOrRestoreWindow(object _, RoutedEventArgs e) { - var window = this.FindAncestorOfType(); + var window = TopLevel.GetTopLevel(this) as Window; if (window != null) window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; @@ -41,7 +40,7 @@ private void MaximizeOrRestoreWindow(object _, RoutedEventArgs e) private void CloseWindow(object _, RoutedEventArgs e) { - var window = this.FindAncestorOfType(); + var window = TopLevel.GetTopLevel(this) as Window; window?.Close(); e.Handled = true; diff --git a/src/Views/ChangeStatusIcon.cs b/src/Views/ChangeStatusIcon.cs index cbb47842d..42ab10f10 100644 --- a/src/Views/ChangeStatusIcon.cs +++ b/src/Views/ChangeStatusIcon.cs @@ -47,7 +47,7 @@ public override void Render(DrawingContext context) if (Change == null || Bounds.Width <= 0) return; - var typeface = new Typeface("fonts:SourceGit#JetBrains Mono"); + var typeface = new Typeface("fonts:SourceGit#JetBrains Mono NL"); var idx = (int)(IsUnstagedChange ? Change.WorkTree : Change.Index); var indicator = INDICATOR[idx]; diff --git a/src/Views/ChangeSubmoduleUrl.axaml b/src/Views/ChangeSubmoduleUrl.axaml index a1d6cef02..e30ced8b2 100644 --- a/src/Views/ChangeSubmoduleUrl.axaml +++ b/src/Views/ChangeSubmoduleUrl.axaml @@ -36,7 +36,7 @@ Height="26" VerticalAlignment="Center" CornerRadius="3" - Watermark="{DynamicResource Text.RepositoryURL}" + PlaceholderText="{DynamicResource Text.RepositoryURL}" Text="{Binding Url, Mode=TwoWay}"> SamplesProperty = + AvaloniaProperty.Register(nameof(Samples)); + + public Models.StatisticsSamples Samples + { + get => GetValue(SamplesProperty); + set => SetValue(SamplesProperty, value); + } + + public static readonly StyledProperty LabelFontFamilyProperty = + AvaloniaProperty.Register(nameof(LabelFontFamily)); + + public FontFamily LabelFontFamily + { + get => GetValue(LabelFontFamilyProperty); + set => SetValue(LabelFontFamilyProperty, value); + } + + public static readonly StyledProperty SampleBrushProperty = + AvaloniaProperty.Register(nameof(SampleBrush), Brushes.SkyBlue); + + public IBrush SampleBrush + { + get => GetValue(SampleBrushProperty); + set => SetValue(SampleBrushProperty, value); + } + + public Chart() + { + ToolTip.SetPlacement(this, PlacementMode.Pointer); + ToolTip.SetShowDelay(this, 0); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + + var samples = Samples; + if (samples == null || samples.Count == 0) + return; + + var w = Bounds.Width; + var h = Bounds.Height; + context.FillRectangle(Brushes.Transparent, new Rect(0, 0, w, h)); + + var count = samples.Count; + var maxValue = samples.MaxValue; + var time = samples.EndTime; + var minTime = samples.StartTime; + var hasUserSamples = samples.HasSpecialUser; + + var labelPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), .5); + var labelTypeface = new Typeface(LabelFontFamily); + var corner = new CornerRadius(2, 2, 0, 0); + var sampleBrush = SampleBrush; + + var leftMargin = 0.0; + for (var i = 1; i <= 8; i++) + { + var percent = i * 0.125; + var value = Math.Floor(maxValue * (1.0 - percent)); + var y = Math.Floor((h - 24) * percent) + 0.5; + + var label = new FormattedText( + $"{value}", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + labelTypeface, + 11, + Brushes.Gray); + + if (leftMargin == 0) + leftMargin = label.Width + 24.0; + + context.DrawText(label, new Point(leftMargin - label.Width - 8.0, y - label.Height * 0.5)); + context.DrawLine(labelPen, new Point(leftMargin, y), new Point(w, y)); + } + + var step = Math.Max((w - leftMargin) / count, 10.0); + _maxOffsetX = Math.Max(count * step - (w - leftMargin), 0); + _hitBoxes.Clear(); + _lastHitted = new Rect(0, 0, 0, 0); + + var x = w + Math.Min(_maxOffsetX, _offsetX); + var sampleW = hasUserSamples ? Math.Min(step * 0.5 - 2.5, 14.0) : Math.Min(step - 3, 28.0); + var maxSampleH = h - 24.0; + var maxLabelEndX = w - 4.0; + + using var clip = context.PushClip(new Rect(leftMargin, 0, w - leftMargin, h)); + do + { + var (label, total, user) = samples.GetSample(time); + + if (x - step <= w && total > 0) + { + if (hasUserSamples) + { + var startX = x - step * 0.5 - 1 - sampleW; + var startY = maxSampleH * (1.0 - total * 1.0 / maxValue); + var rect = new Rect(startX, startY, sampleW, maxSampleH - startY); + + using (context.PushOpacity(0.2)) + { + context.DrawRectangle(sampleBrush, null, new RoundedRect(rect, corner)); + } + + if (user > 0) + { + var userStartX = startX + sampleW + 2; + var userStartY = maxSampleH * (1.0 - user * 1.0 / maxValue); + var userRect = new Rect(userStartX, userStartY, sampleW, maxSampleH - userStartY); + context.DrawRectangle(sampleBrush, null, new RoundedRect(userRect, corner)); + } + + var hitRect = new Rect(startX, startY, sampleW * 2 + 2, maxSampleH - startY); + _hitBoxes.Add(new(hitRect, new(label, true, total, user))); + } + else + { + var startX = x - step * 0.5 - sampleW * 0.5; + var startY = maxSampleH * (1.0 - total * 1.0 / maxValue); + var rect = new Rect(startX, startY, sampleW, maxSampleH - startY); + + context.DrawRectangle(sampleBrush, null, new RoundedRect(rect, corner)); + _hitBoxes.Add(new(rect, new(label, false, total, 0))); + } + } + + if (x <= w) + { + var formattedLabel = new FormattedText( + label, + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + labelTypeface, + 11, + Brushes.Gray); + + var labelCenterX = x - step * 0.5; + var labelEndX = labelCenterX + formattedLabel.Width * 0.5; + if (labelEndX <= maxLabelEndX) + { + var labelStartX = labelCenterX - formattedLabel.Width * 0.5; + var labelStartY = h - formattedLabel.Height - 2.0; + context.DrawText(formattedLabel, new Point(labelStartX, labelStartY)); + maxLabelEndX = labelStartX - 16.0; + } + } + + if (x <= leftMargin) + break; + + x -= step; + + time = samples.NextSampleTime(time); + if (time < minTime) + break; + } while (true); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == SamplesProperty) + { + _offsetX = 0; + InvalidateVisual(); + } + else if (change.Property == SampleBrushProperty) + { + InvalidateVisual(); + } + } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + + if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) + { + _isDraging = true; + _lastDragX = e.GetPosition(this).X; + e.Pointer.Capture(this); + } + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + + if (_isDraging) + { + var posX = e.GetPosition(this).X; + if (Math.Abs(posX - _lastDragX) < 0.5f) + return; + + var desired = Math.Max(0, Math.Min(_offsetX + posX - _lastDragX, _maxOffsetX)); + if (Math.Abs(desired - _offsetX) < 0.5f) + return; + + _offsetX = desired; + _lastDragX = posX; + _lastHitted = new Rect(0, 0, 0, 0); + InvalidateVisual(); + } + else + { + var p = e.GetPosition(this); + + if (!_lastHitted.Contains(p)) + { + foreach (var box in _hitBoxes) + { + if (box.Rect.Contains(p)) + { + ToolTip.SetTip(this, box.ToolTip); + _lastHitted = box.Rect; + return; + } + } + + _lastHitted = new Rect(0, 0, 0, 0); + ToolTip.SetTip(this, null); + } + } + } + + protected override void OnPointerReleased(PointerReleasedEventArgs e) + { + base.OnPointerReleased(e); + _isDraging = false; + e.Pointer.Capture(null); + } + + protected override void OnPointerWheelChanged(PointerWheelEventArgs e) + { + e.Handled = true; + + var deltaX = e.KeyModifiers == KeyModifiers.Shift ? e.Delta.Y : e.Delta.X; + var deltaOffset = Bounds.Width * deltaX * 0.5; + var desired = Math.Max(0, Math.Min(_offsetX + deltaOffset, _maxOffsetX)); + if (Math.Abs(desired - _offsetX) < 0.1) + return; + + _offsetX = desired; + _isDraging = false; + _lastHitted = new Rect(0, 0, 0, 0); + InvalidateVisual(); + } + + private record HitBox(Rect Rect, ChartToolTip ToolTip); + + private double _offsetX = 0; + private double _maxOffsetX = 0; + private bool _isDraging = false; + private double _lastDragX = 0; + private List _hitBoxes = []; + private Rect _lastHitted = new(0, 0, 0, 0); + } +} diff --git a/src/Views/ChromelessWindow.cs b/src/Views/ChromelessWindow.cs index b05785b1f..9d6d6150c 100644 --- a/src/Views/ChromelessWindow.cs +++ b/src/Views/ChromelessWindow.cs @@ -1,5 +1,5 @@ using System; -using Avalonia; + using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Input; @@ -8,15 +8,6 @@ namespace SourceGit.Views { public class ChromelessWindow : Window { - public static readonly StyledProperty LeftCaptionButtonWidthProperty = - AvaloniaProperty.Register(nameof(LeftCaptionButtonWidth), 72.0); - - public double LeftCaptionButtonWidth - { - get => GetValue(LeftCaptionButtonWidthProperty); - set => SetValue(LeftCaptionButtonWidthProperty, value); - } - public bool UseSystemWindowFrame { get => Native.OS.UseSystemWindowFrame; @@ -32,7 +23,6 @@ public bool CloseOnESC public ChromelessWindow() { - LeftCaptionButtonWidth = 72.0 / Math.Max(1.0, ViewModels.Preferences.Instance.Zoom); Focusable = true; Native.OS.SetupForWindow(this); } @@ -84,25 +74,6 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - - if (change.Property == WindowStateProperty && OperatingSystem.IsWindows()) - { - if (WindowState == WindowState.Maximized) - { - BorderThickness = new Thickness(0); - Padding = new Thickness(8, 6, 8, 8); - } - else - { - BorderThickness = new Thickness(1); - Padding = new Thickness(0); - } - } - } - protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); @@ -123,14 +94,12 @@ protected override void OnKeyDown(KeyEventArgs e) { var zoom = Math.Min(ViewModels.Preferences.Instance.Zoom + 0.05, 2.5); ViewModels.Preferences.Instance.Zoom = zoom; - LeftCaptionButtonWidth = 72.0 / zoom; e.Handled = true; } else if (e.Key == Key.OemMinus) { var zoom = Math.Max(ViewModels.Preferences.Instance.Zoom - 0.05, 1); ViewModels.Preferences.Instance.Zoom = zoom; - LeftCaptionButtonWidth = 72.0 / zoom; e.Handled = true; } } diff --git a/src/Views/Clone.axaml b/src/Views/Clone.axaml index a501474be..eb30dce5e 100644 --- a/src/Views/Clone.axaml +++ b/src/Views/Clone.axaml @@ -50,7 +50,7 @@ x:Name="TxtSshKey" Height="28" CornerRadius="3" - Watermark="{DynamicResource Text.SSHKey.Placeholder}" + PlaceholderText="{DynamicResource Text.SSHKey.Placeholder}" Text="{Binding SSHKey, Mode=TwoWay}" IsVisible="{Binding UseSSH}"> @@ -90,7 +90,7 @@ ((c, _) => c.UpdateColors()); - } - public override void Render(DrawingContext context) { base.Render(context); diff --git a/src/Views/CommandLogContentPresenter.cs b/src/Views/CommandLogContentPresenter.cs index 99dc6d13d..b7fff0145 100644 --- a/src/Views/CommandLogContentPresenter.cs +++ b/src/Views/CommandLogContentPresenter.cs @@ -149,6 +149,10 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang if (!string.IsNullOrEmpty(PureText)) Text = PureText; } + else if (change.Property.Name == nameof(ActualThemeVariant) && change.NewValue != null) + { + Models.TextMateHelper.SetThemeByApp(_textMate); + } } private TextMate.Installation _textMate = null; diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index 6b059c5b9..f36be3a5e 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -28,7 +28,9 @@ + Foreground="{DynamicResource Brush.FG2}" + Background="Transparent" + ContextRequested="OnDateTimeContextMenuRequested"/> @@ -46,7 +48,9 @@ + Foreground="{DynamicResource Brush.FG2}" + Background="Transparent" + ContextRequested="OnDateTimeContextMenuRequested"/> @@ -69,7 +73,7 @@ - - @@ -142,7 +142,7 @@ - + @@ -150,9 +150,10 @@ + ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}" + PropertyChanged="OnToggleButtonPropertyChanged"> @@ -172,20 +173,13 @@ - + - - - - + ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}" + PropertyChanged="OnToggleButtonPropertyChanged"> - + + + + + @@ -355,7 +361,7 @@ Height="28" CornerRadius="3" Text="{Binding #ThisControl.DefaultUser, Mode=TwoWay}" - Watermark="{DynamicResource Text.Preferences.Git.User.Placeholder}"/> + PlaceholderText="{DynamicResource Text.Preferences.Git.User.Placeholder}"/> + PlaceholderText="{DynamicResource Text.Preferences.Git.Email.Placeholder}"/>