Compare commits

...

128 commits

Author SHA1 Message Date
leo
190d2eec73
Merge branch 'release/v2025.23' 2025-06-23 09:59:54 +08:00
leo
bfb9d6b6bc
version: Release 2025.23
Signed-off-by: leo <longshuang@msn.cn>
2025-06-23 09:59:45 +08:00
leo
9d2f8b1555
fix: Conventional Commit Helper not working in Interactive Rebase (#1446)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-23 09:56:18 +08:00
github-actions[bot]
f59b34fe25 doc: Update translation status and sort locale files
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
2025-06-22 01:30:06 +00:00
Sina Hinderks
6e4f35c4e1
localization: update German translations (#1445) 2025-06-22 09:29:54 +08:00
github-actions[bot]
6ecdabc212 doc: Update translation status and sort locale files 2025-06-22 01:29:17 +00:00
AquariusStar
8b902bd5c9
localization: update russian translate (#1444) 2025-06-22 09:28:58 +08:00
github-actions[bot]
73eccdb495 doc: Update translation status and sort locale files
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Waiting to run
2025-06-21 04:03:36 +00:00
leo
9bfc315ace
feature: allow to push revision where local branch is ahead of its upstream (#1394) (#1441)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-21 11:58:56 +08:00
leo
64ffbb113f
fix: wrong localization key to compare remote branch with current
Signed-off-by: leo <longshuang@msn.cn>
2025-06-21 10:45:40 +08:00
leo
221e964df0
code_review: PR #1442
Trim both `\` (on Windows) and `/` (on Linux/macOS) characters at the end of path

Signed-off-by: leo <longshuang@msn.cn>
2025-06-21 10:42:19 +08:00
Ihor
20daa584e3
fix: fix working tree folder path detection error (#1442)
Fix the error of adding an extra slash when selecting a working tree directory.
2025-06-21 10:25:55 +08:00
leo
c5ad4b837d
feature: auto-follow HEAD when bisecting (#1438)
Some checks failed
Continuous Integration / Build (push) Has been cancelled
Continuous Integration / Prepare version string (push) Has been cancelled
Continuous Integration / Package (push) Has been cancelled
Signed-off-by: leo <longshuang@msn.cn>
2025-06-20 09:19:21 +08:00
leo
957c52aac4
fix: crash after remove worktree while it is opened in sourcegit (#1436)
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 17:58:02 +08:00
leo
8d74586970
ux: show only subject in Apply Stash and Drop Stash popup
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 14:26:31 +08:00
leo
dcd8effc32
fix: saving revision file may crash this app if target dir is not exists (#1434)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 11:39:53 +08:00
leo
af2b644792
code_review: PR #1416
- Split `DoubleTapped` into two methods: `CheckoutBranchByDecorator` and `CheckoutBranchByCommit`
- Move `DoubleTappedEvent` from whole ListBox to the row tapped actually
- Do nothing if the decorator double-clicked is HEAD
- Code-style

Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 11:31:04 +08:00
Nathan Baulch
88fd8f32f1
feature: double tap specific branch (#1416)
* feature: double tap specific branch
* exactly match behavior of left sidebar
2025-06-19 10:27:31 +08:00
leo
cadcf40d74
feature: support to open selected folder in file manager
Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 09:32:27 +08:00
github-actions[bot]
fcf1107304 doc: Update translation status and sort locale files
Some checks failed
Localization Check / localization-check (push) Has been cancelled
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
2025-06-19 01:13:09 +00:00
leo
e81674912c
refactor: remove duplicated context menu to ignore untracked files under folder
Signed-off-by: leo <longshuang@msn.cn>
2025-06-19 09:12:27 +08:00
leo
6729d4e896
feature: supports to ignore new files in folder from context menu of selected folder node in change tree (#1432)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 22:10:23 +08:00
leo
f9f44ae9cb
ux: show Name of stash instead of SHA in Apply Stash and Drop Stash popup
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 20:33:49 +08:00
leo
c67e8e3c64
enhance: create only one filesystem watcher when repo's $GIT_DIR is the same as $REPO_ROOT/.git
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 17:12:50 +08:00
leo
5ec8ae1296
ux: use CheckCircled instead of Check icon for stash apply context menu
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Waiting to run
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 14:37:14 +08:00
leo
2d91fed05e
code_style: remove unnecessary namespace using
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 14:30:46 +08:00
github-actions[bot]
3ac803d88c doc: Update translation status and sort locale files 2025-06-18 05:55:24 +00:00
leo
94d25ee6c9
code_review: PR #1430
- add missing Chinese translations
- add missing icons for stash context menu

Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 13:55:03 +08:00
github-actions[bot]
3711399c59 doc: Update translation status and sort locale files 2025-06-18 05:48:50 +00:00
Göran W
004022648c
Add "Copy Message" to context-menu for Stash item (#1430)
* Refactor: Simplify parsing in QueryStashes, by passing the `-z` argument to `git stash list` for item separation.
* Add "Copy Message" command in stash-item context-menu.
2025-06-18 13:48:39 +08:00
leo
240db2ea2f
ux: use small font size for tips
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 12:51:39 +08:00
github-actions[bot]
5ca1fcfd8f doc: Update translation status and sort locale files 2025-06-18 04:37:53 +00:00
leo
bad8904edc
code_style: make sure translations are ordered by key
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 12:37:39 +08:00
github-actions[bot]
86828b9711 doc: Update translation status and sort locale files 2025-06-18 04:33:05 +00:00
leo
6d682ac409
refactor: stash (#1420) (#1426)
- supports to use multi-line as stash message
- new style to display stashes

Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 12:32:50 +08:00
leo
b06a4cbb8a
code_style: remove whitespaces
Signed-off-by: leo <longshuang@msn.cn>
2025-06-18 09:32:39 +08:00
Nathan Baulch
d404f6dbe2
code_style: general cleanup (#1428) 2025-06-18 09:29:18 +08:00
github-actions[bot]
ae46728bbc doc: Update translation status and sort locale files
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Waiting to run
2025-06-17 12:56:18 +00:00
leo
957fbbf54f
refactor: rewrite stash local changes
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 20:56:02 +08:00
github-actions[bot]
10569022d7 doc: Update translation status and sort locale files
Some checks are pending
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Continuous Integration / Build (push) Waiting to run
Localization Check / localization-check (push) Waiting to run
2025-06-17 07:08:25 +00:00
leo
90310a704d
feature: supports to customize merge message (--edit) (#1421)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 15:07:55 +08:00
leo
a8da8c09ac
feature: add a button to open current revision file with default editor in FileHistories
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 14:44:12 +08:00
leo
df7375313e
enhance: clear last view revision file info after commit changed
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 14:12:00 +08:00
leo
efa6e46471
feature: add a button to open current revision file with default editor
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 12:20:02 +08:00
leo
e102e49f45
code_style: remove unnecessary properties
Signed-off-by: leo <longshuang@msn.cn>
2025-06-17 11:29:24 +08:00
leo
dcdc52592c
code_review: PR #1423
Some checks are pending
Continuous Integration / Package (push) Blocked by required conditions
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Localization Check / localization-check (push) Waiting to run
Since we have already used `OnPropertyChanged`, move `ActualThemeVariantProperty` changed handler into it

Signed-off-by: leo <longshuang@msn.cn>
2025-06-16 12:31:37 +08:00
Nathan Baulch
e28b537f89
enhance: darker ChangeStatusIcon when using dark theme (#1423) 2025-06-16 12:19:14 +08:00
leo
ed66d2337b
ux: show stash message as tooltip when hovering it (#1419)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-16 12:09:02 +08:00
leo
0cbf1215e0
Merge branch 'master' into develop 2025-06-16 09:19:19 +08:00
leo
74d77ab704
Merge branch 'release/v2025.22' 2025-06-16 09:18:41 +08:00
leo
b617181fc5
version: Release 2025.22
Signed-off-by: leo <longshuang@msn.cn>
2025-06-16 09:18:31 +08:00
github-actions[bot]
9dedcacb2f doc: Update translation status and sort locale files 2025-06-16 01:15:05 +00:00
Javier J. Martínez M.
b22733b565
localization: update spanish translations (#1422)
add missing translations
2025-06-16 09:14:52 +08:00
Göran W
28844c59cf
perf: optimize the WorkingCopy.IsChanged() method (#1418)
Some checks failed
Continuous Integration / Build (push) Has been cancelled
Continuous Integration / Prepare version string (push) Has been cancelled
Continuous Integration / Package (push) Has been cancelled
* There's no need to populate a Dictionary just to diff the the "old" and "cur" Lists of Changes.
* If the two lists are of equal length and no change has occurred, we can assume that they are also reported in equal sort-order (by git-status).
* Thus, we only need to compare the two items at each successive index.
2025-06-13 19:23:20 +08:00
leo
f88652ffdd
code_review: PR #1417
Remove unnecessary namespace using

Signed-off-by: leo <longshuang@msn.cn>
2025-06-13 17:12:14 +08:00
Göran W
8dffdef48d
refactor: reduce redundant code in NumericSort (#1417)
* Refactor the 2 do-loops into simpler while-loops and replace the use of "tmp1/2" char-arrays with calls to String.Substring().
* Rename the "loc1/2" variables to "subLen1/2", for clarity, since they represent the lengths of the two extracted Substrings.

These changes make the logic more compact and easier to follow.
2025-06-13 17:06:35 +08:00
leo
158d926189
ux: new style for submodule diff
Signed-off-by: leo <longshuang@msn.cn>
2025-06-13 16:19:04 +08:00
leo
99b7208a54
enhance: prevent to start bisect if it is already running
Signed-off-by: leo <longshuang@msn.cn>
2025-06-13 15:32:31 +08:00
leo
05757ebf40
feature: supports to view .tiff images
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-12 18:15:25 +08:00
leo
cb6d6a233f
feature: show change tooltip in INFORMATION page
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-12 11:42:58 +08:00
leo
79650d1851
feature: supports to view .gif file as static image (not animated)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-12 11:32:24 +08:00
leo
7e2f3bec8c
enhance: clear commit message before merging/cherry-picking/rebasing/reverting to allow SourceGit read it from git (#1414)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-12 10:39:52 +08:00
leo
7de5991ecb
code_review: PR #1415
- Column for hotkey in `Reset` popup should use `Auto` for width
- Add `SelectionBoxItemTemplate` for current selected mode in `Reset` popup

Signed-off-by: leo <longshuang@msn.cn>
2025-06-12 09:54:53 +08:00
Nathan Baulch
ffac71b15f
code_style: general cleanup (#1415)
* code_style:  general cleanup

* code_style: whitespace cleanup
2025-06-12 09:35:37 +08:00
leo
35eda489be
feature: show local branch's track status in CheckoutAndFastForward popup
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 21:14:06 +08:00
leo
f59851f454
refactor: case-insensitive sorting
- `ToUpper` is not necessary to compare digit char with non-digit char
- use numeric sorting for commit decorators with same type

Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 20:25:41 +08:00
leo
a128b67bd4
code_review: PR #1412
- Use `ViewModels.StashesPage.SelectedStash` instead of `sender is not ListBox { SelectedValue: Models.Stash stash }`
- In tags view, `SelectedItem` can be `Models.Tag` or `ViewModels.TagTreeNode`
- In logs window, `vm.SelectedLog` may be null

Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 16:13:47 +08:00
Nathan Baulch
196b454ae8
feature: support delete key everywhere (#1412) 2025-06-11 15:35:43 +08:00
leo
5494093261
refactor: now all filesystem related trees/lists are sorted in case-insensitive mode
Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 15:20:50 +08:00
leo
c3c7d32167
refactor: do not change original image aspect ratio and do not up-scale image in BLEND image-diff mode
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 10:25:24 +08:00
leo
7c1a894525
refactor: do not change original image aspect ratio and do not upscale image in SWIPE mode
Signed-off-by: leo <longshuang@msn.cn>
2025-06-11 10:12:03 +08:00
leo
bcefb773c1
code_style: remove comment
Some checks failed
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
Signed-off-by: leo <longshuang@msn.cn>
2025-06-10 17:19:37 +08:00
leo
aa1c8b1cc1
code_style: use combined expr
Signed-off-by: leo <longshuang@msn.cn>
2025-06-10 17:09:57 +08:00
github-actions[bot]
5e303d43d4 doc: Update translation status and sort locale files 2025-06-10 09:04:35 +00:00
leo
7d0536d94b
feature: when trying to checkout a local branch from its tracking upstream and it is behind the upstream, show Checkout & Fast-Forward popup
Signed-off-by: leo <longshuang@msn.cn>
2025-06-10 17:04:06 +08:00
Nathan Baulch
6c04f5390a
feature: double tap commit with tracked remote branch checks out local tracking branch (#1409) 2025-06-10 15:58:57 +08:00
leo
ee4d8a6a0e
code_review: PR #1408
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-10 11:18:20 +08:00
johanw1232
0ea4021a64
feature: update blame data when clicking/navigating commits (#1408)
* initial work on allowing navigation by clicking on commits in the blame window
* cleanup
2025-06-10 09:30:12 +08:00
leo
11a46dbc93
update: built-in github and unreal icons
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-09 17:35:20 +08:00
leo
69792b3262
refactor: do not upscale images
Signed-off-by: leo <longshuang@msn.cn>
2025-06-09 17:22:31 +08:00
leo
1b1dc2f666
code_style: remove unnecessary code
Signed-off-by: leo <longshuang@msn.cn>
2025-06-09 15:42:02 +08:00
leo
4302d7adb5
Merge branch 'master' into develop
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
2025-06-09 09:31:46 +08:00
leo
932baeec53
Merge branch 'release/v2025.21' 2025-06-09 09:30:45 +08:00
leo
637e133f47
version: Release 2025.21
Signed-off-by: leo <longshuang@msn.cn>
2025-06-09 09:30:36 +08:00
github-actions[bot]
a1e76e9bea doc: Update translation status and sort locale files 2025-06-09 01:27:28 +00:00
AquariusStar
a8541a780e
localization: update translate Russian (#1404) 2025-06-09 09:27:10 +08:00
Sina Hinderks
d55f19586f
fix: issue tracker rule over keyword in subject (#1403)
Some teams use issue tracker numbers in front of the commit message
subject, followed by a colon.  It was not possible to use an issue
tracker rule in such cases, since the issue tracker number would be
interpreted as a keyword due to the colon and therefore displayed in
bold face instead of as a link into the issue tracker.
2025-06-09 09:26:27 +08:00
leo
a22c39519f
code_style: remove unnecessary code
Some checks failed
Continuous Integration / Build (push) Has been cancelled
Continuous Integration / Prepare version string (push) Has been cancelled
Continuous Integration / Package (push) Has been cancelled
Signed-off-by: leo <longshuang@msn.cn>
2025-06-08 11:54:54 +08:00
leo
84fb39f97a
code_review: PR #1402
- it's unnecessary to implement `IEnumerable` interface
- we should check `IsIntersecting` before creating `InlineElement` to avoid unnecessary works suck as running `git cat-file -t <hash>`
- sort whold list after all elements have been added to avoid unnecessary memmove in `Insert`

Signed-off-by: leo <longshuang@msn.cn>
2025-06-08 11:09:20 +08:00
Sina Hinderks
fe54d30b70
refactor: collecting inlines for subjects (#1402)
Instead of checking intersections of inline elements yourself before adding an inline element, the new class `InlineElementCollector` prevents intersections internally.

Additionally the inline elements are sorted by the new class, so it's no longer necessary to do this after adding the inline elements.
2025-06-08 08:47:03 +08:00
leo
ba4c0f0cd2
enhance: scroll to home when active revision file changed
Some checks are pending
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Continuous Integration / Build (push) Waiting to run
Signed-off-by: leo <longshuang@msn.cn>
2025-06-07 20:53:34 +08:00
leo
2478d2953b
code_style: remove unnecessary code in DiffContext
Signed-off-by: leo <longshuang@msn.cn>
2025-06-07 20:42:45 +08:00
leo
74f52fb266
enhance: only show syntax-highlighting toggle if current revision content is a text file
Signed-off-by: leo <longshuang@msn.cn>
2025-06-07 20:27:52 +08:00
leo
f830b68f6a
ux: change foreground for some labels
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-07 12:20:09 +08:00
leo
d323a2064e
feature: supports RGBA16 pixel format
Signed-off-by: leo <longshuang@msn.cn>
2025-06-07 12:00:16 +08:00
leo
203c50350e
fix: wrong pfim image format
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 20:50:37 +08:00
leo
47012e29dc
fix: file extensions are case-insensitive
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 18:47:36 +08:00
leo
8db033be99
code_review: PR #1392
- fix the issue that not all channel takes 8 bits
- if `PixelFormatTranscoder.Transcode` supports the same pixel formats, let it converts pixels automatically

Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 18:23:10 +08:00
Henrik Andersson
a2ca071f08
feature: .dds image support (#1392)
* Added Pfim as 3rdparty lib

* Added support for parsing showing dds and tga images using Pfim

---------

Co-authored-by: Snimax <snimax@live.se>
2025-06-06 16:44:40 +08:00
Nathan Baulch
7bba40d03f
typos: (#1397) 2025-06-06 12:10:55 +08:00
leo
0c22409b7b
ux: new sort by time icon (#1393)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 11:37:56 +08:00
leo
f63fe8637b
feature: use different icon for sort mode (#1393)
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Waiting to run
Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 11:22:30 +08:00
github-actions[bot]
08665e45c1 doc: Update translation status and sort locale files 2025-06-06 02:45:35 +00:00
leo
3bb20868fc
refactor: remove unnecessary sort by name (descending) for tags (#1393)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 10:45:18 +08:00
leo
ac55bed812
enhance: revision file viewer
- show current file path
- add a toggle button to use global syntax highlighting setting (sometimes TextMateSharp will crash this app)

Signed-off-by: leo <longshuang@msn.cn>
2025-06-06 10:07:58 +08:00
leo
f003f67129
fix: should use file.SHA instead of _commit.SHA to query submodule's commit
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 21:54:09 +08:00
Göran W
f04b0c5d97
fix: prevent exception on repo with no commits/branches
Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 21:28:32 +08:00
Göran W
406ace9e79
enhance: activate TabsDropdownItem on Tapped instead of DoubleTapped
Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 21:28:10 +08:00
leo
464fe74580
code_review: commit b969ac161a
- The return code of `AutoRemoveInvalidNode`  is never used
- It's not necessary to sort all nodes after re-scan default clone dir. Because `FindOrAddNodeByRepositoryPath` makes sure added node is ordered
- Add a new parameter `save` to `FindOrAddNodeByRepositoryPath` method, and disable it while scanning. Instead, we will save it after scan finished.

Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 21:27:19 +08:00
Göran W
b969ac161a
enhance: unify sorting of RepositoryNode tree, unconditional sort & save after rescan 2025-06-05 21:19:25 +08:00
Göran W
88c38b4139
enhance: unified all file-path normalization - use char-replace, trim trailing slash 2025-06-05 21:17:18 +08:00
Göran W
54c05ac35a
fix: remove trailing slash in paths, to avoid failing comparisons.
This is needed since DirectoryInfo.Fullname (and .FullPath) will not "normalize" trailing slashes, so direct equality tests are error-prone.
This fixes a bug in ScanRepositories.GetUnmanagedRepositories(), where not all Git repo folders were added.
(Also, corrected a variable name from 'founded' to 'found'.)
2025-06-05 21:15:28 +08:00
Göran W
75c32c1a01
typo: corrected spelling error in App.GetLauncher() method 2025-06-05 21:15:28 +08:00
leo
a023a9259b
refactor: rewrite lfs pointer detection and image loading
Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 21:06:31 +08:00
leo
eebadd67a1
feature: remember the last active tab index in lfs-image diff view
Some checks are pending
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Continuous Integration / Build (push) Waiting to run
Signed-off-by: leo <longshuang@msn.cn>
2025-06-05 09:18:19 +08:00
leo
f716c5ee1e
refactor: use existing QueryFileContent command
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-04 21:30:08 +08:00
leo
ed496a41fb
feature: supports to view image diff when lfs object points to a image
Signed-off-by: leo <longshuang@msn.cn>
2025-06-04 20:53:42 +08:00
leo
06a77502bc
fix: crash when clicking Previous Difference without visual lines (#1385)
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Always scroll to top when the state of `Show All Lines` changed

Signed-off-by: leo <longshuang@msn.cn>
2025-06-04 13:13:28 +08:00
leo
c2187edbe9
fix: running git command in UIThread via context menu entry blocks whole app (#1384)
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 23:36:15 +08:00
github-actions[bot]
d85f82e171 doc: Update translation status and sort locale files 2025-06-03 13:38:04 +00:00
leo
f7c10d0b33
feature: supports to load avatar from local image and save it to disk
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 21:37:47 +08:00
leo
25e272fa55
ux: layout of filter mode toggle buttons
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 20:28:44 +08:00
leo
98041c803e
feature: supports re-order custom actions (#1346)
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 20:24:30 +08:00
leo
ee2e7d0127
enhance: ignores $ char when measuring contents in NamedHighlightedTextBlock
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 14:12:23 +08:00
leo
6517e78ab6
enhance: enable StaysOpenOnClick for filter mode in graph context menu item
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 14:06:53 +08:00
leo
bf43dd828a
ux: new style for ref's Visibility in Graph context menu item
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 12:34:49 +08:00
leo
cd009bda6b
ux: enable Use monospace font only in text editor by default
Signed-off-by: leo <longshuang@msn.cn>
2025-06-03 10:15:58 +08:00
leo
cd8ff2e9bf
Merge branch 'master' into develop
Some checks are pending
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
2025-06-03 09:27:51 +08:00
207 changed files with 3497 additions and 1827 deletions

View file

@ -71,20 +71,20 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase # name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# private static fields should have s_ prefix # private static fields should have s_ prefix
dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style
dotnet_naming_symbols.private_static_fields.applicable_kinds = field dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.required_modifiers = static dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
@ -93,14 +93,14 @@ dotnet_naming_style.private_static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase # internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _ dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers # use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion

View file

@ -56,7 +56,7 @@ You can find the current translation status in [TRANSLATION.md](https://github.c
**To use this tool, you need to install Git(>=2.25.1) first.** **To use this tool, you need to install Git(>=2.25.1) first.**
You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [Github Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits. You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [GitHub Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs. This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs.
@ -93,7 +93,7 @@ For **macOS** users:
brew tap ybeapps/homebrew-sourcegit brew tap ybeapps/homebrew-sourcegit
brew install --cask --no-quarantine sourcegit brew install --cask --no-quarantine sourcegit
``` ```
* If you want to install `SourceGit.app` from Github Release manually, you need run following command to make sure it works: * If you want to install `SourceGit.app` from GitHub Release manually, you need run following command to make sure it works:
```shell ```shell
sudo xattr -cr /Applications/SourceGit.app sudo xattr -cr /Applications/SourceGit.app
``` ```

View file

@ -6,49 +6,29 @@ 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) ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)
### ![de__DE](https://img.shields.io/badge/de__DE-96.50%25-yellow) ### ![de__DE](https://img.shields.io/badge/de__DE-%E2%88%9A-brightgreen)
### ![es__ES](https://img.shields.io/badge/es__ES-99.13%25-yellow)
<details> <details>
<summary>Missing keys in de_DE.axaml</summary> <summary>Missing keys in es_ES.axaml</summary>
- Text.BranchCM.ResetToSelectedCommit - Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.Merge.Edit
- Text.CreateBranch.OverwriteExisting - Text.Push.Revision
- Text.DeinitSubmodule - Text.Push.Revision.Title
- Text.DeinitSubmodule.Force - Text.Stash.Mode
- Text.DeinitSubmodule.Path - Text.StashCM.CopyMessage
- Text.Diff.Submodule.Deleted - Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.SwitchWorkspace
- Text.Hotkeys.Global.SwitchTab
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Pull.RecurseSubmodules
- Text.Repository.ClearStashes
- Text.Repository.ShowSubmodulesAsTree
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
- Text.Submodule.URL
- Text.WorkingCopy.ResetAuthor
</details> </details>
### ![es__ES](https://img.shields.io/badge/es__ES-%E2%88%9A-brightgreen) ### ![fr__FR](https://img.shields.io/badge/fr__FR-91.19%25-yellow)
### ![fr__FR](https://img.shields.io/badge/fr__FR-92.38%25-yellow)
<details> <details>
<summary>Missing keys in fr_FR.axaml</summary> <summary>Missing keys in fr_FR.axaml</summary>
- Text.Avatar.Load
- Text.Bisect - Text.Bisect
- Text.Bisect.Abort - Text.Bisect.Abort
- Text.Bisect.Bad - Text.Bisect.Bad
@ -58,9 +38,12 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules - Text.Checkout.RecurseSubmodules
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount - Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode - Text.Configure.Git.PreferredMergeMode
@ -80,8 +63,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool - Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.BranchSort - Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate - Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName - Text.Repository.BranchSort.ByName
@ -93,6 +79,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout - Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo - Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target - Text.ResetWithoutCheckout.Target
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.Submodule.Status - Text.Submodule.Status
- Text.Submodule.Status.Modified - Text.Submodule.Status.Modified
@ -104,6 +92,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete - Text.ViewLogs.Delete
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ConfirmCommitWithFilter - Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool - Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts - Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
@ -113,12 +102,16 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![it__IT](https://img.shields.io/badge/it__IT-97.75%25-yellow) ### ![it__IT](https://img.shields.io/badge/it__IT-96.53%25-yellow)
<details> <details>
<summary>Missing keys in it_IT.axaml</summary> <summary>Missing keys in it_IT.axaml</summary>
- Text.Avatar.Load
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CreateBranch.OverwriteExisting - Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule - Text.DeinitSubmodule
@ -129,21 +122,28 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.Global.SwitchTab - Text.Hotkeys.Global.SwitchTab
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.ClearStashes - Text.Repository.ClearStashes
- Text.ResetWithoutCheckout - Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo - Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target - Text.ResetWithoutCheckout.Target
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ResetAuthor - Text.WorkingCopy.ResetAuthor
</details> </details>
### ![ja__JP](https://img.shields.io/badge/ja__JP-92.01%25-yellow) ### ![ja__JP](https://img.shields.io/badge/ja__JP-90.94%25-yellow)
<details> <details>
<summary>Missing keys in ja_JP.axaml</summary> <summary>Missing keys in ja_JP.axaml</summary>
- Text.Avatar.Load
- Text.Bisect - Text.Bisect
- Text.Bisect.Abort - Text.Bisect.Abort
- Text.Bisect.Bad - Text.Bisect.Bad
@ -154,9 +154,12 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CompareWithCurrent - Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules - Text.Checkout.RecurseSubmodules
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount - Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode - Text.Configure.Git.PreferredMergeMode
@ -176,8 +179,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool - Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.BranchSort - Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate - Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName - Text.Repository.BranchSort.ByName
@ -185,12 +191,13 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree - Text.Repository.ShowSubmodulesAsTree
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit - Text.Repository.Visit
- Text.ResetWithoutCheckout - Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo - Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target - Text.ResetWithoutCheckout.Target
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.Submodule.Status - Text.Submodule.Status
- Text.Submodule.Status.Modified - Text.Submodule.Status.Modified
@ -202,6 +209,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete - Text.ViewLogs.Delete
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ConfirmCommitWithFilter - Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool - Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts - Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
@ -211,7 +219,7 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![pt__BR](https://img.shields.io/badge/pt__BR-84.02%25-yellow) ### ![pt__BR](https://img.shields.io/badge/pt__BR-83.25%25-yellow)
<details> <details>
<summary>Missing keys in pt_BR.axaml</summary> <summary>Missing keys in pt_BR.axaml</summary>
@ -222,6 +230,7 @@ This document shows the translation status of each locale file in the repository
- Text.ApplyStash.DropAfterApply - Text.ApplyStash.DropAfterApply
- Text.ApplyStash.RestoreIndex - Text.ApplyStash.RestoreIndex
- Text.ApplyStash.Stash - Text.ApplyStash.Stash
- Text.Avatar.Load
- Text.Bisect - Text.Bisect
- Text.Bisect.Abort - Text.Bisect.Abort
- Text.Bisect.Bad - Text.Bisect.Bad
@ -234,12 +243,15 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.BranchUpstreamInvalid - Text.BranchUpstreamInvalid
- Text.Checkout.RecurseSubmodules - Text.Checkout.RecurseSubmodules
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.Clone.RecurseSubmodules - Text.Clone.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitCM.Merge - Text.CommitCM.Merge
- Text.CommitCM.MergeMultiple - Text.CommitCM.MergeMultiple
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CommitDetail.Files.Search - Text.CommitDetail.Files.Search
- Text.CommitDetail.Info.Children - Text.CommitDetail.Info.Children
@ -280,6 +292,7 @@ This document shows the translation status of each locale file in the repository
- Text.InProgress.Revert.Head - Text.InProgress.Revert.Head
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Merge.Source - Text.Merge.Source
- Text.MergeMultiple - Text.MergeMultiple
- Text.MergeMultiple.CommitChanges - Text.MergeMultiple.CommitChanges
@ -293,6 +306,8 @@ This document shows the translation status of each locale file in the repository
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Preferences.Git.SSLVerify - Text.Preferences.Git.SSLVerify
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.BranchSort - Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate - Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName - Text.Repository.BranchSort.ByName
@ -308,8 +323,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree - Text.Repository.ShowSubmodulesAsTree
- Text.Repository.Skip - Text.Repository.Skip
- Text.Repository.Tags.OrderByCreatorDate - Text.Repository.Tags.OrderByCreatorDate
- Text.Repository.Tags.OrderByNameAsc - Text.Repository.Tags.OrderByName
- Text.Repository.Tags.OrderByNameDes
- Text.Repository.Tags.Sort - Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories - Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
@ -322,8 +336,8 @@ This document shows the translation status of each locale file in the repository
- Text.SetUpstream.Unset - Text.SetUpstream.Unset
- Text.SetUpstream.Upstream - Text.SetUpstream.Upstream
- Text.SHALinkCM.NavigateTo - Text.SHALinkCM.NavigateTo
- Text.Stash.AutoRestore - Text.Stash.Mode
- Text.Stash.AutoRestore.Tip - Text.StashCM.CopyMessage
- Text.StashCM.SaveAsPatch - Text.StashCM.SaveAsPatch
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.Submodule.Status - Text.Submodule.Status
@ -336,6 +350,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete - Text.ViewLogs.Delete
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.CommitToEdit - Text.WorkingCopy.CommitToEdit
- Text.WorkingCopy.ConfirmCommitWithFilter - Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool - Text.WorkingCopy.Conflicts.OpenExternalMergeTool
@ -347,22 +362,14 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![ru__RU](https://img.shields.io/badge/ru__RU-99.63%25-yellow) ### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen)
<details> ### ![ta__IN](https://img.shields.io/badge/ta__IN-91.07%25-yellow)
<summary>Missing keys in ru_RU.axaml</summary>
- Text.BranchCM.CompareWithCurrent
- Text.Repository.ClearStashes
- Text.WorkingCopy.ResetAuthor
</details>
### ![ta__IN](https://img.shields.io/badge/ta__IN-92.26%25-yellow)
<details> <details>
<summary>Missing keys in ta_IN.axaml</summary> <summary>Missing keys in ta_IN.axaml</summary>
- Text.Avatar.Load
- Text.Bisect - Text.Bisect
- Text.Bisect.Abort - Text.Bisect.Abort
- Text.Bisect.Bad - Text.Bisect.Bad
@ -373,9 +380,12 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CompareWithCurrent - Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules - Text.Checkout.RecurseSubmodules
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount - Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode - Text.Configure.Git.PreferredMergeMode
@ -395,8 +405,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool - Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.BranchSort - Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate - Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName - Text.Repository.BranchSort.ByName
@ -408,6 +421,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout - Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo - Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target - Text.ResetWithoutCheckout.Target
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.Submodule.Status - Text.Submodule.Status
- Text.Submodule.Status.Modified - Text.Submodule.Status.Modified
@ -420,6 +435,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete - Text.ViewLogs.Delete
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool - Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts - Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine - Text.WorkingCopy.Conflicts.UseMine
@ -428,11 +444,12 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![uk__UA](https://img.shields.io/badge/uk__UA-93.51%25-yellow) ### ![uk__UA](https://img.shields.io/badge/uk__UA-92.31%25-yellow)
<details> <details>
<summary>Missing keys in uk_UA.axaml</summary> <summary>Missing keys in uk_UA.axaml</summary>
- Text.Avatar.Load
- Text.Bisect - Text.Bisect
- Text.Bisect.Abort - Text.Bisect.Abort
- Text.Bisect.Bad - Text.Bisect.Bad
@ -442,9 +459,12 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit - Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules - Text.Checkout.RecurseSubmodules
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count - Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount - Text.CommitMessageTextBox.SubjectCount
- Text.ConfigureWorkspace.Name - Text.ConfigureWorkspace.Name
@ -460,8 +480,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool - Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces - Text.Launcher.Workspaces
- Text.Launcher.Pages - Text.Launcher.Pages
- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules - Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
- Text.Repository.BranchSort - Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate - Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName - Text.Repository.BranchSort.ByName
@ -473,6 +496,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout - Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo - Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target - Text.ResetWithoutCheckout.Target
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.Submodule.Deinit - Text.Submodule.Deinit
- Text.Submodule.Status - Text.Submodule.Status
- Text.Submodule.Status.Modified - Text.Submodule.Status.Modified
@ -484,6 +509,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete - Text.ViewLogs.Delete
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ResetAuthor - Text.WorkingCopy.ResetAuthor
</details> </details>

View file

@ -1 +1 @@
2025.20 2025.23

View file

@ -12,4 +12,4 @@
dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj
``` ```
> [!NOTE] > [!NOTE]
> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replece the `$DESTINATION_FOLDER` with the real path that will store the output executable files. > Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replace the `$DESTINATION_FOLDER` with the real path that will store the output executable files.

View file

@ -301,7 +301,7 @@ namespace SourceGit
return await clipboard.GetTextAsync(); return await clipboard.GetTextAsync();
} }
} }
return default; return null;
} }
public static string Text(string key, params object[] args) public static string Text(string key, params object[] args)
@ -323,8 +323,7 @@ namespace SourceGit
icon.Height = 12; icon.Height = 12;
icon.Stretch = Stretch.Uniform; icon.Stretch = Stretch.Uniform;
var geo = Current?.FindResource(key) as StreamGeometry; if (Current?.FindResource(key) is StreamGeometry geo)
if (geo != null)
icon.Data = geo; icon.Data = geo;
return icon; return icon;
@ -338,7 +337,7 @@ namespace SourceGit
return null; return null;
} }
public static ViewModels.Launcher GetLauncer() public static ViewModels.Launcher GetLauncher()
{ {
return Current is App app ? app._launcher : null; return Current is App app ? app._launcher : null;
} }
@ -522,7 +521,7 @@ namespace SourceGit
private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop) private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop)
{ {
var args = desktop.Args; var args = desktop.Args;
if (args == null || args.Length <= 1 || !args[0].Equals("--core-editor", StringComparison.Ordinal)) if (args is not { Length: > 1 } || !args[0].Equals("--core-editor", StringComparison.Ordinal))
return false; return false;
var file = args[1]; var file = args[1];
@ -532,8 +531,8 @@ namespace SourceGit
return true; return true;
} }
var editor = new Views.StandaloneCommitMessageEditor(); var editor = new Views.CommitMessageEditor();
editor.SetFile(file); editor.AsStandalone(file);
desktop.MainWindow = editor; desktop.MainWindow = editor;
return true; return true;
} }
@ -682,8 +681,7 @@ namespace SourceGit
} }
var name = sb.ToString(); var name = sb.ToString();
var idx = name.IndexOf('#'); if (name.Contains('#', StringComparison.Ordinal))
if (idx >= 0)
{ {
if (!name.Equals("fonts:Inter#Inter", StringComparison.Ordinal) && if (!name.Equals("fonts:Inter#Inter", StringComparison.Ordinal) &&
!name.Equals("fonts:SourceGit#JetBrains Mono", StringComparison.Ordinal)) !name.Equals("fonts:SourceGit#JetBrains Mono", StringComparison.Ordinal))

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only. <!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls. Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="SourceGit.Desktop"/> <assemblyIdentity version="1.0.0.0" name="SourceGit.Desktop"/>

View file

@ -51,7 +51,7 @@ namespace SourceGit.Commands
private void ParseLine(string line) private void ParseLine(string line)
{ {
if (line.IndexOf('\0', StringComparison.Ordinal) >= 0) if (line.Contains('\0', StringComparison.Ordinal))
{ {
_result.IsBinary = true; _result.IsBinary = true;
_result.LineInfos.Clear(); _result.LineInfos.Clear();
@ -89,7 +89,7 @@ namespace SourceGit.Commands
private readonly Models.BlameData _result = new Models.BlameData(); private readonly Models.BlameData _result = new Models.BlameData();
private readonly StringBuilder _content = new StringBuilder(); private readonly StringBuilder _content = new StringBuilder();
private readonly string _dateFormat = Models.DateTimeFormat.Actived.DateOnly; private readonly string _dateFormat = Models.DateTimeFormat.Active.DateOnly;
private string _lastSHA = string.Empty; private string _lastSHA = string.Empty;
private bool _needUnifyCommitSHA = false; private bool _needUnifyCommitSHA = false;
private int _minSHALen = 64; private int _minSHALen = 64;

View file

@ -194,7 +194,7 @@ namespace SourceGit.Commands
private void HandleOutput(string line, List<string> errs) private void HandleOutput(string line, List<string> errs)
{ {
line = line ?? string.Empty; line ??= string.Empty;
Log?.AppendLine(line); Log?.AppendLine(line);
// Lines to hide in error message. // Lines to hide in error message.

View file

@ -34,6 +34,6 @@ namespace SourceGit.Commands
return succ; return succ;
} }
private string _tmpFile = string.Empty; private readonly string _tmpFile;
} }
} }

View file

@ -39,7 +39,7 @@ namespace SourceGit.Commands
foreach (var line in lines) foreach (var line in lines)
ParseLine(line); ParseLine(line);
_changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal)); _changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
return _changes; return _changes;
} }

View file

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

View file

@ -5,11 +5,20 @@ namespace SourceGit.Commands
{ {
public class Merge : Command public class Merge : Command
{ {
public Merge(string repo, string source, string mode) public Merge(string repo, string source, string mode, bool edit)
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"merge --progress {source} {mode}"; Editor = EditorType.CoreEditor;
var builder = new StringBuilder();
builder.Append("merge --progress ");
builder.Append(edit ? "--edit " : "--no-edit ");
builder.Append(source);
builder.Append(' ');
builder.Append(mode);
Args = builder.ToString();
} }
public Merge(string repo, List<string> targets, bool autoCommit, string strategy) public Merge(string repo, List<string> targets, bool autoCommit, string strategy)

View file

@ -24,7 +24,7 @@ namespace SourceGit.Commands
if (!File.Exists(toolPath)) if (!File.Exists(toolPath))
{ {
Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT found external merge tool in '{toolPath}'!")); Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!"));
return false; return false;
} }
@ -54,7 +54,7 @@ namespace SourceGit.Commands
if (!File.Exists(toolPath)) if (!File.Exists(toolPath))
{ {
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT found external diff tool in '{toolPath}'!")); Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!"));
return false; return false;
} }

View file

@ -48,16 +48,12 @@ namespace SourceGit.Commands
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead)) if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
{ {
b.IsUpstreamGone = false; b.IsUpstreamGone = false;
b.TrackStatus ??= new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
if (b.TrackStatus == null)
b.TrackStatus = new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
} }
else else
{ {
b.IsUpstreamGone = true; b.IsUpstreamGone = true;
b.TrackStatus ??= new Models.BranchTrackStatus();
if (b.TrackStatus == null)
b.TrackStatus = new Models.BranchTrackStatus();
} }
} }
} }

View file

@ -90,6 +90,6 @@ namespace SourceGit.Commands
private List<Models.InteractiveCommit> _commits = []; private List<Models.InteractiveCommit> _commits = [];
private Models.InteractiveCommit _current = null; private Models.InteractiveCommit _current = null;
private string _boundary = ""; private readonly string _boundary;
} }
} }

View file

@ -35,5 +35,39 @@ namespace SourceGit.Commands
return stream; return stream;
} }
public static Stream FromLFS(string repo, string oid, long size)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
starter.FileName = Native.OS.GitExecutable;
starter.Arguments = $"lfs smudge";
starter.UseShellExecute = false;
starter.CreateNoWindow = true;
starter.WindowStyle = ProcessWindowStyle.Hidden;
starter.RedirectStandardInput = true;
starter.RedirectStandardOutput = true;
var stream = new MemoryStream();
try
{
var proc = new Process() { StartInfo = starter };
proc.Start();
proc.StandardInput.WriteLine("version https://git-lfs.github.com/spec/v1");
proc.StandardInput.WriteLine($"oid sha256:{oid}");
proc.StandardInput.WriteLine($"size {size}");
proc.StandardOutput.BaseStream.CopyTo(stream);
proc.WaitForExit();
proc.Close();
stream.Position = 0;
}
catch (Exception e)
{
App.RaiseException(repo, $"Failed to query file content: {e}");
}
return stream;
}
} }
} }

View file

@ -16,9 +16,6 @@ namespace SourceGit.Commands
public long Result() public long Result()
{ {
if (_result != 0)
return _result;
var rs = ReadToEnd(); var rs = ReadToEnd();
if (rs.IsSuccess) if (rs.IsSuccess)
{ {
@ -29,7 +26,5 @@ namespace SourceGit.Commands
return 0; return 0;
} }
private readonly long _result = 0;
} }
} }

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "stash list --format=%H%n%P%n%ct%n%gd%n%s"; Args = $"stash list -z --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B\"";
} }
public List<Models.Stash> Result() public List<Models.Stash> Result()
@ -19,55 +19,50 @@ namespace SourceGit.Commands
if (!rs.IsSuccess) if (!rs.IsSuccess)
return outs; return outs;
var nextPartIdx = 0; var items = rs.StdOut.Split('\0', StringSplitOptions.RemoveEmptyEntries);
var start = 0; foreach (var item in items)
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)
{ {
var line = rs.StdOut.Substring(start, end - start); var current = new Models.Stash();
switch (nextPartIdx) var nextPartIdx = 0;
var start = 0;
var end = item.IndexOf('\n', start);
while (end > 0 && nextPartIdx < 4)
{ {
case 0: var line = item.Substring(start, end - start);
_current = new Models.Stash() { SHA = line };
outs.Add(_current); switch (nextPartIdx)
break; {
case 1: case 0:
ParseParent(line); current.SHA = line;
break; break;
case 2: case 1:
_current.Time = ulong.Parse(line); if (line.Length > 6)
break; current.Parents.AddRange(line.Split(' ', StringSplitOptions.RemoveEmptyEntries));
case 3: break;
_current.Name = line; case 2:
break; current.Time = ulong.Parse(line);
case 4: break;
_current.Message = line; case 3:
current.Name = line;
break;
}
nextPartIdx++;
start = end + 1;
if (start >= item.Length - 1)
break; break;
end = item.IndexOf('\n', start);
} }
nextPartIdx++; if (start < item.Length)
if (nextPartIdx > 4) current.Message = item.Substring(start);
nextPartIdx = 0;
start = end + 1; outs.Add(current);
end = rs.StdOut.IndexOf('\n', start);
} }
if (start < rs.StdOut.Length)
_current.Message = rs.StdOut.Substring(start);
return outs; return outs;
} }
private void ParseParent(string data)
{
if (data.Length < 8)
return;
_current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
}
private Models.Stash _current = null;
} }
} }

View file

@ -24,7 +24,7 @@ namespace SourceGit.Commands
var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries); var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries);
foreach (var record in records) foreach (var record in records)
{ {
var subs = record.Split('\0', StringSplitOptions.None); var subs = record.Split('\0');
if (subs.Length != 6) if (subs.Length != 6)
continue; continue;

View file

@ -10,15 +10,15 @@ namespace SourceGit.Commands
{ {
public static void Run(string repo, string revision, string file, string saveTo) public static void Run(string repo, string revision, string file, string saveTo)
{ {
var dir = Path.GetDirectoryName(saveTo);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result(); var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result();
if (isLFSFiltered) if (isLFSFiltered)
{ {
var tmpFile = saveTo + ".tmp"; var pointerStream = QueryFileContent.Run(repo, revision, file);
if (ExecCmd(repo, $"show {revision}:\"{file}\"", tmpFile)) ExecCmd(repo, $"lfs smudge", saveTo, pointerStream);
{
ExecCmd(repo, $"lfs smudge", saveTo, tmpFile);
}
File.Delete(tmpFile);
} }
else else
{ {
@ -26,7 +26,7 @@ namespace SourceGit.Commands
} }
} }
private static bool ExecCmd(string repo, string args, string outputFile, string inputFile = null) private static void ExecCmd(string repo, string args, string outputFile, Stream input = null)
{ {
var starter = new ProcessStartInfo(); var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo; starter.WorkingDirectory = repo;
@ -45,27 +45,11 @@ namespace SourceGit.Commands
{ {
var proc = new Process() { StartInfo = starter }; var proc = new Process() { StartInfo = starter };
proc.Start(); proc.Start();
if (input != null)
if (inputFile != null) proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
{
using (StreamReader sr = new StreamReader(inputFile))
{
while (true)
{
var line = sr.ReadLine();
if (line == null)
break;
proc.StandardInput.WriteLine(line);
}
}
}
proc.StandardOutput.BaseStream.CopyTo(sw); proc.StandardOutput.BaseStream.CopyTo(sw);
proc.WaitForExit(); proc.WaitForExit();
var rs = proc.ExitCode == 0;
proc.Close(); proc.Close();
return rs;
} }
catch (Exception e) catch (Exception e)
{ {
@ -73,7 +57,6 @@ namespace SourceGit.Commands
{ {
App.RaiseException(repo, "Save file failed: " + e.Message); App.RaiseException(repo, "Save file failed: " + e.Message);
}); });
return false;
} }
} }
} }

View file

@ -23,13 +23,11 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash); _patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t"); _patchBuilder.Append("\t");
_patchBuilder.Append(c.OriginalPath); _patchBuilder.Append(c.OriginalPath);
_patchBuilder.Append("\n");
} }
else if (c.Index == Models.ChangeState.Added) else if (c.Index == Models.ChangeState.Added)
{ {
_patchBuilder.Append("0 0000000000000000000000000000000000000000\t"); _patchBuilder.Append("0 0000000000000000000000000000000000000000\t");
_patchBuilder.Append(c.Path); _patchBuilder.Append(c.Path);
_patchBuilder.Append("\n");
} }
else if (c.Index == Models.ChangeState.Deleted) else if (c.Index == Models.ChangeState.Deleted)
{ {
@ -37,7 +35,6 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash); _patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t"); _patchBuilder.Append("\t");
_patchBuilder.Append(c.Path); _patchBuilder.Append(c.Path);
_patchBuilder.Append("\n");
} }
else else
{ {
@ -46,8 +43,9 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash); _patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t"); _patchBuilder.Append("\t");
_patchBuilder.Append(c.Path); _patchBuilder.Append(c.Path);
_patchBuilder.Append("\n");
} }
_patchBuilder.Append("\n");
} }
} }

View file

@ -0,0 +1,27 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;
namespace SourceGit.Converters
{
public static class ObjectConverters
{
public class IsTypeOfConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return false;
return value.GetType().IsAssignableTo((Type)parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return new NotImplementedException();
}
}
public static readonly IsTypeOfConverter IsTypeOf = new IsTypeOfConverter();
}
}

View file

@ -17,7 +17,7 @@ namespace SourceGit.Models
{ {
public interface IAvatarHost public interface IAvatarHost
{ {
void OnAvatarResourceChanged(string email); void OnAvatarResourceChanged(string email, Bitmap image);
} }
public partial class AvatarManager public partial class AvatarManager
@ -26,10 +26,7 @@ namespace SourceGit.Models
{ {
get get
{ {
if (_instance == null) return _instance ??= new AvatarManager();
_instance = new AvatarManager();
return _instance;
} }
} }
@ -38,7 +35,7 @@ namespace SourceGit.Models
[GeneratedRegex(@"^(?:(\d+)\+)?(.+?)@.+\.github\.com$")] [GeneratedRegex(@"^(?:(\d+)\+)?(.+?)@.+\.github\.com$")]
private static partial Regex REG_GITHUB_USER_EMAIL(); private static partial Regex REG_GITHUB_USER_EMAIL();
private object _synclock = new object(); private readonly Lock _synclock = new();
private string _storePath; private string _storePath;
private List<IAvatarHost> _avatars = new List<IAvatarHost>(); private List<IAvatarHost> _avatars = new List<IAvatarHost>();
private Dictionary<string, Bitmap> _resources = new Dictionary<string, Bitmap>(); private Dictionary<string, Bitmap> _resources = new Dictionary<string, Bitmap>();
@ -119,7 +116,7 @@ namespace SourceGit.Models
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
_resources[email] = img; _resources[email] = img;
NotifyResourceChanged(email); NotifyResourceChanged(email, img);
}); });
} }
@ -144,14 +141,13 @@ namespace SourceGit.Models
if (_defaultAvatars.Contains(email)) if (_defaultAvatars.Contains(email))
return null; return null;
if (_resources.ContainsKey(email)) _resources.Remove(email);
_resources.Remove(email);
var localFile = Path.Combine(_storePath, GetEmailHash(email)); var localFile = Path.Combine(_storePath, GetEmailHash(email));
if (File.Exists(localFile)) if (File.Exists(localFile))
File.Delete(localFile); File.Delete(localFile);
NotifyResourceChanged(email); NotifyResourceChanged(email, null);
} }
else else
{ {
@ -179,13 +175,40 @@ namespace SourceGit.Models
lock (_synclock) lock (_synclock)
{ {
if (!_requesting.Contains(email)) _requesting.Add(email);
_requesting.Add(email);
} }
return null; return null;
} }
public void SetFromLocal(string email, string file)
{
try
{
Bitmap image = null;
using (var stream = File.OpenRead(file))
{
image = Bitmap.DecodeToWidth(stream, 128);
}
if (image == null)
return;
_resources[email] = image;
_requesting.Remove(email);
var store = Path.Combine(_storePath, GetEmailHash(email));
File.Copy(file, store, true);
NotifyResourceChanged(email, image);
}
catch
{
// ignore
}
}
private void LoadDefaultAvatar(string key, string img) private void LoadDefaultAvatar(string key, string img)
{ {
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute)); var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
@ -203,12 +226,10 @@ namespace SourceGit.Models
return builder.ToString(); return builder.ToString();
} }
private void NotifyResourceChanged(string email) private void NotifyResourceChanged(string email, Bitmap image)
{ {
foreach (var avatar in _avatars) foreach (var avatar in _avatars)
{ avatar.OnAvatarResourceChanged(email, image);
avatar.OnAvatarResourceChanged(email);
}
} }
} }
} }

View file

@ -19,7 +19,7 @@ namespace SourceGit.Models
public class Commit public class Commit
{ {
// As retrieved by: git mktree </dev/null // As retrieved by: git mktree </dev/null
public static readonly string EmptyTreeSHA1 = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"; public const string EmptyTreeSHA1 = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
public static double OpacityForNotMerged public static double OpacityForNotMerged
{ {
@ -33,14 +33,14 @@ namespace SourceGit.Models
public User Committer { get; set; } = User.Invalid; public User Committer { get; set; } = User.Invalid;
public ulong CommitterTime { get; set; } = 0; public ulong CommitterTime { get; set; } = 0;
public string Subject { get; set; } = string.Empty; public string Subject { get; set; } = string.Empty;
public List<string> Parents { get; set; } = new List<string>(); public List<string> Parents { get; set; } = new();
public List<Decorator> Decorators { get; set; } = new List<Decorator>(); public List<Decorator> Decorators { get; set; } = new();
public bool HasDecorators => Decorators.Count > 0; public bool HasDecorators => Decorators.Count > 0;
public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly); public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly); public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
public bool IsMerged { get; set; } = false; public bool IsMerged { get; set; } = false;
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
@ -49,7 +49,7 @@ namespace SourceGit.Models
public int Color { get; set; } = 0; public int Color { get; set; } = 0;
public double Opacity => IsMerged ? 1 : OpacityForNotMerged; public double Opacity => IsMerged ? 1 : OpacityForNotMerged;
public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular; public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular;
public Thickness Margin { get; set; } = new Thickness(0); public Thickness Margin { get; set; } = new(0);
public IBrush Brush => CommitGraph.Pens[Color].Brush; public IBrush Brush => CommitGraph.Pens[Color].Brush;
public void ParseDecorators(string data) public void ParseDecorators(string data)
@ -113,7 +113,7 @@ namespace SourceGit.Models
if (l.Type != r.Type) if (l.Type != r.Type)
return (int)l.Type - (int)r.Type; return (int)l.Type - (int)r.Type;
else else
return string.Compare(l.Name, r.Name, StringComparison.Ordinal); return NumericSort.Compare(l.Name, r.Name);
}); });
} }
} }
@ -121,6 +121,6 @@ namespace SourceGit.Models
public class CommitFullMessage public class CommitFullMessage
{ {
public string Message { get; set; } = string.Empty; public string Message { get; set; } = string.Empty;
public List<InlineElement> Inlines { get; set; } = []; public InlineElementCollector Inlines { get; set; } = new();
} }
} }

View file

@ -4,7 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models namespace SourceGit.Models
{ {
public partial class CommitTemplate : ObservableObject public class CommitTemplate : ObservableObject
{ {
public string Name public string Name
{ {

View file

@ -25,7 +25,7 @@ namespace SourceGit.Models
set; set;
} = 0; } = 0;
public static DateTimeFormat Actived public static DateTimeFormat Active
{ {
get => Supported[ActiveIndex]; get => Supported[ActiveIndex];
} }

View file

@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace SourceGit.Models
{
public class DealWithChangesAfterStashing
{
public string Label { get; set; }
public string Desc { get; set; }
public static readonly List<DealWithChangesAfterStashing> Supported = [
new ("Discard", "All (or selected) changes will be discarded"),
new ("Keep Index", "Staged changes are left intact"),
new ("Keep All", "All (or selected) changes are left intact"),
];
public DealWithChangesAfterStashing(string label, string desc)
{
Label = label;
Desc = desc;
}
}
}

View file

@ -16,11 +16,10 @@ namespace SourceGit.Models
Deleted, Deleted,
} }
public class TextInlineRange public class TextInlineRange(int p, int n)
{ {
public int Start { get; set; } public int Start { get; set; } = p;
public int End { get; set; } public int End { get; set; } = p + n - 1;
public TextInlineRange(int p, int n) { Start = p; End = p + n - 1; }
} }
public class TextDiffLine public class TextDiffLine
@ -556,7 +555,7 @@ namespace SourceGit.Models
} }
else if (test.Type == TextDiffLineType.Added) else if (test.Type == TextDiffLineType.Added)
{ {
if (i < start - 1) if (i < start - 1 || isOldSide)
{ {
if (revert) if (revert)
{ {
@ -566,18 +565,7 @@ namespace SourceGit.Models
} }
else else
{ {
if (isOldSide) newCount++;
{
if (revert)
{
newCount++;
oldCount++;
}
}
else
{
newCount++;
}
} }
if (i == end - 1 && tailed) if (i == end - 1 && tailed)
@ -655,9 +643,7 @@ namespace SourceGit.Models
public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0"; public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0";
} }
public class NoOrEOLChange public class NoOrEOLChange;
{
}
public class FileModeDiff public class FileModeDiff
{ {

View file

@ -107,8 +107,7 @@ namespace SourceGit.Models
// Ignore // Ignore
} }
if (_customPaths == null) _customPaths ??= new ExternalToolPaths();
_customPaths = new ExternalToolPaths();
} }
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null) public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)

View file

@ -0,0 +1,10 @@
namespace SourceGit.Models
{
public enum ImageDecoder
{
None = 0,
Builtin,
Pfim,
Tiff,
}
}

View file

@ -2,8 +2,7 @@
{ {
public enum InlineElementType public enum InlineElementType
{ {
None = 0, Keyword = 0,
Keyword,
Link, Link,
CommitSHA, CommitSHA,
Code, Code,
@ -11,10 +10,10 @@
public class InlineElement public class InlineElement
{ {
public InlineElementType Type { get; set; } = InlineElementType.None; public InlineElementType Type { get; }
public int Start { get; set; } = 0; public int Start { get; }
public int Length { get; set; } = 0; public int Length { get; }
public string Link { get; set; } = ""; public string Link { get; }
public InlineElement(InlineElementType type, int start, int length, string link) public InlineElement(InlineElementType type, int start, int length, string link)
{ {
@ -24,7 +23,7 @@
Link = link; Link = link;
} }
public bool Intersect(int start, int length) public bool IsIntersecting(int start, int length)
{ {
if (start == Start) if (start == Start)
return true; return true;

View file

@ -0,0 +1,38 @@
using System.Collections.Generic;
namespace SourceGit.Models
{
public class InlineElementCollector
{
public int Count => _implementation.Count;
public InlineElement this[int index] => _implementation[index];
public InlineElement Intersect(int start, int length)
{
foreach (var elem in _implementation)
{
if (elem.IsIntersecting(start, length))
return elem;
}
return null;
}
public void Add(InlineElement element)
{
_implementation.Add(element);
}
public void Sort()
{
_implementation.Sort((l, r) => l.Start.CompareTo(r.Start));
}
public void Clear()
{
_implementation.Clear();
}
private readonly List<InlineElement> _implementation = [];
}
}

View file

@ -8,10 +8,7 @@ namespace SourceGit.Models
{ {
public class IpcChannel : IDisposable public class IpcChannel : IDisposable
{ {
public bool IsFirstInstance public bool IsFirstInstance { get; }
{
get => _isFirstInstance;
}
public event Action<string> MessageReceived; public event Action<string> MessageReceived;
@ -19,8 +16,8 @@ namespace SourceGit.Models
{ {
try try
{ {
_singletoneLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); _singletonLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_isFirstInstance = true; IsFirstInstance = true;
_server = new NamedPipeServerStream( _server = new NamedPipeServerStream(
"SourceGitIPCChannel" + Environment.UserName, "SourceGitIPCChannel" + Environment.UserName,
PipeDirection.In, PipeDirection.In,
@ -32,7 +29,7 @@ namespace SourceGit.Models
} }
catch catch
{ {
_isFirstInstance = false; IsFirstInstance = false;
} }
} }
@ -67,7 +64,7 @@ namespace SourceGit.Models
public void Dispose() public void Dispose()
{ {
_cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Cancel();
_singletoneLock?.Dispose(); _singletonLock?.Dispose();
} }
private async void StartServer() private async void StartServer()
@ -96,8 +93,7 @@ namespace SourceGit.Models
} }
} }
private FileStream _singletoneLock = null; private FileStream _singletonLock = null;
private bool _isFirstInstance = false;
private NamedPipeServerStream _server = null; private NamedPipeServerStream _server = null;
private CancellationTokenSource _cancellationTokenSource = null; private CancellationTokenSource _cancellationTokenSource = null;
} }

View file

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Text.RegularExpressions;
using System.Text.RegularExpressions;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -46,7 +45,7 @@ namespace SourceGit.Models
set => SetProperty(ref _urlTemplate, value); set => SetProperty(ref _urlTemplate, value);
} }
public void Matches(List<InlineElement> outs, string message) public void Matches(InlineElementCollector outs, string message)
{ {
if (_regex == null || string.IsNullOrEmpty(_urlTemplate)) if (_regex == null || string.IsNullOrEmpty(_urlTemplate))
return; return;
@ -60,17 +59,7 @@ namespace SourceGit.Models
var start = match.Index; var start = match.Index;
var len = match.Length; var len = match.Length;
var intersect = false; if (outs.Intersect(start, len) != null)
foreach (var exist in outs)
{
if (exist.Intersect(start, len))
{
intersect = true;
break;
}
}
if (intersect)
continue; continue;
var link = _urlTemplate; var link = _urlTemplate;

View file

@ -1,8 +1,22 @@
namespace SourceGit.Models using System.Text.RegularExpressions;
namespace SourceGit.Models
{ {
public class LFSObject public partial class LFSObject
{ {
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
private static partial Regex REG_FORMAT();
public string Oid { get; set; } = string.Empty; public string Oid { get; set; } = string.Empty;
public long Size { get; set; } = 0; public long Size { get; set; } = 0;
public static LFSObject Parse(string content)
{
var match = REG_FORMAT().Match(content);
if (match.Success)
return new() { Oid = match.Groups[1].Value, Size = long.Parse(match.Groups[2].Value) };
return null;
}
} }
} }

View file

@ -1,6 +1,4 @@
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class Null public class Null;
{
}
} }

View file

@ -1,4 +1,6 @@
namespace SourceGit.Models using System;
namespace SourceGit.Models
{ {
public static class NumericSort public static class NumericSort
{ {
@ -10,52 +12,35 @@
int marker1 = 0; int marker1 = 0;
int marker2 = 0; int marker2 = 0;
char[] tmp1 = new char[len1];
char[] tmp2 = new char[len2];
while (marker1 < len1 && marker2 < len2) while (marker1 < len1 && marker2 < len2)
{ {
char c1 = s1[marker1]; char c1 = s1[marker1];
char c2 = s2[marker2]; char c2 = s2[marker2];
int loc1 = 0;
int loc2 = 0;
bool isDigit1 = char.IsDigit(c1); bool isDigit1 = char.IsDigit(c1);
bool isDigit2 = char.IsDigit(c2); bool isDigit2 = char.IsDigit(c2);
if (isDigit1 != isDigit2) if (isDigit1 != isDigit2)
return c1.CompareTo(c2); return c1.CompareTo(c2);
do int subLen1 = 1;
{ while (marker1 + subLen1 < len1 && char.IsDigit(s1[marker1 + subLen1]) == isDigit1)
tmp1[loc1] = c1; subLen1++;
loc1++;
marker1++;
if (marker1 < len1) int subLen2 = 1;
c1 = s1[marker1]; while (marker2 + subLen2 < len2 && char.IsDigit(s2[marker2 + subLen2]) == isDigit2)
else subLen2++;
break;
} while (char.IsDigit(c1) == isDigit1);
do string sub1 = s1.Substring(marker1, subLen1);
{ string sub2 = s2.Substring(marker2, subLen2);
tmp2[loc2] = c2;
loc2++;
marker2++;
if (marker2 < len2) marker1 += subLen1;
c2 = s2[marker2]; marker2 += subLen2;
else
break;
} while (char.IsDigit(c2) == isDigit2);
string sub1 = new string(tmp1, 0, loc1);
string sub2 = new string(tmp2, 0, loc2);
int result; int result;
if (isDigit1) if (isDigit1)
result = loc1 == loc2 ? string.CompareOrdinal(sub1, sub2) : loc1 - loc2; result = (subLen1 == subLen2) ? string.CompareOrdinal(sub1, sub2) : (subLen1 - subLen2);
else else
result = string.CompareOrdinal(sub1, sub2); result = string.Compare(sub1, sub2, StringComparison.OrdinalIgnoreCase);
if (result != 0) if (result != 0)
return result; return result;

View file

@ -32,7 +32,7 @@ namespace SourceGit.Models
set; set;
} = false; } = false;
public bool OnlyHighlighCurrentBranchInHistories public bool OnlyHighlightCurrentBranchInHistories
{ {
get; get;
set; set;
@ -176,19 +176,13 @@ namespace SourceGit.Models
set; set;
} = false; } = false;
public bool KeepIndexWhenStash public int ChangesAfterStashing
{ {
get; get;
set; set;
} = false; } = 0;
public bool AutoRestoreAfterStash public string PreferredOpenAIService
{
get;
set;
} = false;
public string PreferedOpenAIService
{ {
get; get;
set; set;
@ -287,9 +281,8 @@ namespace SourceGit.Models
return false; return false;
} }
for (int i = 0; i < HistoriesFilters.Count; i++) foreach (var filter in HistoriesFilters)
{ {
var filter = HistoriesFilters[i];
if (filter.Type != type) if (filter.Type != type)
continue; continue;
@ -453,5 +446,19 @@ namespace SourceGit.Models
if (act != null) if (act != null)
CustomActions.Remove(act); CustomActions.Remove(act);
} }
public void MoveCustomActionUp(CustomAction act)
{
var idx = CustomActions.IndexOf(act);
if (idx > 0)
CustomActions.Move(idx - 1, idx);
}
public void MoveCustomActionDown(CustomAction act)
{
var idx = CustomActions.IndexOf(act);
if (idx < CustomActions.Count - 1)
CustomActions.Move(idx + 1, idx);
}
} }
} }

View file

@ -1,4 +1,6 @@
using Avalonia.Media.Imaging; using System.Globalization;
using System.IO;
using Avalonia.Media.Imaging;
namespace SourceGit.Models namespace SourceGit.Models
{ {
@ -9,10 +11,17 @@ namespace SourceGit.Models
public class RevisionImageFile public class RevisionImageFile
{ {
public Bitmap Image { get; set; } = null; public Bitmap Image { get; }
public long FileSize { get; set; } = 0; public long FileSize { get; }
public string ImageType { get; set; } = string.Empty; public string ImageType { get; }
public string ImageSize => Image != null ? $"{Image.PixelSize.Width} x {Image.PixelSize.Height}" : "0 x 0"; public string ImageSize => Image != null ? $"{Image.PixelSize.Width} x {Image.PixelSize.Height}" : "0 x 0";
public RevisionImageFile(string file, Bitmap img, long size)
{
Image = img;
FileSize = size;
ImageType = Path.GetExtension(file)!.Substring(1).ToUpper(CultureInfo.CurrentCulture);
}
} }
public class RevisionTextFile public class RevisionTextFile

View file

@ -33,9 +33,7 @@ namespace SourceGit.Models
} }
} }
public class AlreadyUpToDate public class AlreadyUpToDate;
{
}
public class SelfUpdateFailed public class SelfUpdateFailed
{ {

View file

@ -11,6 +11,24 @@ namespace SourceGit.Models
public ulong Time { get; set; } = 0; public ulong Time { get; set; } = 0;
public string Message { get; set; } = ""; public string Message { get; set; } = "";
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); public string Subject
{
get
{
var idx = Message.IndexOf('\n', StringComparison.Ordinal);
return idx > 0 ? Message.Substring(0, idx).Trim() : Message;
}
}
public string TimeStr
{
get
{
return DateTime.UnixEpoch
.AddSeconds(Time)
.ToLocalTime()
.ToString(DateTimeFormat.Active.DateTime);
}
}
} }
} }

View file

@ -5,8 +5,7 @@ namespace SourceGit.Models
public enum TagSortMode public enum TagSortMode
{ {
CreatorDate = 0, CreatorDate = 0,
NameInAscending, Name,
NameInDescending,
} }
public class Tag : ObservableObject public class Tag : ObservableObject

View file

@ -102,7 +102,7 @@ namespace SourceGit.Models
private int? Integer() private int? Integer()
{ {
var start = _pos; var start = _pos;
while (Peek() is char c && c >= '0' && c <= '9') while (Peek() is >= '0' and <= '9')
{ {
_pos++; _pos++;
} }
@ -118,7 +118,7 @@ namespace SourceGit.Models
// text token start // text token start
var tok = _pos; var tok = _pos;
bool esc = false; bool esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {
@ -129,7 +129,7 @@ namespace SourceGit.Models
{ {
case ESCAPE: case ESCAPE:
// allow to escape only \ and $ // allow to escape only \ and $
if (Peek() is char nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR)) if (Peek() is { } nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR))
{ {
esc = true; esc = true;
FlushText(tok, _pos - 1); FlushText(tok, _pos - 1);
@ -173,7 +173,7 @@ namespace SourceGit.Models
if (Next() != VARIABLE_START) if (Next() != VARIABLE_START)
return null; return null;
int name_start = _pos; int name_start = _pos;
while (Next() is char c) while (Next() is { } c)
{ {
// name character, continue advancing // name character, continue advancing
if (IsNameChar(c)) if (IsNameChar(c))
@ -228,7 +228,7 @@ namespace SourceGit.Models
var sb = new StringBuilder(); var sb = new StringBuilder();
var tok = _pos; var tok = _pos;
var esc = false; var esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {
@ -277,7 +277,7 @@ namespace SourceGit.Models
var sb = new StringBuilder(); var sb = new StringBuilder();
var tok = _pos; var tok = _pos;
var esc = false; var esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {
@ -402,7 +402,7 @@ namespace SourceGit.Models
sb.AppendJoin(", ", paths); sb.AppendJoin(", ", paths);
if (max < context.changes.Count) if (max < context.changes.Count)
sb.AppendFormat(" and {0} other files", context.changes.Count - max); sb.Append($" and {context.changes.Count - max} other files");
return sb.ToString(); return sb.ToString();
} }

View file

@ -2,30 +2,22 @@
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class TextInlineChange public class TextInlineChange(int dp, int dc, int ap, int ac)
{ {
public int DeletedStart { get; set; } public int DeletedStart { get; set; } = dp;
public int DeletedCount { get; set; } public int DeletedCount { get; set; } = dc;
public int AddedStart { get; set; } public int AddedStart { get; set; } = ap;
public int AddedCount { get; set; } public int AddedCount { get; set; } = ac;
class Chunk private class Chunk(int hash, int start, int size)
{ {
public int Hash; public readonly int Hash = hash;
public readonly int Start = start;
public readonly int Size = size;
public bool Modified; public bool Modified;
public int Start;
public int Size;
public Chunk(int hash, int start, int size)
{
Hash = hash;
Modified = false;
Start = start;
Size = size;
}
} }
enum Edit private enum Edit
{ {
None, None,
DeletedRight, DeletedRight,
@ -34,7 +26,7 @@ namespace SourceGit.Models
AddedLeft, AddedLeft,
} }
class EditResult private class EditResult
{ {
public Edit State; public Edit State;
public int DeleteStart; public int DeleteStart;
@ -43,14 +35,6 @@ namespace SourceGit.Models
public int AddEnd; public int AddEnd;
} }
public TextInlineChange(int dp, int dc, int ap, int ac)
{
DeletedStart = dp;
DeletedCount = dc;
AddedStart = ap;
AddedCount = ac;
}
public static List<TextInlineChange> Compare(string oldValue, string newValue) public static List<TextInlineChange> Compare(string oldValue, string newValue)
{ {
var hashes = new Dictionary<string, int>(); var hashes = new Dictionary<string, int>();
@ -204,11 +188,10 @@ namespace SourceGit.Models
for (int i = 0; i <= half; i++) for (int i = 0; i <= half; i++)
{ {
for (int j = -i; j <= i; j += 2) for (int j = -i; j <= i; j += 2)
{ {
var idx = j + half; var idx = j + half;
int o, n; int o;
if (j == -i || (j != i && forward[idx - 1] < forward[idx + 1])) if (j == -i || (j != i && forward[idx - 1] < forward[idx + 1]))
{ {
o = forward[idx + 1]; o = forward[idx + 1];
@ -220,7 +203,7 @@ namespace SourceGit.Models
rs.State = Edit.DeletedRight; rs.State = Edit.DeletedRight;
} }
n = o - j; var n = o - j;
var startX = o; var startX = o;
var startY = n; var startY = n;
@ -258,7 +241,7 @@ namespace SourceGit.Models
for (int j = -i; j <= i; j += 2) for (int j = -i; j <= i; j += 2)
{ {
var idx = j + half; var idx = j + half;
int o, n; int o;
if (j == -i || (j != i && reverse[idx + 1] <= reverse[idx - 1])) if (j == -i || (j != i && reverse[idx + 1] <= reverse[idx - 1]))
{ {
o = reverse[idx + 1] - 1; o = reverse[idx + 1] - 1;
@ -270,7 +253,7 @@ namespace SourceGit.Models
rs.State = Edit.AddedLeft; rs.State = Edit.AddedLeft;
} }
n = o - (j + delta); var n = o - (j + delta);
var endX = o; var endX = o;
var endY = n; var endY = n;
@ -312,8 +295,7 @@ namespace SourceGit.Models
private static void AddChunk(List<Chunk> chunks, Dictionary<string, int> hashes, string data, int start) private static void AddChunk(List<Chunk> chunks, Dictionary<string, int> hashes, string data, int start)
{ {
int hash; if (hashes.TryGetValue(data, out var hash))
if (hashes.TryGetValue(data, out hash))
{ {
chunks.Add(new Chunk(hash, start, data.Length)); chunks.Add(new Chunk(hash, start, data.Length));
} }

View file

@ -26,11 +26,7 @@ namespace SourceGit.Models
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null || !(obj is User)) return obj is User other && Name == other.Name && Email == other.Email;
return false;
var other = obj as User;
return Name == other.Name && Email == other.Email;
} }
public override int GetHashCode() public override int GetHashCode()

View file

@ -12,27 +12,50 @@ namespace SourceGit.Models
{ {
_repo = repo; _repo = repo;
_wcWatcher = new FileSystemWatcher(); var testGitDir = new DirectoryInfo(Path.Combine(fullpath, ".git")).FullName;
_wcWatcher.Path = fullpath; var desiredDir = new DirectoryInfo(gitDir).FullName;
_wcWatcher.Filter = "*"; if (testGitDir.Equals(desiredDir, StringComparison.Ordinal))
_wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime; {
_wcWatcher.IncludeSubdirectories = true; var combined = new FileSystemWatcher();
_wcWatcher.Created += OnWorkingCopyChanged; combined.Path = fullpath;
_wcWatcher.Renamed += OnWorkingCopyChanged; combined.Filter = "*";
_wcWatcher.Changed += OnWorkingCopyChanged; combined.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
_wcWatcher.Deleted += OnWorkingCopyChanged; combined.IncludeSubdirectories = true;
_wcWatcher.EnableRaisingEvents = true; combined.Created += OnRepositoryChanged;
combined.Renamed += OnRepositoryChanged;
combined.Changed += OnRepositoryChanged;
combined.Deleted += OnRepositoryChanged;
combined.EnableRaisingEvents = true;
_repoWatcher = new FileSystemWatcher(); _watchers.Add(combined);
_repoWatcher.Path = gitDir; }
_repoWatcher.Filter = "*"; else
_repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; {
_repoWatcher.IncludeSubdirectories = true; var wc = new FileSystemWatcher();
_repoWatcher.Created += OnRepositoryChanged; wc.Path = fullpath;
_repoWatcher.Renamed += OnRepositoryChanged; wc.Filter = "*";
_repoWatcher.Changed += OnRepositoryChanged; wc.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
_repoWatcher.Deleted += OnRepositoryChanged; wc.IncludeSubdirectories = true;
_repoWatcher.EnableRaisingEvents = true; wc.Created += OnWorkingCopyChanged;
wc.Renamed += OnWorkingCopyChanged;
wc.Changed += OnWorkingCopyChanged;
wc.Deleted += OnWorkingCopyChanged;
wc.EnableRaisingEvents = true;
var git = new FileSystemWatcher();
git.Path = gitDir;
git.Filter = "*";
git.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
git.IncludeSubdirectories = true;
git.Created += OnGitDirChanged;
git.Renamed += OnGitDirChanged;
git.Changed += OnGitDirChanged;
git.Deleted += OnGitDirChanged;
git.EnableRaisingEvents = true;
_watchers.Add(wc);
_watchers.Add(git);
}
_timer = new Timer(Tick, null, 100, 100); _timer = new Timer(Tick, null, 100, 100);
} }
@ -77,22 +100,13 @@ namespace SourceGit.Models
public void Dispose() public void Dispose()
{ {
_repoWatcher.EnableRaisingEvents = false; foreach (var watcher in _watchers)
_repoWatcher.Created -= OnRepositoryChanged; {
_repoWatcher.Renamed -= OnRepositoryChanged; watcher.EnableRaisingEvents = false;
_repoWatcher.Changed -= OnRepositoryChanged; watcher.Dispose();
_repoWatcher.Deleted -= OnRepositoryChanged; }
_repoWatcher.Dispose();
_repoWatcher = null;
_wcWatcher.EnableRaisingEvents = false;
_wcWatcher.Created -= OnWorkingCopyChanged;
_wcWatcher.Renamed -= OnWorkingCopyChanged;
_wcWatcher.Changed -= OnWorkingCopyChanged;
_wcWatcher.Deleted -= OnWorkingCopyChanged;
_wcWatcher.Dispose();
_wcWatcher = null;
_watchers.Clear();
_timer.Dispose(); _timer.Dispose();
_timer = null; _timer = null;
} }
@ -153,11 +167,45 @@ namespace SourceGit.Models
} }
private void OnRepositoryChanged(object o, FileSystemEventArgs e) private void OnRepositoryChanged(object o, FileSystemEventArgs e)
{
if (string.IsNullOrEmpty(e.Name) || e.Name.Equals(".git", StringComparison.Ordinal))
return;
var name = e.Name.Replace('\\', '/').TrimEnd('/');
if (name.EndsWith("/.git", StringComparison.Ordinal))
return;
if (name.StartsWith(".git/", StringComparison.Ordinal))
HandleGitDirFileChanged(name.Substring(5));
else
HandleWorkingCopyFileChanged(name);
}
private void OnGitDirChanged(object o, FileSystemEventArgs e)
{ {
if (string.IsNullOrEmpty(e.Name)) if (string.IsNullOrEmpty(e.Name))
return; return;
var name = e.Name.Replace("\\", "/"); var name = e.Name.Replace('\\', '/').TrimEnd('/');
HandleGitDirFileChanged(name);
}
private void OnWorkingCopyChanged(object o, FileSystemEventArgs e)
{
if (string.IsNullOrEmpty(e.Name))
return;
var name = e.Name.Replace('\\', '/').TrimEnd('/');
if (name.Equals(".git", StringComparison.Ordinal) ||
name.StartsWith(".git/", StringComparison.Ordinal) ||
name.EndsWith("/.git", StringComparison.Ordinal))
return;
HandleWorkingCopyFileChanged(name);
}
private void HandleGitDirFileChanged(string name)
{
if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) || if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) ||
name.EndsWith(".lock", StringComparison.Ordinal) || name.EndsWith(".lock", StringComparison.Ordinal) ||
name.StartsWith("lfs/", StringComparison.Ordinal)) name.StartsWith("lfs/", StringComparison.Ordinal))
@ -200,17 +248,8 @@ namespace SourceGit.Models
} }
} }
private void OnWorkingCopyChanged(object o, FileSystemEventArgs e) private void HandleWorkingCopyFileChanged(string name)
{ {
if (string.IsNullOrEmpty(e.Name))
return;
var name = e.Name.Replace("\\", "/");
if (name.Equals(".git", StringComparison.Ordinal) ||
name.StartsWith(".git/", StringComparison.Ordinal) ||
name.EndsWith("/.git", StringComparison.Ordinal))
return;
if (name.StartsWith(".vs/", StringComparison.Ordinal)) if (name.StartsWith(".vs/", StringComparison.Ordinal))
return; return;
@ -236,8 +275,7 @@ namespace SourceGit.Models
} }
private readonly IRepository _repo = null; private readonly IRepository _repo = null;
private FileSystemWatcher _repoWatcher = null; private List<FileSystemWatcher> _watchers = [];
private FileSystemWatcher _wcWatcher = null;
private Timer _timer = null; private Timer _timer = null;
private int _lockCount = 0; private int _lockCount = 0;
private long _updateWC = 0; private long _updateWC = 0;
@ -246,7 +284,7 @@ namespace SourceGit.Models
private long _updateStashes = 0; private long _updateStashes = 0;
private long _updateTags = 0; private long _updateTags = 0;
private object _lockSubmodule = new object(); private readonly Lock _lockSubmodule = new();
private List<string> _submodules = new List<string>(); private List<string> _submodules = new List<string>();
} }
} }

View file

@ -23,7 +23,7 @@ namespace SourceGit.Models
get get
{ {
if (IsDetached) if (IsDetached)
return $"deteched HEAD at {Head.AsSpan(10)}"; return $"detached HEAD at {Head.AsSpan(10)}";
if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal)) if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal))
return Branch.Substring(11); return Branch.Substring(11);

View file

@ -120,8 +120,8 @@ namespace SourceGit.Native
private string FindExecutable(string filename) private string FindExecutable(string filename)
{ {
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty; var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries); var paths = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
foreach (var path in pathes) foreach (var path in paths)
{ {
var test = Path.Combine(path, filename); var test = Path.Combine(path, filename);
if (File.Exists(test)) if (File.Exists(test))

View file

@ -54,7 +54,7 @@ namespace SourceGit.Native
public void SetupApp(AppBuilder builder) public void SetupApp(AppBuilder builder)
{ {
// Fix drop shadow issue on Windows 10 // Fix drop shadow issue on Windows 10
if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000, 0)) if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000))
{ {
Window.WindowStateProperty.Changed.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w)); Window.WindowStateProperty.Changed.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w));
Control.LoadedEvent.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w)); Control.LoadedEvent.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w));
@ -80,17 +80,17 @@ namespace SourceGit.Native
var p = IntPtrToPixelPoint(lParam); var p = IntPtrToPixelPoint(lParam);
GetWindowRect(hWnd, out var rcWindow); GetWindowRect(hWnd, out var rcWindow);
var borderThinkness = (int)(4 * window.RenderScaling); var borderThickness = (int)(4 * window.RenderScaling);
int y = 1; int y = 1;
int x = 1; int x = 1;
if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThinkness) if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThickness)
x = 0; x = 0;
else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThinkness) else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThickness)
x = 2; x = 2;
if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThinkness) if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThickness)
y = 0; y = 0;
else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThinkness) else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThickness)
y = 2; y = 2;
var zone = y * 3 + x; var zone = y * 3 + x;
@ -127,23 +127,17 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryHive.LocalMachine, Microsoft.Win32.RegistryHive.LocalMachine,
Microsoft.Win32.RegistryView.Registry64); Microsoft.Win32.RegistryView.Registry64);
var git = reg.OpenSubKey("SOFTWARE\\GitForWindows"); var git = reg.OpenSubKey(@"SOFTWARE\GitForWindows");
if (git != null && git.GetValue("InstallPath") is string installPath) if (git?.GetValue("InstallPath") is string installPath)
{
return Path.Combine(installPath, "bin", "git.exe"); return Path.Combine(installPath, "bin", "git.exe");
}
var builder = new StringBuilder("git.exe", 259); var builder = new StringBuilder("git.exe", 259);
if (!PathFindOnPath(builder, null)) if (!PathFindOnPath(builder, null))
{
return null; return null;
}
var exePath = builder.ToString(); var exePath = builder.ToString();
if (!string.IsNullOrEmpty(exePath)) if (!string.IsNullOrEmpty(exePath))
{
return exePath; return exePath;
}
return null; return null;
} }
@ -181,7 +175,7 @@ namespace SourceGit.Native
break; break;
case "cmd": case "cmd":
return "C:\\Windows\\System32\\cmd.exe"; return @"C:\Windows\System32\cmd.exe";
case "wt": case "wt":
var wtFinder = new StringBuilder("wt.exe", 512); var wtFinder = new StringBuilder("wt.exe", 512);
if (PathFindOnPath(wtFinder, null)) if (PathFindOnPath(wtFinder, null))
@ -199,8 +193,8 @@ namespace SourceGit.Native
finder.VSCode(FindVSCode); finder.VSCode(FindVSCode);
finder.VSCodeInsiders(FindVSCodeInsiders); finder.VSCodeInsiders(FindVSCodeInsiders);
finder.VSCodium(FindVSCodium); finder.VSCodium(FindVSCodium);
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe"); finder.Fleet(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\Programs\Fleet\Fleet.exe");
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox"); finder.FindJetBrainsFromToolbox(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\JetBrains\Toolbox");
finder.SublimeText(FindSublimeText); finder.SublimeText(FindSublimeText);
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio); finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
return finder.Founded; return finder.Founded;
@ -299,9 +293,7 @@ namespace SourceGit.Native
// VSCode (system) // VSCode (system)
var systemVScode = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EA457B21-F73E-494C-ACAB-524FDE069978}_is1"); var systemVScode = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EA457B21-F73E-494C-ACAB-524FDE069978}_is1");
if (systemVScode != null) if (systemVScode != null)
{
return systemVScode.GetValue("DisplayIcon") as string; return systemVScode.GetValue("DisplayIcon") as string;
}
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey( var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser, Microsoft.Win32.RegistryHive.CurrentUser,
@ -310,9 +302,7 @@ namespace SourceGit.Native
// VSCode (user) // VSCode (user)
var vscode = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{771FD6B0-FA20-440A-A002-3B3BAC16DC50}_is1"); var vscode = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{771FD6B0-FA20-440A-A002-3B3BAC16DC50}_is1");
if (vscode != null) if (vscode != null)
{
return vscode.GetValue("DisplayIcon") as string; return vscode.GetValue("DisplayIcon") as string;
}
return string.Empty; return string.Empty;
} }
@ -326,9 +316,7 @@ namespace SourceGit.Native
// VSCode - Insiders (system) // VSCode - Insiders (system)
var systemVScodeInsiders = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1"); var systemVScodeInsiders = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1");
if (systemVScodeInsiders != null) if (systemVScodeInsiders != null)
{
return systemVScodeInsiders.GetValue("DisplayIcon") as string; return systemVScodeInsiders.GetValue("DisplayIcon") as string;
}
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey( var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser, Microsoft.Win32.RegistryHive.CurrentUser,
@ -337,9 +325,7 @@ namespace SourceGit.Native
// VSCode - Insiders (user) // VSCode - Insiders (user)
var vscodeInsiders = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{217B4C08-948D-4276-BFBB-BEE930AE5A2C}_is1"); var vscodeInsiders = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{217B4C08-948D-4276-BFBB-BEE930AE5A2C}_is1");
if (vscodeInsiders != null) if (vscodeInsiders != null)
{
return vscodeInsiders.GetValue("DisplayIcon") as string; return vscodeInsiders.GetValue("DisplayIcon") as string;
}
return string.Empty; return string.Empty;
} }
@ -351,11 +337,9 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryView.Registry64); Microsoft.Win32.RegistryView.Registry64);
// VSCodium (system) // VSCodium (system)
var systemVScodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1"); var systemVSCodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1");
if (systemVScodium != null) if (systemVSCodium != null)
{ return systemVSCodium.GetValue("DisplayIcon") as string;
return systemVScodium.GetValue("DisplayIcon") as string;
}
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey( var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser, Microsoft.Win32.RegistryHive.CurrentUser,
@ -364,9 +348,7 @@ namespace SourceGit.Native
// VSCodium (user) // VSCodium (user)
var vscodium = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{2E1F05D1-C245-4562-81EE-28188DB6FD17}_is1"); var vscodium = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{2E1F05D1-C245-4562-81EE-28188DB6FD17}_is1");
if (vscodium != null) if (vscodium != null)
{
return vscodium.GetValue("DisplayIcon") as string; return vscodium.GetValue("DisplayIcon") as string;
}
return string.Empty; return string.Empty;
} }
@ -403,15 +385,13 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryView.Registry64); Microsoft.Win32.RegistryView.Registry64);
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files // Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher) if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is { } launcher)
{ {
// Get actual path to the executable // Get actual path to the executable
if (launcher.GetValue(string.Empty) is string CLSID && if (launcher.GetValue(string.Empty) is string CLSID &&
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv && localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is { } devenv &&
devenv.GetValue(string.Empty) is string localServer32) devenv.GetValue(string.Empty) is string localServer32)
{
return localServer32!.Trim('\"'); return localServer32!.Trim('\"');
}
} }
return string.Empty; return string.Empty;

View file

@ -89,7 +89,8 @@
<StreamGeometry x:Key="Icons.Move">M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z</StreamGeometry> <StreamGeometry x:Key="Icons.Move">M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z</StreamGeometry>
<StreamGeometry x:Key="Icons.MoveToAnotherGroup">M64 363l0 204 265 0L329 460c0-11 6-18 14-20C349 437 355 437 362 441c93 60 226 149 226 149 33 22 34 60 0 82 0 0-133 89-226 149-14 9-32-3-32-18l-1-110L64 693l0 117c0 41 34 75 75 75l746 0c41 0 75-34 75-74L960 364c0-0 0-1 0-1L64 363zM64 214l0 75 650 0-33-80c-16-38-62-69-103-69l-440 0C97 139 64 173 64 214z</StreamGeometry> <StreamGeometry x:Key="Icons.MoveToAnotherGroup">M64 363l0 204 265 0L329 460c0-11 6-18 14-20C349 437 355 437 362 441c93 60 226 149 226 149 33 22 34 60 0 82 0 0-133 89-226 149-14 9-32-3-32-18l-1-110L64 693l0 117c0 41 34 75 75 75l746 0c41 0 75-34 75-74L960 364c0-0 0-1 0-1L64 363zM64 214l0 75 650 0-33-80c-16-38-62-69-103-69l-440 0C97 139 64 173 64 214z</StreamGeometry>
<StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry> <StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry>
<StreamGeometry x:Key="Icons.Order">M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z</StreamGeometry> <StreamGeometry x:Key="Icons.OrderByName">M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z</StreamGeometry>
<StreamGeometry x:Key="Icons.OrderByTime">M512 0a512 512 0 01512 512 57 57 0 01-114 0 398 398 0 10-398 398 57 57 0 010 114A512 512 0 01512 0zm367 600 121 120a57 57 0 01-80 81l-40-40V967a57 57 0 01-50 57l-7 0a57 57 0 01-57-57v-205l-40 40a57 57 0 01-75 5l-5-5a57 57 0 01-0-80l120-121a80 80 0 01113-0zM512 272a57 57 0 0157 57V499h114a57 57 0 0156 50L740 556a57 57 0 01-57 57H512a57 57 0 01-57-57v-228a57 57 0 0150-57L512 272z</StreamGeometry>
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry> <StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
<StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry> <StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry>
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry> <StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before After
Before After

View file

@ -39,6 +39,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE DATEIEN</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE DATEIEN</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Bild laden...</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Aktualisieren</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.Bisect">Bisect</x:String> <x:String x:Key="Text.Bisect">Bisect</x:String>
<x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String> <x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String>
@ -66,6 +68,7 @@
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String> <x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ auf ${1}$...</x:String> <x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ auf ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Benenne ${0}$ um...</x:String> <x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Benenne ${0}$ um...</x:String>
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Setze ${0}$ zurück auf ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Setze verfolgten Branch...</x:String> <x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Setze verfolgten Branch...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String> <x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Ungültiger upstream!</x:String> <x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Ungültiger upstream!</x:String>
@ -87,6 +90,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Alle Submodule updaten</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Alle Submodule updaten</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Auschecken &amp; Fast-Forward</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Fast-Forward zu:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Quelle an Commit-Nachricht anhängen</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Quelle an Commit-Nachricht anhängen</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
@ -119,6 +124,7 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactives Rebase von ${0}$ auf diesen Commit</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactives Rebase von ${0}$ auf diesen Commit</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge in ${0}$ hinein</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge in ${0}$ hinein</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Merge ...</x:String> <x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Merge ...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">Push ${0}$ zu ${1}$</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase von ${0}$ auf diesen Commit</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase von ${0}$ auf diesen Commit</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ auf diesen Commit</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ auf diesen Commit</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Commit rückgängig machen</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Commit rückgängig machen</x:String>
@ -127,6 +133,7 @@
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash in den Vorgänger</x:String> <x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash in den Vorgänger</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Nachfolger Commits bis hier</x:String> <x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Nachfolger Commits bis hier</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ÄNDERUNGEN</x:String> <x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ÄNDERUNGEN</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">geänderte Datei(en)</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Änderungen durchsuchen...</x:String> <x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Änderungen durchsuchen...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">DATEIEN</x:String> <x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">DATEIEN</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS DATEI</x:String> <x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">LFS DATEI</x:String>
@ -218,6 +225,7 @@
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Branch-Namen eingeben.</x:String> <x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Branch-Namen eingeben.</x:String>
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Leerzeichen werden durch Bindestriche ersetzt.</x:String> <x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Leerzeichen werden durch Bindestriche ersetzt.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Lokalen Branch erstellen</x:String> <x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Lokalen Branch erstellen</x:String>
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Überschreibe existierenden Branch</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Tag erstellen...</x:String> <x:String x:Key="Text.CreateTag" xml:space="preserve">Tag erstellen...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Neuer Tag auf:</x:String> <x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Neuer Tag auf:</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Mit GPG signieren</x:String> <x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Mit GPG signieren</x:String>
@ -232,6 +240,9 @@
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">Ohne Anmerkung</x:String> <x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">Ohne Anmerkung</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Halte Strg gedrückt, um direkt auszuführen</x:String> <x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Halte Strg gedrückt, um direkt auszuführen</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Ausschneiden</x:String> <x:String x:Key="Text.Cut" xml:space="preserve">Ausschneiden</x:String>
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">De-initialisiere Submodul</x:String>
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">Erzwinge De-Initialisierung, selbst wenn es lokale Änderungen enthält.</x:String>
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">Submodul:</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Branch löschen</x:String> <x:String x:Key="Text.DeleteBranch" xml:space="preserve">Branch löschen</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">Du löscht gerade einen Remote-Branch!!!</x:String> <x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">Du löscht gerade einen Remote-Branch!!!</x:String>
@ -267,6 +278,7 @@
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Zeige versteckte Symbole</x:String> <x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Zeige versteckte Symbole</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Nebeneinander</x:String> <x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Nebeneinander</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMODUL</x:String> <x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMODUL</x:String>
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">GELÖSCHT</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NEU</x:String> <x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NEU</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Seiten wechseln</x:String> <x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Seiten wechseln</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Hervorhebung</x:String> <x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Hervorhebung</x:String>
@ -325,6 +337,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String> <x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String> <x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Ziel:</x:String> <x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Ziel:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">Push zu Remote(s) nach Durchführung des Finish</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">Squash beim Merge</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String> <x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix-Prefix:</x:String> <x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix-Prefix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Git-Flow initialisieren</x:String> <x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Git-Flow initialisieren</x:String>
@ -386,6 +400,8 @@
<x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Zum vorherigen Tab wechseln</x:String> <x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Zum vorherigen Tab wechseln</x:String>
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Neuen Tab erstellen</x:String> <x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Neuen Tab erstellen</x:String>
<x:String x:Key="Text.Hotkeys.Global.OpenPreferences" xml:space="preserve">Einstellungen öffnen</x:String> <x:String x:Key="Text.Hotkeys.Global.OpenPreferences" xml:space="preserve">Einstellungen öffnen</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchWorkspace" xml:space="preserve">Aktiven Arbeitsplatz wechseln</x:String>
<x:String x:Key="Text.Hotkeys.Global.SwitchTab" xml:space="preserve">Aktiven Tab wechseln</x:String>
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String> <x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Gestagte Änderungen committen</x:String> <x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Gestagte Änderungen committen</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Gestagte Änderungen committen und pushen</x:String> <x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Gestagte Änderungen committen und pushen</x:String>
@ -406,6 +422,7 @@
<x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Suchpanel schließen</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Suchpanel schließen</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Suche nächste Übereinstimmung</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Suche nächste Übereinstimmung</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Suche vorherige Übereinstimmung</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Suche vorherige Übereinstimmung</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.OpenExternalMergeTool" xml:space="preserve">Öffne mit externem Diff/Merge Tool</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Öffne Suchpanel</x:String> <x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Öffne Suchpanel</x:String>
<x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Verwerfen</x:String> <x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Verwerfen</x:String>
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stagen</x:String> <x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stagen</x:String>
@ -427,7 +444,10 @@
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">In Browser öffnen</x:String> <x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">In Browser öffnen</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">FEHLER</x:String> <x:String x:Key="Text.Launcher.Error" xml:space="preserve">FEHLER</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">INFO</x:String> <x:String x:Key="Text.Launcher.Info" xml:space="preserve">INFO</x:String>
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Arbeitsplätze</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Tabs</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Branch mergen</x:String> <x:String x:Key="Text.Merge" xml:space="preserve">Branch mergen</x:String>
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Merge-Nachricht anpassen</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Ziel-Branch:</x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">Ziel-Branch:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Quelle:</x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">Quelle:</x:String>
@ -460,6 +480,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">Vor {0} Monaten</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">Vor {0} Monaten</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">Vor {0} Jahren</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">Vor {0} Jahren</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Gestern</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Gestern</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Verwende 'Shift+Enter' um eine neue Zeile einzufügen. 'Enter' ist das Kürzel für den OK Button</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Einstellungen</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Einstellungen</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analysierung des Diff Befehl</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analysierung des Diff Befehl</x:String>
@ -529,6 +550,7 @@
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String> <x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String> <x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String> <x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">Alle Submodule aktualisieren</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote:</x:String> <x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String> <x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Rebase anstatt Merge verwenden</x:String> <x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Rebase anstatt Merge verwenden</x:String>
@ -537,6 +559,8 @@
<x:String x:Key="Text.Push.Force" xml:space="preserve">Erzwinge Push</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">Erzwinge Push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Lokaler Branch:</x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">Lokaler Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Push.Revision" xml:space="preserve">Revision:</x:String>
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">Push Revision zu Remote-Branch</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Push</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Remote-Branch:</x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">Remote-Branch:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Remote-Branch verfolgen</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">Remote-Branch verfolgen</x:String>
@ -550,7 +574,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Lokale Änderungen stashen &amp; wieder anwenden</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Lokale Änderungen stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Auf:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">Auf:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Aktualisieren</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Remote hinzufügen</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Remote hinzufügen</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Remote bearbeiten</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Remote bearbeiten</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
@ -578,6 +601,7 @@
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC &amp; Prune)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Filter aufheben</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Filter aufheben</x:String>
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Löschen</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Repository Einstellungen</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">Repository Einstellungen</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">WEITER</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">WEITER</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Benutzerdefinierte Aktionen</x:String> <x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Benutzerdefinierte Aktionen</x:String>
@ -615,6 +639,7 @@
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String> <x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Aktueller Branch</x:String> <x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Aktueller Branch</x:String>
<x:String x:Key="Text.Repository.ShowSubmodulesAsTree" xml:space="preserve">Submodule als Baum anzeigen</x:String>
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Zeige Tags als Baum</x:String> <x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Zeige Tags als Baum</x:String>
<x:String x:Key="Text.Repository.Skip" xml:space="preserve">ÜBERSPRINGEN</x:String> <x:String x:Key="Text.Repository.Skip" xml:space="preserve">ÜBERSPRINGEN</x:String>
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistiken</x:String> <x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistiken</x:String>
@ -624,8 +649,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Nach Erstellungsdatum</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Nach Erstellungsdatum</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Nach Namen (Aufsteigend)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Nach Namen</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Nach Namen (Absteigend)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
@ -639,12 +663,14 @@
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Rücksetzmodus:</x:String> <x:String x:Key="Text.Reset.Mode" xml:space="preserve">Rücksetzmodus:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Verschiebe zu:</x:String> <x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Verschiebe zu:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Aktueller Branch:</x:String> <x:String x:Key="Text.Reset.Target" xml:space="preserve">Aktueller Branch:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">Reset Branch (ohne Checkout)</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">Auf:</x:String>
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Zeige im Datei-Explorer</x:String> <x:String x:Key="Text.RevealFile" xml:space="preserve">Zeige im Datei-Explorer</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Commit rückgängig machen</x:String> <x:String x:Key="Text.Revert" xml:space="preserve">Commit rückgängig machen</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit Änderungen rückgängig machen</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit Änderungen rückgängig machen</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Commit Nachricht umformulieren</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Commit Nachricht umformulieren</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Verwende 'Shift+Enter' um eine neue Zeile einzufügen. 'Enter' ist das Kürzel für den OK Button</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Bitte warten...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Bitte warten...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SPEICHERN</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SPEICHERN</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Speichern als...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Speichern als...</x:String>
@ -670,16 +696,15 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Pfad zum privaten SSH Schlüssel</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Pfad zum privaten SSH Schlüssel</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String> <x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Automatisch wiederherstellen nach dem Stashen</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Die Arbeitsdateien bleiben unverändert, aber ein Stash wird gespeichert.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Inklusive nicht-verfolgter Dateien</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Inklusive nicht-verfolgter Dateien</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Behalte gestagte Dateien</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Name:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name dieses Stashes</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Informationen zu dieses Stashes</x:String>
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">Modus:</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Nur gestagte Änderungen</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Nur gestagte Änderungen</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Gestagte und unstagte Änderungen der ausgewähleten Datei(en) werden gestasht!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Gestagte und unstagte Änderungen der ausgewähleten Datei(en) werden gestasht!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Lokale Änderungen stashen</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Lokale Änderungen stashen</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Anwenden</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Anwenden</x:String>
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Kopiere Nachricht</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Entfernen</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Entfernen</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Als Path speichern...</x:String> <x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Als Path speichern...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Stash entfernen</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Stash entfernen</x:String>
@ -698,11 +723,18 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULE</x:String> <x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULE</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Submodul hinzufügen</x:String> <x:String x:Key="Text.Submodule.Add" xml:space="preserve">Submodul hinzufügen</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Relativen Pfad kopieren</x:String> <x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Relativen Pfad kopieren</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">De-initialisiere Submodul</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Untergeordnete Submodule fetchen</x:String> <x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Untergeordnete Submodule fetchen</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Öffne Submodul Repository</x:String> <x:String x:Key="Text.Submodule.Open" xml:space="preserve">Öffne Submodul Repository</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relativer Pfad:</x:String> <x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relativer Pfad:</x:String>
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relativer Ordner um dieses Submodul zu speichern.</x:String> <x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relativer Ordner um dieses Submodul zu speichern.</x:String>
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Submodul löschen</x:String> <x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Submodul löschen</x:String>
<x:String x:Key="Text.Submodule.Status" xml:space="preserve">STATUS</x:String>
<x:String x:Key="Text.Submodule.Status.Modified" xml:space="preserve">geändert</x:String>
<x:String x:Key="Text.Submodule.Status.NotInited" xml:space="preserve">nicht initialisiert</x:String>
<x:String x:Key="Text.Submodule.Status.RevisionChanged" xml:space="preserve">Revision geändert</x:String>
<x:String x:Key="Text.Submodule.Status.Unmerged" xml:space="preserve">nicht gemerged</x:String>
<x:String x:Key="Text.Submodule.URL" xml:space="preserve">URL</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String> <x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Tag-Namen kopieren</x:String> <x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Tag-Namen kopieren</x:String>
<x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">Tag-Nachricht kopieren</x:String> <x:String x:Key="Text.TagCM.CopyMessage" xml:space="preserve">Tag-Nachricht kopieren</x:String>
@ -739,7 +771,7 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignoriere alle *{0} Dateien</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignoriere alle *{0} Dateien</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignoriere *{0} Datein im selben Ordner</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignoriere *{0} Datein im selben Ordner</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignoriere Dateien im selben Ordner</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">Ignoriere nicht-verfolgte Dateien in diesem Ordner</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignoriere nur diese Datei</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignoriere nur diese Datei</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Du kannst diese Datei jetzt stagen.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Du kannst diese Datei jetzt stagen.</x:String>
@ -759,6 +791,7 @@
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String> <x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String>
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Autor zurücksetzen</x:String>
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Rechtsklick auf selektierte Dateien und wähle die Konfliktlösungen aus.</x:String> <x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Rechtsklick auf selektierte Dateien und wähle die Konfliktlösungen aus.</x:String>
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">SignOff</x:String> <x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">SignOff</x:String>
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">GESTAGED</x:String> <x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">GESTAGED</x:String>
@ -767,7 +800,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGEN</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGEN</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ALLES STAGEN</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ALLES STAGEN</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">ARBEITSPLATZ: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">ARBEITSPLATZ: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Arbeitsplätze konfigurieren...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Arbeitsplätze konfigurieren...</x:String>

View file

@ -35,6 +35,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Load Image...</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String>
<x:String x:Key="Text.Bisect">Bisect</x:String> <x:String x:Key="Text.Bisect">Bisect</x:String>
<x:String x:Key="Text.Bisect.Abort">Abort</x:String> <x:String x:Key="Text.Bisect.Abort">Abort</x:String>
@ -84,6 +86,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Checkout &amp; Fast-Forward</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Fast-Forward to:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
@ -116,6 +120,7 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactively Rebase ${0}$ on Here</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactively Rebase ${0}$ on Here</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge to ${0}$</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge to ${0}$</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Merge ...</x:String> <x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Merge ...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">Push ${0}$ to ${1}$</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ on Here</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ on Here</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revert Commit</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revert Commit</x:String>
@ -438,6 +443,7 @@
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Workspaces</x:String> <x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Workspaces</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Pages</x:String> <x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Pages</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String> <x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Customize merge message</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Into:</x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Source:</x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">Source:</x:String>
@ -470,6 +476,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} months ago</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} months ago</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} years ago</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Yesterday</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Yesterday</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Use 'Shift+Enter' to input a new line. 'Enter' is the hotkey of OK button</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferences</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Preferences</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
@ -548,6 +555,8 @@
<x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch:</x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Push.Revision" xml:space="preserve">Revision:</x:String>
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">Push Revision To Remote</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Push Changes To Remote</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">Push Changes To Remote</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Remote Branch:</x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">Remote Branch:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Set as tracking branch</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">Set as tracking branch</x:String>
@ -561,7 +570,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
@ -637,8 +645,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">By Name (Ascending)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">By Name</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">By Name (Descending)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sort</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sort</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String>
@ -660,7 +667,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revert changes</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revert changes</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reword Commit Message</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Reword Commit Message</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Use 'Shift+Enter' to input a new line. 'Enter' is the hotkey of OK button</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Running. Please wait...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Running. Please wait...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SAVE</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SAVE</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Save As...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Save As...</x:String>
@ -686,16 +692,15 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String> <x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Auto-restore after stashing</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Your working files remain unchanged, but a stash is saved.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Keep staged files</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Message of this stash</x:String>
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">Mode:</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Only staged changes</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Only staged changes</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Both staged and unstaged changes of selected file(s) will be stashed!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Both staged and unstaged changes of selected file(s) will be stashed!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Local Changes</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Local Changes</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String>
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Copy Message</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String> <x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String>
@ -762,7 +767,7 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignore files in the same folder</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">Ignore untracked files in this folder</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignore this file only</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignore this file only</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
@ -791,7 +796,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE ALL</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE ALL</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VIEW ASSUME UNCHANGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VIEW ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configure Workspaces...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configure Workspaces...</x:String>

View file

@ -39,6 +39,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Cargar Imagen...</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Refrescar</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">¡ARCHIVO BINARIO NO SOPORTADO!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">¡ARCHIVO BINARIO NO SOPORTADO!</x:String>
<x:String x:Key="Text.Bisect">Bisect</x:String> <x:String x:Key="Text.Bisect">Bisect</x:String>
<x:String x:Key="Text.Bisect.Abort">Abortar</x:String> <x:String x:Key="Text.Bisect.Abort">Abortar</x:String>
@ -88,6 +90,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reaplicar</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Actualizar todos los submódulos</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Actualizar todos los submódulos</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Rama:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Rama:</x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Checkout &amp; Fast-Forward</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Fast-Forward a:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Añadir fuente al mensaje de commit</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Añadir fuente al mensaje de commit</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
@ -474,6 +478,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">Hace {0} meses</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">Hace {0} meses</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">Hace {0} años</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">Hace {0} años</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ayer</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ayer</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Usa 'Shift+Enter' para introducir una nueva línea. 'Enter' es el atajo del botón OK</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferencias</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Preferencias</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analizar Diff Prompt</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analizar Diff Prompt</x:String>
@ -565,7 +570,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reaplicar cambios locales</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reaplicar cambios locales</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">En:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">En:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refrescar</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Añadir Remoto</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Añadir Remoto</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nombre:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Nombre:</x:String>
@ -641,8 +645,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ETIQUETAS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">ETIQUETAS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUEVA ETIQUETA</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUEVA ETIQUETA</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Por Fecha de Creación</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Por Fecha de Creación</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Por Nombre (Ascendiente)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Por Nombre</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Por Nombre (Descendiente)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordenar</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordenar</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usar tiempo relativo en las historias</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usar tiempo relativo en las historias</x:String>
@ -664,7 +667,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revertir cambios</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revertir cambios</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reescribir Mensaje de Commit</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Reescribir Mensaje de Commit</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Usa 'Shift+Enter' para introducir una nueva línea. 'Enter' es el atajo del botón OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Ejecutando. Por favor espera...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Ejecutando. Por favor espera...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">GUARDAR</x:String> <x:String x:Key="Text.Save" xml:space="preserve">GUARDAR</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Guardar Como...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Guardar Como...</x:String>
@ -690,12 +692,9 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Ruta de almacenamiento de la clave privada SSH</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Ruta de almacenamiento de la clave privada SSH</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String> <x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Restaurar automáticamente después del stashing</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Tus archivos de trabajo permanecen sin cambios, pero se guarda un stash.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir archivos no rastreados</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir archivos no rastreados</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Mantener archivos staged</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensaje:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensaje:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opcional. Nombre de este stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opcional. Información de este stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo cambios staged</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo cambios staged</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">¡Tanto los cambios staged como los no staged de los archivos seleccionados serán stashed!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">¡Tanto los cambios staged como los no staged de los archivos seleccionados serán stashed!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Cambios Locales</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Cambios Locales</x:String>
@ -766,7 +765,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorar todos los archivos *{0}</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorar todos los archivos *{0}</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorar archivos *{0} en la misma carpeta</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorar archivos *{0} en la misma carpeta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignorar archivos en la misma carpeta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar solo este archivo</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar solo este archivo</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Enmendar</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Enmendar</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puedes hacer stage a este archivo ahora.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puedes hacer stage a este archivo ahora.</x:String>
@ -795,7 +793,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODO</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODO</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VER ASSUME UNCHANGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VER ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Plantilla: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Plantilla: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String>

View file

@ -39,6 +39,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">SUPPRIMER</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">SUPPRIMER</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Rafraîchir</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String>
@ -443,6 +444,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">il y a {0} mois</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">il y a {0} mois</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">il y a {0} ans</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">il y a {0} ans</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Hier</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Hier</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Utiliser 'Maj+Entrée' pour insérer une nouvelle ligne. 'Entrée' est la touche pour valider</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Préférences</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Préférences</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">IA</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">IA</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyser Diff Prompt</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyser Diff Prompt</x:String>
@ -532,7 +534,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; réappliquer changements locaux</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; réappliquer changements locaux</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Sur :</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">Sur :</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase :</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase :</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Rafraîchir</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Ajouter dépôt distant</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Ajouter dépôt distant</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifier dépôt distant</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifier dépôt distant</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nom :</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Nom :</x:String>
@ -602,8 +603,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NOUVEAU TAG</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NOUVEAU TAG</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Par date de créateur</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Par date de créateur</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Par nom (Croissant)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Par nom</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Par nom (Décroissant)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Trier</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Trier</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Ouvrir dans un terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Ouvrir dans un terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Utiliser le temps relatif dans les historiques</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Utiliser le temps relatif dans les historiques</x:String>
@ -620,7 +620,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit :</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit :</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit les changements de l'annulation</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit les changements de l'annulation</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reformuler le message de commit</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Reformuler le message de commit</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Utiliser 'Maj+Entrée' pour insérer une nouvelle ligne. 'Entrée' est la touche pour valider</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">En exécution. Veuillez patienter...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">En exécution. Veuillez patienter...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SAUVEGARDER</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SAUVEGARDER</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Sauvegarder en tant que...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Sauvegarder en tant que...</x:String>
@ -646,12 +645,9 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Chemin du magasin de clés privées SSH</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Chemin du magasin de clés privées SSH</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String> <x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Auto-restauration après le stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Vos fichiers de travail restent inchangés, mais une sauvegarde est enregistrée.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Inclure les fichiers non-suivis</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Inclure les fichiers non-suivis</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Garder les fichiers indexés</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Message :</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Message :</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optionnel. Nom de ce stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optionnel. Information de ce stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Seulement les changements indexés</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Seulement les changements indexés</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Les modifications indexées et non-indexées des fichiers sélectionnés seront stockées!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Les modifications indexées et non-indexées des fichiers sélectionnés seront stockées!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash les changements locaux</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash les changements locaux</x:String>
@ -711,7 +707,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorer tous les *{0} fichiers</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorer tous les *{0} fichiers</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorer *{0} fichiers dans le même dossier</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorer *{0} fichiers dans le même dossier</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignorer les fichiers dans le même dossier</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">N'ignorer que ce fichier</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">N'ignorer que ce fichier</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amender</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amender</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Vous pouvez indexer ce fichier.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Vous pouvez indexer ce fichier.</x:String>
@ -734,7 +729,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON INDEXÉ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON INDEXÉ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">INDEXER</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">INDEXER</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">INDEXER TOUT</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">INDEXER TOUT</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Modèle: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Modèle: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACE DE TRAVAIL : </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">ESPACE DE TRAVAIL : </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurer les espaces de travail...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurer les espaces de travail...</x:String>

View file

@ -39,6 +39,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILE ASSUNTI COME INVARIATI</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILE ASSUNTI COME INVARIATI</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NESSUN FILE ASSUNTO COME INVARIATO</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NESSUN FILE ASSUNTO COME INVARIATO</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">RIMUOVI</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">RIMUOVI</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Aggiorna</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FILE BINARIO NON SUPPORTATO!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FILE BINARIO NON SUPPORTATO!!!</x:String>
<x:String x:Key="Text.Bisect" xml:space="preserve">Biseca</x:String> <x:String x:Key="Text.Bisect" xml:space="preserve">Biseca</x:String>
<x:String x:Key="Text.Bisect.Abort" xml:space="preserve">Annulla</x:String> <x:String x:Key="Text.Bisect.Abort" xml:space="preserve">Annulla</x:String>
@ -463,6 +464,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} mesi fa</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} mesi fa</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} anni fa</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} anni fa</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ieri</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ieri</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Usa 'Shift+Enter' per inserire una nuova riga. 'Enter' è il tasto rapido per il pulsante OK</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferenze</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Preferenze</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analizza il Prompt Differenza</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analizza il Prompt Differenza</x:String>
@ -553,7 +555,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stasha e Riapplica modifiche locali</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stasha e Riapplica modifiche locali</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Su:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">Su:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Riallinea:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Riallinea:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Aggiorna</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Aggiungi Remoto</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Aggiungi Remoto</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifica Remoto</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifica Remoto</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
@ -628,8 +629,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAG</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAG</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUOVO TAG</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUOVO TAG</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Per data di creazione</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Per data di creazione</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Per nome (ascendente)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Per nome</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Per nome (discendente)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordina</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordina</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Apri nel Terminale</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Apri nel Terminale</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usa tempo relativo nello storico</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usa tempo relativo nello storico</x:String>
@ -648,7 +648,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit delle modifiche di ripristino</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit delle modifiche di ripristino</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Modifica Messaggio di Commit</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Modifica Messaggio di Commit</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Usa 'Shift+Enter' per inserire una nuova riga. 'Enter' è il tasto rapido per il pulsante OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">In esecuzione. Attendere...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">In esecuzione. Attendere...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SALVA</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SALVA</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Salva come...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Salva come...</x:String>
@ -674,12 +673,9 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Percorso per la chiave SSH privata</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Percorso per la chiave SSH privata</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">AVVIA</x:String> <x:String x:Key="Text.Start" xml:space="preserve">AVVIA</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stasha</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stasha</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Auto-ripristino dopo lo stash</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">I tuoi file di lavoro rimangono inalterati, ma viene salvato uno stash.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Includi file non tracciati</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Includi file non tracciati</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Mantieni file in stage</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Messaggio:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Messaggio:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opzionale. Nome di questo stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opzionale. Informazioni di questo stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo modifiche in stage</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo modifiche in stage</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Sia le modifiche in stage che quelle non in stage dei file selezionati saranno stashate!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Sia le modifiche in stage che quelle non in stage dei file selezionati saranno stashate!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stasha Modifiche Locali</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Stasha Modifiche Locali</x:String>
@ -749,7 +745,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignora tutti i file *{0}</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignora tutti i file *{0}</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignora i file *{0} nella stessa cartella</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignora i file *{0} nella stessa cartella</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignora i file nella stessa cartella</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignora solo questo file</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignora solo questo file</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Modifica</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Modifica</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puoi aggiungere in stage questo file ora.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puoi aggiungere in stage questo file ora.</x:String>
@ -777,7 +772,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON IN STAGE</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON IN STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">FAI LO STAGE</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">FAI LO STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">FAI LO STAGE DI TUTTO</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">FAI LO STAGE DI TUTTO</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VISUALIZZA COME NON MODIFICATO</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VISUALIZZA COME NON MODIFICATO</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE:</x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE:</x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Workspaces...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Workspaces...</x:String>

View file

@ -39,6 +39,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">変更されていないとみなされるファイル</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">変更されていないとみなされるファイル</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">変更されていないとみなされるファイルはありません</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">変更されていないとみなされるファイルはありません</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">削除</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">削除</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">更新</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">バイナリファイルはサポートされていません!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">バイナリファイルはサポートされていません!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAMEではこのファイルはサポートされていません!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAMEではこのファイルはサポートされていません!!!</x:String>
@ -442,6 +443,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} ヶ月前</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} ヶ月前</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨日</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨日</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">改行には'Shift+Enter'キーを使用します。 'Enter"はOKボタンのホットキーとして機能します。</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">設定</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">設定</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">差分分析プロンプト</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">差分分析プロンプト</x:String>
@ -531,7 +533,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">ローカルの変更をスタッシュして再適用</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">ローカルの変更をスタッシュして再適用</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">リベース:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">リベース:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">更新</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">リモートを追加</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">リモートを追加</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">リモートを編集</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">リモートを編集</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">名前:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">名前:</x:String>
@ -600,7 +601,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">タグ</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">タグ</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新しいタグを作成</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新しいタグを作成</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">作成者日時</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">作成者日時</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">名前 (昇順)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">名前</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">ソート</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">ソート</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">ターミナルで開く</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">ターミナルで開く</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">履歴に相対時間を使用</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">履歴に相対時間を使用</x:String>
@ -617,7 +618,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">コミット:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">コミット:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">コミットの変更を戻す</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">コミットの変更を戻す</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">コミットメッセージを書き直す</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">コミットメッセージを書き直す</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">改行には'Shift+Enter'キーを使用します。 'Enter"はOKボタンのホットキーとして機能します。</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">実行中です。しばらくお待ちください...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">実行中です。しばらくお待ちください...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">保存</x:String> <x:String x:Key="Text.Save" xml:space="preserve">保存</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">名前を付けて保存...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">名前を付けて保存...</x:String>
@ -643,12 +643,9 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">プライベートSSHキーストアのパス</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">プライベートSSHキーストアのパス</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">スタート</x:String> <x:String x:Key="Text.Start" xml:space="preserve">スタート</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">スタッシュ</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">スタッシュ</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">スタッシュ後に自動で復元</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">作業ファイルは変更されず、スタッシュが保存されます。</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">追跡されていないファイルを含める</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">追跡されていないファイルを含める</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">ステージされたファイルを保持</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">メッセージ:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">メッセージ:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">オプション. このスタッシュの名前を入力</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">オプション. このスタッシュの情報</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">ステージされた変更のみ</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">ステージされた変更のみ</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">選択したファイルの、ステージされた変更とステージされていない変更の両方がスタッシュされます!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">選択したファイルの、ステージされた変更とステージされていない変更の両方がスタッシュされます!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">ローカルの変更をスタッシュ</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">ローカルの変更をスタッシュ</x:String>
@ -708,7 +705,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">すべての*{0}ファイルを無視</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">すべての*{0}ファイルを無視</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">同じフォルダ内の*{0}ファイルを無視</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">同じフォルダ内の*{0}ファイルを無視</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">同じフォルダ内のファイルを無視</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">このファイルのみを無視</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">このファイルのみを無視</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">このファイルを今すぐステージできます。</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">このファイルを今すぐステージできます。</x:String>
@ -731,7 +727,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未ステージのファイル</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未ステージのファイル</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ステージへ移動</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ステージへ移動</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">すべてステージへ移動</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">すべてステージへ移動</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">変更されていないとみなしたものを表示</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">変更されていないとみなしたものを表示</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">テンプレート: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">テンプレート: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">ワークスペース: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">ワークスペース: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">ワークスペースを設定...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">ワークスペースを設定...</x:String>

View file

@ -33,6 +33,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Atualizar</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ARQUIVO BINÁRIO NÃO SUPORTADO!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ARQUIVO BINÁRIO NÃO SUPORTADO!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String>
@ -405,6 +406,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} meses atrás</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} meses atrás</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} anos atrás</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} anos atrás</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ontem</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Ontem</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Use 'Shift+Enter' para inserir uma nova linha. 'Enter' é a tecla de atalho do botão OK</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferências</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Preferências</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">INTELIGÊNCIA ARTIFICIAL</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">INTELIGÊNCIA ARTIFICIAL</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Prompt para Analisar Diff</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Prompt para Analisar Diff</x:String>
@ -488,7 +490,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Guardar &amp; reaplicar alterações locais</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Guardar &amp; reaplicar alterações locais</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Em:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">Em:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Atualizar</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Adicionar Remoto</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Adicionar Remoto</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
@ -563,7 +564,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commitar alterações de reversão</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commitar alterações de reversão</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reescrever Mensagem do Commit</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Reescrever Mensagem do Commit</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Use 'Shift+Enter' para inserir uma nova linha. 'Enter' é a tecla de atalho do botão OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Executando. Por favor, aguarde...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Executando. Por favor, aguarde...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SALVAR</x:String> <x:String x:Key="Text.Save" xml:space="preserve">SALVAR</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Salvar Como...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Salvar Como...</x:String>
@ -585,9 +585,8 @@
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String> <x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir arquivos não rastreados</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Incluir arquivos não rastreados</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Manter arquivos em stage</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensagem:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Mensagem:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opcional. Nome deste stash</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opcional. Informações deste stash</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Apenas mudanças em stage</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Apenas mudanças em stage</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Tanto mudanças em stage e fora de stage dos arquivos selecionados serão enviadas para stash!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Tanto mudanças em stage e fora de stage dos arquivos selecionados serão enviadas para stash!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Guardar Alterações Locais</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Guardar Alterações Locais</x:String>
@ -646,7 +645,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorar todos os arquivos *{0}</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignorar todos os arquivos *{0}</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorar arquivos *{0} na mesma pasta</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignorar arquivos *{0} na mesma pasta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignorar arquivos na mesma pasta</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar apenas este arquivo</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar apenas este arquivo</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Corrigir</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Corrigir</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Você pode stagear este arquivo agora.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Você pode stagear este arquivo agora.</x:String>
@ -667,7 +665,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODOS</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODOS</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VER SUPOR NÃO ALTERADO</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VER SUPOR NÃO ALTERADO</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">Workspaces: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">Workspaces: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurar workspaces...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurar workspaces...</x:String>

View file

@ -39,6 +39,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">СПИСОК ПУСТ</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">СПИСОК ПУСТ</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">УДАЛИТЬ</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">УДАЛИТЬ</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Загрузить картинку...</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Обновить</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
<x:String x:Key="Text.Bisect">Раздвоить</x:String> <x:String x:Key="Text.Bisect">Раздвоить</x:String>
<x:String x:Key="Text.Bisect.Abort">О</x:String> <x:String x:Key="Text.Bisect.Abort">О</x:String>
@ -50,6 +52,7 @@
<x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Переключиться на ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Переключиться на ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithCurrent" xml:space="preserve">Сравнить с ${0}$</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String> <x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String> <x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String>
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Изменить действие</x:String> <x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Изменить действие</x:String>
@ -87,6 +90,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Отложить и примненить повторно</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Отложить и примненить повторно</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Обновить все подкаталоги</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Обновить все подкаталоги</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Ветка:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Переключиться и перемотать</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Перемотать к:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve"> Частичный выбор</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve"> Частичный выбор</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Добавить источник для ревизии сообщения</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Добавить источник для ревизии сообщения</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Ревизия(и):</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Ревизия(и):</x:String>
@ -119,6 +124,7 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Интерактивное перемещение (rebase -i) ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Интерактивное перемещение (rebase -i) ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Влить в ${0}$</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Влить в ${0}$</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Влить ...</x:String> <x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Влить ...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">Выложить ${0}$ в ${1}$</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Переместить ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Переместить ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Сбросить ${0}$ сюда</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Сбросить ${0}$ сюда</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Отменить ревизию</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Отменить ревизию</x:String>
@ -441,6 +447,7 @@
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Рабочие места</x:String> <x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Рабочие места</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Страницы</x:String> <x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Страницы</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Влить ветку</x:String> <x:String x:Key="Text.Merge" xml:space="preserve">Влить ветку</x:String>
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Изменить сообщение слияния</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">В:</x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">В:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Опции слияния:</x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">Опции слияния:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Источник:</x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">Источник:</x:String>
@ -473,6 +480,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} месяцев назад</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} месяцев назад</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} лет назад</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} лет назад</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Вчера</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Вчера</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Используйте «Shift+Enter» для ввода новой строки. «Enter» - это горячая клавиша кнопки «OK»</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Параметры</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Параметры</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">ОТКРЫТЬ ИИ</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">ОТКРЫТЬ ИИ</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Запрос на анализ сравнения</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Запрос на анализ сравнения</x:String>
@ -551,6 +559,8 @@
<x:String x:Key="Text.Push.Force" xml:space="preserve">Принудительно выложить</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">Принудительно выложить</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Локальная ветка:</x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">Локальная ветка:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Внешний репозиторий:</x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">Внешний репозиторий:</x:String>
<x:String x:Key="Text.Push.Revision" xml:space="preserve">Ревизия:</x:String>
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">Выложить ревизию на удалёную</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Выложить изменения на внешний репозиторий</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">Выложить изменения на внешний репозиторий</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Ветка внешнего репозитория:</x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">Ветка внешнего репозитория:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Отслеживать ветку</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">Отслеживать ветку</x:String>
@ -564,7 +574,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Отложить и применить повторно локальные изменения</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Отложить и применить повторно локальные изменения</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Переместить:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Переместить:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Обновить</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Добавить внешний репозиторий</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Добавить внешний репозиторий</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редактировать внешний репозиторий</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редактировать внешний репозиторий</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Имя:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Имя:</x:String>
@ -592,6 +601,7 @@
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Очистить</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка репозитория</x:String> <x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка репозитория</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String> <x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Изменить действия</x:String> <x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Изменить действия</x:String>
@ -639,8 +649,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">МЕТКИ</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">МЕТКИ</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВАЯ МЕТКА</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВАЯ МЕТКА</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">По дате создания</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">По дате создания</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">По имени (по возрастанию)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">По имени</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">По имени (по убыванию)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String>
@ -662,7 +671,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Ревизия:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Ревизия:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Отмена ревизии</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Отмена ревизии</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Изменить комментарий ревизии</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Изменить комментарий ревизии</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Используйте «Shift+Enter» для ввода новой строки. «Enter» - это горячая клавиша кнопки «OK»</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Запуск. Подождите пожалуйста...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Запуск. Подождите пожалуйста...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">СОХРАНИТЬ</x:String> <x:String x:Key="Text.Save" xml:space="preserve">СОХРАНИТЬ</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Сохранить как...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Сохранить как...</x:String>
@ -688,16 +696,15 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Путь хранения приватного ключа SSH</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Путь хранения приватного ключа SSH</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">ЗАПУСК</x:String> <x:String x:Key="Text.Start" xml:space="preserve">ЗАПУСК</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Отложить</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Отложить</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Автоматически восстанавливать после откладывания</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Ваши рабочие файлы остаются неизменными, но отложенные сохранятся.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включить неотслеживаемые файлы</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включить неотслеживаемые файлы</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Хранить отложенные файлы</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Сообщение:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Сообщение:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Имя тайника (необязательно)</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Имя тайника (необязательно)</x:String>
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">Режим:</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Только сформированные изменения</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Только сформированные изменения</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Сформированные так и несформированные изменения выбранных файлов будут сохранены!!!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Сформированные так и несформированные изменения выбранных файлов будут сохранены!!!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Отложить локальные изменения</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Отложить локальные изменения</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Принять</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Принять</x:String>
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Копировать сообщение</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Отбросить</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Отбросить</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Сохранить как заплатку...</x:String> <x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Сохранить как заплатку...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Отбросить тайник</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Отбросить тайник</x:String>
@ -764,7 +771,7 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Игнорировать Git</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Игнорировать Git</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Игнорировать все *{0} файлы</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Игнорировать все *{0} файлы</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Игнорировать *{0} файлы в том же каталоге</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Игнорировать *{0} файлы в том же каталоге</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Игнорировать файлы в том же каталоге</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">Игнорировать неотслеживаемые файлы в этом каталоге</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Игнорировать только эти файлы</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Игнорировать только эти файлы</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Изменить</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Изменить</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Теперь вы можете сформировать этот файл.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Теперь вы можете сформировать этот файл.</x:String>
@ -784,6 +791,7 @@
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String> <x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">НЕТ ШАБЛОНОВ РЕВИЗИИ</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">НЕТ ШАБЛОНОВ РЕВИЗИИ</x:String>
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Сбросить автора</x:String>
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Щёлкните правой кнопкой мыши выбранный файл(ы) и разрешите конфликты.</x:String> <x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Щёлкните правой кнопкой мыши выбранный файл(ы) и разрешите конфликты.</x:String>
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Завершение работы</x:String> <x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Завершение работы</x:String>
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">СФОРМИРОВАННЫЕ</x:String> <x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">СФОРМИРОВАННЫЕ</x:String>
@ -792,7 +800,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕСФОРМИРОВАННЫЕ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕСФОРМИРОВАННЫЕ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">СФОРМИРОВАТЬ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">СФОРМИРОВАТЬ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">СФОРМИРОВАТЬ ВСЁ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">СФОРМИРОВАТЬ ВСЁ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">РАБОЧЕЕ ПРОСТРАНСТВО: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">РАБОЧЕЕ ПРОСТРАНСТВО: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Настройка рабочего пространства...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Настройка рабочего пространства...</x:String>

View file

@ -39,6 +39,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">நீக்கு</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">நீக்கு</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">புதுப்பி</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">குற்றச்சாட்டு</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">குற்றச்சாட்டு</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!</x:String>
@ -442,6 +443,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} திங்களுக்கு முன்பு</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} திங்களுக்கு முன்பு</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} ஆண்டுகளுக்கு முன்பு</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} ஆண்டுகளுக்கு முன்பு</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">நேற்று</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">நேற்று</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">புதிய வரியை உள்ளிட 'உயர்த்து+நுழை' ஐப் பயன்படுத்தவும். 'நுழை' என்பது சரி பொத்தானின் சூடானவிசை ஆகும்</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">விருப்பத்தேர்வுகள்</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">விருப்பத்தேர்வுகள்</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">செநு</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">செநு</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">வேறுபாடு உடனடியாக பகுப்பாய்வு செய்</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">வேறுபாடு உடனடியாக பகுப்பாய்வு செய்</x:String>
@ -531,7 +533,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">உள்ளக மாற்றங்களை பதுக்கிவை &amp; மீண்டும் இடு</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">உள்ளக மாற்றங்களை பதுக்கிவை &amp; மீண்டும் இடு</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">மேல்:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">மேல்:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">மறுதளம்:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">மறுதளம்:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">புதுப்பி</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">தொலையைச் சேர்</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">தொலையைச் சேர்</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">தொலையைத் திருத்து</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">தொலையைத் திருத்து</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">பெயர்:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">பெயர்:</x:String>
@ -601,8 +602,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">குறிசொற்கள்</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">குறிசொற்கள்</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">புதிய குறிசொல்</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">புதிய குறிசொல்</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">படைப்பாளர் தேதியின்படி</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">படைப்பாளர் தேதியின்படி</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">பெயர் (ஏறுவரிசை) மூலம்</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">பெயர் மூலம்</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">பெயர் (இறகுவரிசை) மூலம்</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">வரிசைப்படுத்து</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">வரிசைப்படுத்து</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">முனையத்தில் திற</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">முனையத்தில் திற</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">வரலாறுகளில் உறவு நேரத்தைப் பயன்படுத்து</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">வரலாறுகளில் உறவு நேரத்தைப் பயன்படுத்து</x:String>
@ -619,7 +619,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">உறுதிமொழி:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">உறுதிமொழி:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">பின்வாங்கு மாற்றங்களை உறுதிமொழி</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">பின்வாங்கு மாற்றங்களை உறுதிமொழி</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">மாறுசொல் உறுதிமொழி செய்தி</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">மாறுசொல் உறுதிமொழி செய்தி</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">புதிய வரியை உள்ளிட 'உயர்த்து+நுழை' ஐப் பயன்படுத்தவும். 'நுழை' என்பது சரி பொத்தானின் சூடானவிசை ஆகும்</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">இயங்குகிறது. காத்திருக்கவும்...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">இயங்குகிறது. காத்திருக்கவும்...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">சேமி</x:String> <x:String x:Key="Text.Save" xml:space="preserve">சேமி</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">எனச் சேமி...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">எனச் சேமி...</x:String>
@ -645,10 +644,7 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">தனியார் பாஓடு திறவுகோல் கடை பாதை</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">தனியார் பாஓடு திறவுகோல் கடை பாதை</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">தொடங்கு</x:String> <x:String x:Key="Text.Start" xml:space="preserve">தொடங்கு</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">பதுக்கிவை</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">பதுக்கிவை</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">பதுக்கிவைத்த பிறகு தானியங்கி மீட்டமை</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">உங்கள் செயல்படும் கோப்புகள் மாறாமல் இருக்கும், ஆனால் ஒரு பதுக்கிவைக்கப்படும்.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">கண்காணிக்கப்படாத கோப்புகளைச் சேர்</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">கண்காணிக்கப்படாத கோப்புகளைச் சேர்</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">நிலைப்படுத்தப்பட்ட கோப்புகளை வைத்திரு</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">செய்தி:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">செய்தி:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">விருப்பத்தேர்வு. இந்த பதுக்கலின் பெயர்</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">விருப்பத்தேர்வு. இந்த பதுக்கலின் பெயர்</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">நிலைப்படுத்தப்பட்ட மாற்றங்கள் மட்டும்</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">நிலைப்படுத்தப்பட்ட மாற்றங்கள் மட்டும்</x:String>
@ -709,7 +705,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">அறிவிலி புறக்கணி</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">அறிவிலி புறக்கணி</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">எல்லா *{0} கோப்புகளையும் புறக்கணி</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">எல்லா *{0} கோப்புகளையும் புறக்கணி</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">ஒரே கோப்புறையில் *{0} கோப்புகளைப் புறக்கணி</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">ஒரே கோப்புறையில் *{0} கோப்புகளைப் புறக்கணி</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">ஒரே கோப்புறையில் கோப்புகளைப் புறக்கணி</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">இந்த கோப்பை மட்டும் புறக்கணி</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">இந்த கோப்பை மட்டும் புறக்கணி</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">பின்னொட்டு</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">பின்னொட்டு</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">இந்த கோப்பை இப்போது நீங்கள் நிலைப்படுத்தலாம்.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">இந்த கோப்பை இப்போது நீங்கள் நிலைப்படுத்தலாம்.</x:String>
@ -733,7 +728,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">நிலைநீக்கு</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">நிலைநீக்கு</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">நிலைபடுத்து</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">நிலைபடுத்து</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">அனைத்தும் நிலைபடுத்து</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">அனைத்தும் நிலைபடுத்து</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">மாறாதது எனநினைப்பதை பார்</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">மாறாதது எனநினைப்பதை பார்</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">வளர்புரு: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">வளர்புரு: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">பணியிடம்:</x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">பணியிடம்:</x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">பணியிடங்களை உள்ளமை...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">பணியிடங்களை உள்ளமை...</x:String>

View file

@ -39,6 +39,7 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ВИДАЛИТИ</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ВИДАЛИТИ</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Оновити</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Автор рядка</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Автор рядка</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
@ -447,6 +448,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} місяців тому</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} місяців тому</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} років тому</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} років тому</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Вчора</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Вчора</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">Використовуйте 'Shift+Enter' для введення нового рядка. 'Enter' - гаряча клавіша кнопки OK</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">Налаштування</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">Налаштування</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Промпт для аналізу різниці</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Промпт для аналізу різниці</x:String>
@ -536,7 +538,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Сховати та застосувати локальні зміни</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Сховати та застосувати локальні зміни</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Перебазувати:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">Перебазувати:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Оновити</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Додати віддалене сховище</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Додати віддалене сховище</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редагувати віддалене сховище</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редагувати віддалене сховище</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Назва:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">Назва:</x:String>
@ -606,8 +607,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ТЕГИ</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">ТЕГИ</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВИЙ ТЕГ</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВИЙ ТЕГ</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">За датою створення</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">За датою створення</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">За назвою (за зростанням)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">За назвою</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">За назвою (за спаданням)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортувати</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортувати</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Відкрити в терміналі</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Відкрити в терміналі</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Використовувати відносний час в історії</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Використовувати відносний час в історії</x:String>
@ -624,7 +624,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Коміт:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">Коміт:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Закомітити зміни скасування</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Закомітити зміни скасування</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Змінити повідомлення коміту</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">Змінити повідомлення коміту</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Використовуйте 'Shift+Enter' для введення нового рядка. 'Enter' - гаряча клавіша кнопки OK</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Виконується. Будь ласка, зачекайте...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">Виконується. Будь ласка, зачекайте...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">ЗБЕРЕГТИ</x:String> <x:String x:Key="Text.Save" xml:space="preserve">ЗБЕРЕГТИ</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Зберегти як...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">Зберегти як...</x:String>
@ -650,10 +649,7 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Шлях до сховища приватного ключа SSH</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Шлях до сховища приватного ключа SSH</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">ПОЧАТИ</x:String> <x:String x:Key="Text.Start" xml:space="preserve">ПОЧАТИ</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash (Сховати)</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">Stash (Сховати)</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">Автоматично відновити після схову</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">Ваші робочі файли залишаться без змін, але буде збережено схованку.</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включити невідстежувані файли</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Включити невідстежувані файли</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">Зберегти проіндексовані файли</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Повідомлення:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">Повідомлення:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Необов'язково. Назва цієї схованки</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Необов'язково. Назва цієї схованки</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Лише проіндексовані зміни</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Лише проіндексовані зміни</x:String>
@ -715,7 +711,6 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ігнорувати всі файли *{0}</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ігнорувати всі файли *{0}</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ігнорувати файли *{0} у цій же теці</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ігнорувати файли *{0} у цій же теці</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ігнорувати файли у цій же теці</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ігнорувати лише цей файл</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ігнорувати лише цей файл</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend (Доповнити)</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend (Доповнити)</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Тепер ви можете проіндексувати цей файл.</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Тепер ви можете проіндексувати цей файл.</x:String>
@ -743,7 +738,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕПРОІНДЕКСОВАНІ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕПРОІНДЕКСОВАНІ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ІНДЕКСУВАТИ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ІНДЕКСУВАТИ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ІНДЕКСУВАТИ ВСЕ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ІНДЕКСУВАТИ ВСЕ</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">РОБОЧИЙ ПРОСТІР: </x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">РОБОЧИЙ ПРОСТІР: </x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Налаштувати робочі простори...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Налаштувати робочі простори...</x:String>

View file

@ -39,6 +39,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不跟踪更改的文件</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不跟踪更改的文件</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">没有不跟踪更改的文件</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">没有不跟踪更改的文件</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">加载本地图片</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">重新加载</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String>
<x:String x:Key="Text.Bisect">二分定位(bisect)</x:String> <x:String x:Key="Text.Bisect">二分定位(bisect)</x:String>
<x:String x:Key="Text.Bisect.Abort">终止</x:String> <x:String x:Key="Text.Bisect.Abort">终止</x:String>
@ -88,6 +90,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 </x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">检出分支并快进</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">上游分支 </x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表 </x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表 </x:String>
@ -120,6 +124,7 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">合并(merge)此提交至 ${0}$</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">合并(merge)此提交至 ${0}$</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">合并(merge)...</x:String> <x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">合并(merge)...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">推送(push) ${0}$ 到 ${1}$</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滚此提交</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">回滚此提交</x:String>
@ -442,6 +447,7 @@
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作区列表</x:String> <x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作区列表</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">页面列表</x:String> <x:String x:Key="Text.Launcher.Pages" xml:space="preserve">页面列表</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String> <x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">编辑合并信息</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">目标分支 </x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">合并方式 </x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">合并方式 </x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">合并目标 </x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">合并目标 </x:String>
@ -474,6 +480,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0}个月前</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0}个月前</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0}年前</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨天</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨天</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">请使用Shift+Enter换行。Enter键已被【确 定】按钮占用。</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">偏好设置</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">偏好设置</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">Analyze Diff Prompt</x:String>
@ -552,6 +559,8 @@
<x:String x:Key="Text.Push.Force" xml:space="preserve">启用强制推送</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">启用强制推送</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">本地分支 </x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">本地分支 </x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">远程仓库 </x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">远程仓库 </x:String>
<x:String x:Key="Text.Push.Revision" xml:space="preserve">修订 </x:String>
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">推送指定修订到远程仓库</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">推送到远程仓库</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">推送到远程仓库</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">远程分支 </x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">远程分支 </x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">跟踪远程分支</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">跟踪远程分支</x:String>
@ -565,7 +574,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自动贮藏并恢复本地变更</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自动贮藏并恢复本地变更</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目标提交 </x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">目标提交 </x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支 </x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支 </x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">重新加载</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">添加远程仓库</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">添加远程仓库</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">编辑远程仓库</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">编辑远程仓库</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">远程名 </x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">远程名 </x:String>
@ -641,8 +649,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">标签列表</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">标签列表</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新建标签</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新建标签</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">按创建时间</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">按创建时间</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">按名称(升序)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">按名称</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">按名称(降序)</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String>
@ -664,7 +671,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">目标提交 </x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">目标提交 </x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">回滚后提交更改</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">回滚后提交更改</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">编辑提交信息</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">编辑提交信息</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">请使用Shift+Enter换行。Enter键已被【确 定】按钮占用。</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">执行操作中,请耐心等待...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">执行操作中,请耐心等待...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">保 存</x:String> <x:String x:Key="Text.Save" xml:space="preserve">保 存</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">另存为...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">另存为...</x:String>
@ -690,16 +696,15 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">SSH密钥文件</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">SSH密钥文件</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">开 始</x:String> <x:String x:Key="Text.Start" xml:space="preserve">开 始</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">贮藏(stash)</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">贮藏(stash)</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">贮藏后自动恢复工作区</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">工作区文件保持未修改状态,但贮藏内容已保存。</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未跟踪的文件</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未跟踪的文件</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">保留暂存区文件</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">信息 </x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">信息 </x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">选填,用于命名此贮藏</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">选填,此贮藏的描述信息</x:String>
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">模式 </x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">仅贮藏暂存区的变更</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">仅贮藏暂存区的变更</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">选中文件的所有变更均会被贮藏!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">选中文件的所有变更均会被贮藏!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">贮藏本地变更</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">贮藏本地变更</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">应用(apply)</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">应用(apply)</x:String>
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">复制描述信息</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">删除(drop)</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">删除(drop)</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存为补丁...</x:String> <x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存为补丁...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">丢弃贮藏确认</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">丢弃贮藏确认</x:String>
@ -766,7 +771,7 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略列表</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略列表</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 文件</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同目录下所有 *{0} 文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同目录下所有 *{0} 文件</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同目录下所有文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">忽略该目录下的新文件</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本文件</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本文件</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修补</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修补</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String>
@ -795,7 +800,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暂存</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暂存</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暂存选中</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暂存选中</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暂存所有</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暂存所有</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">查看忽略变更文件</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">查看忽略变更文件</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">模板:${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">模板:${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">工作区:</x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">工作区:</x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">配置工作区...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">配置工作区...</x:String>

View file

@ -39,6 +39,8 @@
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不追蹤變更的檔案</x:String> <x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不追蹤變更的檔案</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">沒有不追蹤變更的檔案</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">沒有不追蹤變更的檔案</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">載入本機圖片...</x:String>
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">重新載入</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位檔案不支援該操作!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位檔案不支援該操作!</x:String>
<x:String x:Key="Text.Bisect">二分搜尋 (bisect)</x:String> <x:String x:Key="Text.Bisect">二分搜尋 (bisect)</x:String>
<x:String x:Key="Text.Bisect.Abort">中止</x:String> <x:String x:Key="Text.Bisect.Abort">中止</x:String>
@ -88,6 +90,8 @@
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String> <x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">簽出分支並快轉</x:String>
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">上游分支 </x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表:</x:String> <x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表:</x:String>
@ -120,6 +124,7 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">合併 (merge) 此提交到 ${0}$</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">合併 (merge) 此提交到 ${0}$</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">合併 (merge)...</x:String> <x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">合併 (merge)...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">推送(push) ${0}$ 至 ${1}$</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String> <x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">復原此提交</x:String> <x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">復原此提交</x:String>
@ -442,6 +447,7 @@
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作區列表</x:String> <x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作區列表</x:String>
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">頁面列表</x:String> <x:String x:Key="Text.Launcher.Pages" xml:space="preserve">頁面列表</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String> <x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">編輯合併訊息</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">目標分支:</x:String> <x:String x:Key="Text.Merge.Into" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">合併方式:</x:String> <x:String x:Key="Text.Merge.Mode" xml:space="preserve">合併方式:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">合併來源:</x:String> <x:String x:Key="Text.Merge.Source" xml:space="preserve">合併來源:</x:String>
@ -474,6 +480,7 @@
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} 個月前</x:String> <x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">{0} 個月前</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String> <x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">{0} 年前</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨天</x:String> <x:String x:Key="Text.Period.Yesterday" xml:space="preserve">昨天</x:String>
<x:String x:Key="Text.PopupEnterKeyTip" xml:space="preserve">請使用 Shift + Enter 換行。Enter 鍵已被 [確定] 按鈕佔用。</x:String>
<x:String x:Key="Text.Preferences" xml:space="preserve">偏好設定</x:String> <x:String x:Key="Text.Preferences" xml:space="preserve">偏好設定</x:String>
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String> <x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
<x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String> <x:String x:Key="Text.Preferences.AI.AnalyzeDiffPrompt" xml:space="preserve">分析變更差異提示詞</x:String>
@ -552,6 +559,8 @@
<x:String x:Key="Text.Push.Force" xml:space="preserve">啟用強制推送</x:String> <x:String x:Key="Text.Push.Force" xml:space="preserve">啟用強制推送</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">本機分支:</x:String> <x:String x:Key="Text.Push.Local" xml:space="preserve">本機分支:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">遠端存放庫:</x:String> <x:String x:Key="Text.Push.Remote" xml:space="preserve">遠端存放庫:</x:String>
<x:String x:Key="Text.Push.Revision" xml:space="preserve">修訂:</x:String>
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">推送修訂到遠端存放庫</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">推送到遠端存放庫</x:String> <x:String x:Key="Text.Push.Title" xml:space="preserve">推送到遠端存放庫</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">遠端分支:</x:String> <x:String x:Key="Text.Push.To" xml:space="preserve">遠端分支:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">追蹤遠端分支</x:String> <x:String x:Key="Text.Push.Tracking" xml:space="preserve">追蹤遠端分支</x:String>
@ -565,7 +574,6 @@
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自動擱置變更並復原本機變更</x:String> <x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自動擱置變更並復原本機變更</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目標提交:</x:String> <x:String x:Key="Text.Rebase.On" xml:space="preserve">目標提交:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支:</x:String> <x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">重新載入</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">新增遠端存放庫</x:String> <x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">新增遠端存放庫</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">編輯遠端存放庫</x:String> <x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">編輯遠端存放庫</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">遠端名稱:</x:String> <x:String x:Key="Text.Remote.Name" xml:space="preserve">遠端名稱:</x:String>
@ -641,8 +649,7 @@
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">標籤列表</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">標籤列表</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新增標籤</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新增標籤</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">依建立時間</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">依建立時間</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">依名稱升序</x:String> <x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">依名稱</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">依名稱降序</x:String>
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String>
@ -664,7 +671,6 @@
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">目標提交:</x:String> <x:String x:Key="Text.Revert.Commit" xml:space="preserve">目標提交:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">復原後提交變更</x:String> <x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">復原後提交變更</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">編輯提交訊息</x:String> <x:String x:Key="Text.Reword" xml:space="preserve">編輯提交訊息</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">請使用 Shift + Enter 換行。Enter 鍵已被 [確定] 按鈕佔用。</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">執行操作中,請耐心等待...</x:String> <x:String x:Key="Text.Running" xml:space="preserve">執行操作中,請耐心等待...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">儲存</x:String> <x:String x:Key="Text.Save" xml:space="preserve">儲存</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">另存新檔...</x:String> <x:String x:Key="Text.SaveAs" xml:space="preserve">另存新檔...</x:String>
@ -690,16 +696,15 @@
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">SSH 金鑰檔案</x:String> <x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">SSH 金鑰檔案</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">開 始</x:String> <x:String x:Key="Text.Start" xml:space="preserve">開 始</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">擱置變更 (stash)</x:String> <x:String x:Key="Text.Stash" xml:space="preserve">擱置變更 (stash)</x:String>
<x:String x:Key="Text.Stash.AutoRestore" xml:space="preserve">擱置變更後自動復原工作區</x:String>
<x:String x:Key="Text.Stash.AutoRestore.Tip" xml:space="preserve">工作區檔案保持未修改,但擱置內容已儲存。</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未追蹤的檔案</x:String> <x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">包含未追蹤的檔案</x:String>
<x:String x:Key="Text.Stash.KeepIndex" xml:space="preserve">保留已暫存的變更</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">擱置變更訊息:</x:String> <x:String x:Key="Text.Stash.Message" xml:space="preserve">擱置變更訊息:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">選填,用於命名此擱置變更</x:String> <x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">選填,用於描述此擱置變更</x:String>
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">操作模式:</x:String>
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">僅擱置已暫存的變更</x:String> <x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">僅擱置已暫存的變更</x:String>
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">已選取的檔案中的變更均會被擱置!</x:String> <x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">已選取的檔案中的變更均會被擱置!</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">擱置本機變更</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">擱置本機變更</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">套用 (apply)</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">套用 (apply)</x:String>
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">複製描述訊息</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">刪除 (drop)</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">刪除 (drop)</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存為修補檔 (patch)...</x:String> <x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">另存為修補檔 (patch)...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">捨棄擱置變更確認</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">捨棄擱置變更確認</x:String>
@ -766,7 +771,7 @@
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">加入至 .gitignore 忽略清單</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">加入至 .gitignore 忽略清單</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 檔案</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同路徑下所有 *{0} 檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同路徑下所有 *{0} 檔案</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同路徑下所有檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">忽略本路徑下的新增檔案</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本檔案</x:String> <x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本檔案</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修補</x:String> <x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修補</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String> <x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String>
@ -795,7 +800,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暫存</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暫存</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暫存選取的檔案</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暫存選取的檔案</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暫存所有檔案</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暫存所有檔案</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">檢視不追蹤變更的檔案</x:String> <x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">檢視不追蹤變更的檔案</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">範本: ${0}$</x:String> <x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">範本: ${0}$</x:String>
<x:String x:Key="Text.Workspace" xml:space="preserve">工作區:</x:String> <x:String x:Key="Text.Workspace" xml:space="preserve">工作區:</x:String>
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">設定工作區...</x:String> <x:String x:Key="Text.Workspace.Configure" xml:space="preserve">設定工作區...</x:String>

View file

@ -16,7 +16,7 @@
<Style.Resources> <Style.Resources>
<x:Double x:Key="ScrollBarSize">12</x:Double> <x:Double x:Key="ScrollBarSize">12</x:Double>
</Style.Resources> </Style.Resources>
<Setter Property="ShowDelay" Value="0:0:0.1"/> <Setter Property="ShowDelay" Value="0:0:0.1"/>
<Setter Property="HideDelay" Value="0:0:0.2"/> <Setter Property="HideDelay" Value="0:0:0.2"/>
</Style> </Style>
@ -38,7 +38,7 @@
<Setter Property="BorderThickness" Value="0"/> <Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/> <Setter Property="Padding" Value="0"/>
</Style> </Style>
<Style Selector="Window[WindowState=Maximized].fix_maximized_padding"> <Style Selector="Window[WindowState=Maximized].fix_maximized_padding">
<Setter Property="Padding" Value="8,6,8,8"/> <Setter Property="Padding" Value="8,6,8,8"/>
</Style> </Style>
@ -206,7 +206,7 @@
<DropShadowEffect OffsetX="0" OffsetY="0" BlurRadius="4" Color="Black" Opacity=".6"/> <DropShadowEffect OffsetX="0" OffsetY="0" BlurRadius="4" Color="Black" Opacity=".6"/>
</Border.Effect> </Border.Effect>
</Border> </Border>
<Border Name="LayoutRoot" <Border Name="LayoutRoot"
Margin="4" Margin="4"
Padding="12" Padding="12"
@ -318,7 +318,7 @@
<Setter Property="Foreground" Value="DarkOrange"/> <Setter Property="Foreground" Value="DarkOrange"/>
<Setter Property="TextDecorations" Value="Underline"/> <Setter Property="TextDecorations" Value="Underline"/>
</Style> </Style>
<Style Selector="SelectableTextBlock"> <Style Selector="SelectableTextBlock">
<Setter Property="HorizontalAlignment" Value="Left"/> <Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/>
@ -336,7 +336,7 @@
<Path Width="11" Height="11" Data="{StaticResource Icons.Copy}" VerticalAlignment="Center"/> <Path Width="11" Height="11" Data="{StaticResource Icons.Copy}" VerticalAlignment="Center"/>
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="{DynamicResource Text.CopyAllText}" <MenuItem Header="{DynamicResource Text.CopyAllText}"
Command="{x:Static s:App.CopyTextBlockCommand}" Command="{x:Static s:App.CopyTextBlockCommand}"
CommandParameter="{Binding $parent[SelectableTextBlock]}"> CommandParameter="{Binding $parent[SelectableTextBlock]}">
@ -524,18 +524,12 @@
<Style Selector="Button.flat.primary ToolTip TextBlock"> <Style Selector="Button.flat.primary ToolTip TextBlock">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/> <Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
</Style> </Style>
<Style Selector="SplitButton"> <Style Selector="SplitButton">
<Setter Property="MinHeight" Value="24"/> <Setter Property="MinHeight" Value="24"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid> <Grid ColumnDefinitions="*,1,Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="PART_PrimaryButton" <Button x:Name="PART_PrimaryButton"
Grid.Column="0" Grid.Column="0"
Classes="flat primary" Classes="flat primary"
@ -569,17 +563,17 @@
</Grid> </Grid>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^:disabled /template/ Button"> <Style Selector="^:disabled /template/ Button">
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border2}"/> <Setter Property="BorderBrush" Value="{DynamicResource Brush.Border2}"/>
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
</Style> </Style>
<Style Selector="^:disabled TextBlock"> <Style Selector="^:disabled TextBlock">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/> <Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
</Style> </Style>
<Style Selector="^:disabled Path"> <Style Selector="^:disabled Path">
<Setter Property="Fill" Value="{DynamicResource Brush.FG2}"/> <Setter Property="Fill" Value="{DynamicResource Brush.FG2}"/>
</Style> </Style>
@ -737,7 +731,7 @@
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" /> <Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".8"/> <Setter Property="Opacity" Value=".8"/>
</Style> </Style>
</Style> </Style>
<Style Selector="ContextMenu"> <Style Selector="ContextMenu">
<Setter Property="HorizontalOffset" Value="-4"/> <Setter Property="HorizontalOffset" Value="-4"/>
@ -843,9 +837,13 @@
<DataTemplate DataType="x:String"> <DataTemplate DataType="x:String">
<v:NameHighlightedTextBlock Text="{Binding}" VerticalAlignment="Center"/> <v:NameHighlightedTextBlock Text="{Binding}" VerticalAlignment="Center"/>
</DataTemplate> </DataTemplate>
<DataTemplate DataType="vm:FilterModeInGraph">
<v:FilterModeInGraph/>
</DataTemplate>
</ContentPresenter.DataTemplates> </ContentPresenter.DataTemplates>
</ContentPresenter> </ContentPresenter>
<TextBlock x:Name="PART_InputGestureText" <TextBlock x:Name="PART_InputGestureText"
Grid.Column="2" Grid.Column="2"
Classes="CaptionTextBlockStyle" Classes="CaptionTextBlockStyle"
@ -867,7 +865,7 @@
Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}" Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"
FontSize="11" FontSize="11"
IsVisible="{TemplateBinding (v:MenuItemExtension.Command), Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/> IsVisible="{TemplateBinding (v:MenuItemExtension.Command), Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Path Name="PART_ChevronPath" <Path Name="PART_ChevronPath"
Width="6" Width="6"
Data="M573 512 215 881c-20 20-20 51 0 61l61 61c20 20 51 20 61 0l461-461c10-10 10-20 10-31s0-20-10-31L338 20C317 0 287 0 276 20L215 82c-20 20-20 51 0 61L573 512z" Data="M573 512 215 881c-20 20-20 51 0 61l61 61c20 20 51 20 61 0l461-461c10-10 10-20 10-31s0-20-10-31L338 20C317 0 287 0 276 20L215 82c-20 20-20 51 0 61L573 512z"
@ -910,7 +908,7 @@
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^:icon /template/ ContentControl#PART_IconPresenter"> <Style Selector="^:icon /template/ ContentControl#PART_IconPresenter">
<Setter Property="IsVisible" Value="True" /> <Setter Property="IsVisible" Value="True" />
</Style> </Style>
@ -949,6 +947,20 @@
</Style> </Style>
</Style> </Style>
<Style Selector="MenuItem.filter_mode_switcher">
<Setter Property="Height" Value="48"/>
<Setter Property="StaysOpenOnClick" Value="True"/>
<Style Selector="^:selected">
<Style Selector="^ /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="Foreground" Value="Transparent" />
</Style>
</Style>
</Style>
<Style Selector="ComboBox"> <Style Selector="ComboBox">
<Style.Resources> <Style.Resources>
<Thickness x:Key="ComboBoxDropdownBorderPadding">4,0</Thickness> <Thickness x:Key="ComboBoxDropdownBorderPadding">4,0</Thickness>
@ -983,12 +995,7 @@
<Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid Background="Transparent"> <Grid Background="Transparent" ColumnDefinitions="Auto,*">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" BorderBrush="{DynamicResource Brush.Border1}" BorderThickness="1" Background="Transparent" CornerRadius="2"> <Border x:Name="Border" Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" BorderBrush="{DynamicResource Brush.Border1}" BorderThickness="1" Background="Transparent" CornerRadius="2">
<Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent}" IsVisible="False" Margin="0,2,0,0"/> <Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent}" IsVisible="False" Margin="0,2,0,0"/>
</Border> </Border>
@ -1161,7 +1168,7 @@
<Setter Property="Data" Value="M 0 4 L 8 4 L 4 8 Z" /> <Setter Property="Data" Value="M 0 4 L 8 4 L 4 8 Z" />
</Style> </Style>
</Style> </Style>
<Style Selector="ToggleButton.folder"> <Style Selector="ToggleButton.folder">
<Setter Property="Margin" Value="0" /> <Setter Property="Margin" Value="0" />
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
@ -1234,7 +1241,7 @@
<Style Selector="ToggleButton.toggle_untracked:pointerover /template/ Path#PART_IndicatorIcon"> <Style Selector="ToggleButton.toggle_untracked:pointerover /template/ Path#PART_IndicatorIcon">
<Setter Property="Opacity" Value="1"/> <Setter Property="Opacity" Value="1"/>
</Style> </Style>
<Style Selector="ToggleButton.show_as_tree"> <Style Selector="ToggleButton.show_as_tree">
<Setter Property="Margin" Value="0" /> <Setter Property="Margin" Value="0" />
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
@ -1266,7 +1273,7 @@
<Setter Property="Opacity" Value="1"/> <Setter Property="Opacity" Value="1"/>
</Style> </Style>
</Style> </Style>
<Style Selector="Slider"> <Style Selector="Slider">
<Style.Resources> <Style.Resources>
<Thickness x:Key="SliderTopHeaderMargin">0,0,0,4</Thickness> <Thickness x:Key="SliderTopHeaderMargin">0,0,0,4</Thickness>

View file

@ -55,7 +55,7 @@
<Color x:Key="Color.InlineCode">#FF383838</Color> <Color x:Key="Color.InlineCode">#FF383838</Color>
</ResourceDictionary> </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>
<SolidColorBrush x:Key="Brush.Window" Color="{DynamicResource Color.Window}"/> <SolidColorBrush x:Key="Brush.Window" Color="{DynamicResource Color.Window}"/>
<SolidColorBrush x:Key="Brush.WindowBorder" Color="{DynamicResource Color.WindowBorder}"/> <SolidColorBrush x:Key="Brush.WindowBorder" Color="{DynamicResource Color.WindowBorder}"/>
<SolidColorBrush x:Key="Brush.TitleBar" Color="{DynamicResource Color.TitleBar}"/> <SolidColorBrush x:Key="Brush.TitleBar" Color="{DynamicResource Color.TitleBar}"/>

View file

@ -47,9 +47,11 @@
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.2.0" /> <PackageReference Include="Avalonia.AvaloniaEdit" Version="11.2.0" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.2.0" /> <PackageReference Include="AvaloniaEdit.TextMate" Version="11.2.0" />
<PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.4" /> <PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.4" />
<PackageReference Include="BitMiracle.LibTiff.NET" Version="2.4.660" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" /> <PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
<PackageReference Include="OpenAI" Version="2.2.0-beta.4" /> <PackageReference Include="OpenAI" Version="2.2.0-beta.4" />
<PackageReference Include="Pfim" Version="0.11.3" />
<PackageReference Include="TextMateSharp" Version="1.0.66" /> <PackageReference Include="TextMateSharp" Version="1.0.66" />
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" /> <PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" />
</ItemGroup> </ItemGroup>

View file

@ -25,7 +25,7 @@ namespace SourceGit.ViewModels
{ {
if (!string.IsNullOrEmpty(file)) if (!string.IsNullOrEmpty(file))
{ {
var log = _repo.CreateLog("Remove Assue Unchanged File"); var log = _repo.CreateLog("Remove Assume Unchanged File");
new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec(); new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec();
log.Complete(); log.Complete();
Files.Remove(file); Files.Remove(file);

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Threading; using Avalonia.Threading;
@ -10,10 +11,25 @@ namespace SourceGit.ViewModels
{ {
public class Blame : ObservableObject public class Blame : ObservableObject
{ {
public string Title public string FilePath
{ {
get; get;
private set; }
public Models.Commit Revision
{
get => _revision;
private set => SetProperty(ref _revision, value);
}
public Models.BlameData Data
{
get => _data;
private set
{
if (SetProperty(ref _data, value))
OnPropertyChanged(nameof(IsBinary));
}
} }
public bool IsBinary public bool IsBinary
@ -21,42 +37,27 @@ namespace SourceGit.ViewModels
get => _data != null && _data.IsBinary; get => _data != null && _data.IsBinary;
} }
public Models.BlameData Data public bool CanBack
{ {
get => _data; get => _navigationActiveIndex > 0;
private set => SetProperty(ref _data, value);
} }
public Blame(string repo, string file, string revision) public bool CanForward
{ {
get => _navigationActiveIndex < _navigationHistory.Count - 1;
}
public Blame(string repo, string file, Models.Commit commit)
{
var sha = commit.SHA.Substring(0, 10);
FilePath = file;
Revision = commit;
_repo = repo; _repo = repo;
_navigationHistory.Add(sha);
Title = $"{file} @ {revision.AsSpan(0, 10)}"; _commits.Add(sha, commit);
Task.Run(() => SetBlameData(sha);
{
var result = new Commands.Blame(repo, file, revision).Result();
Dispatcher.UIThread.Invoke(() =>
{
Data = result;
OnPropertyChanged(nameof(IsBinary));
});
});
}
public void NavigateToCommit(string commitSHA)
{
var launcher = App.GetLauncer();
if (launcher == null)
return;
foreach (var page in launcher.Pages)
{
if (page.Data is Repository repo && repo.FullPath.Equals(_repo))
{
repo.NavigateToCommit(commitSHA);
break;
}
}
} }
public string GetCommitMessage(string sha) public string GetCommitMessage(string sha)
@ -69,8 +70,102 @@ namespace SourceGit.ViewModels
return msg; return msg;
} }
private readonly string _repo; public void Back()
{
if (_navigationActiveIndex <= 0)
return;
_navigationActiveIndex--;
OnPropertyChanged(nameof(CanBack));
OnPropertyChanged(nameof(CanForward));
NavigateToCommit(_navigationHistory[_navigationActiveIndex]);
}
public void Forward()
{
if (_navigationActiveIndex >= _navigationHistory.Count - 1)
return;
_navigationActiveIndex++;
OnPropertyChanged(nameof(CanBack));
OnPropertyChanged(nameof(CanForward));
NavigateToCommit(_navigationHistory[_navigationActiveIndex]);
}
public void NavigateToCommit(string commitSHA)
{
if (!_navigationHistory[_navigationActiveIndex].Equals(commitSHA, StringComparison.Ordinal))
{
_navigationHistory.Add(commitSHA);
_navigationActiveIndex = _navigationHistory.Count - 1;
OnPropertyChanged(nameof(CanBack));
OnPropertyChanged(nameof(CanForward));
}
if (!Revision.SHA.StartsWith(commitSHA, StringComparison.Ordinal))
SetBlameData(commitSHA);
if (App.GetLauncher() is { Pages: { } pages })
{
foreach (var page in pages)
{
if (page.Data is Repository repo && repo.FullPath.Equals(_repo))
{
repo.NavigateToCommit(commitSHA);
break;
}
}
}
}
private void SetBlameData(string commitSHA)
{
if (_cancellationSource is { IsCancellationRequested: false })
_cancellationSource.Cancel();
_cancellationSource = new CancellationTokenSource();
var token = _cancellationSource.Token;
if (_commits.TryGetValue(commitSHA, out var c))
{
Revision = c;
}
else
{
Task.Run(() =>
{
var result = new Commands.QuerySingleCommit(_repo, commitSHA).Result();
Dispatcher.UIThread.Invoke(() =>
{
if (!token.IsCancellationRequested)
{
_commits.Add(commitSHA, result);
Revision = result ?? new Models.Commit() { SHA = commitSHA };
}
});
}, token);
}
Task.Run(() =>
{
var result = new Commands.Blame(_repo, FilePath, commitSHA).Result();
Dispatcher.UIThread.Invoke(() =>
{
if (!token.IsCancellationRequested)
Data = result;
});
}, token);
}
private string _repo;
private Models.Commit _revision;
private CancellationTokenSource _cancellationSource = null;
private int _navigationActiveIndex = 0;
private List<string> _navigationHistory = [];
private Models.BlameData _data = null; private Models.BlameData _data = null;
private Dictionary<string, string> _commitMessages = new Dictionary<string, string>(); private Dictionary<string, Models.Commit> _commits = new();
private Dictionary<string, string> _commitMessages = new();
} }
} }

View file

@ -86,7 +86,7 @@ namespace SourceGit.ViewModels
public void NavigateTo(string commitSHA) public void NavigateTo(string commitSHA)
{ {
var launcher = App.GetLauncer(); var launcher = App.GetLauncher();
if (launcher == null) if (launcher == null)
return; return;
@ -118,7 +118,7 @@ namespace SourceGit.ViewModels
public ContextMenu CreateChangeContextMenu() public ContextMenu CreateChangeContextMenu()
{ {
if (_selectedChanges == null || _selectedChanges.Count != 1) if (_selectedChanges is not { Count: 1 })
return null; return null;
var change = _selectedChanges[0]; var change = _selectedChanges[0];

View file

@ -74,9 +74,9 @@ namespace SourceGit.ViewModels
public class Builder public class Builder
{ {
public List<BranchTreeNode> Locals => _locals; public List<BranchTreeNode> Locals { get; } = [];
public List<BranchTreeNode> Remotes => _remotes; public List<BranchTreeNode> Remotes { get; } = [];
public List<string> InvalidExpandedNodes => _invalidExpandedNodes; public List<string> InvalidExpandedNodes { get; } = [];
public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode) public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode)
{ {
@ -109,14 +109,14 @@ namespace SourceGit.ViewModels
fakeRemoteTime--; fakeRemoteTime--;
folders.Add(path, node); folders.Add(path, node);
_remotes.Add(node); Remotes.Add(node);
} }
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (branch.IsLocal) if (branch.IsLocal)
{ {
MakeBranchNode(branch, _locals, folders, "refs/heads", bForceExpanded); MakeBranchNode(branch, Locals, folders, "refs/heads", bForceExpanded);
continue; continue;
} }
@ -131,20 +131,20 @@ namespace SourceGit.ViewModels
foreach (var path in _expanded) foreach (var path in _expanded)
{ {
if (!folders.ContainsKey(path)) if (!folders.ContainsKey(path))
_invalidExpandedNodes.Add(path); InvalidExpandedNodes.Add(path);
} }
folders.Clear(); folders.Clear();
if (_localSortMode == Models.BranchSortMode.Name) if (_localSortMode == Models.BranchSortMode.Name)
SortNodesByName(_locals); SortNodesByName(Locals);
else else
SortNodesByTime(_locals); SortNodesByTime(Locals);
if (_remoteSortMode == Models.BranchSortMode.Name) if (_remoteSortMode == Models.BranchSortMode.Name)
SortNodesByName(_remotes); SortNodesByName(Remotes);
else else
SortNodesByTime(_remotes); SortNodesByTime(Remotes);
} }
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded) private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded)
@ -269,9 +269,6 @@ namespace SourceGit.ViewModels
private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name; private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name;
private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name; private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name;
private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>();
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
private readonly List<string> _invalidExpandedNodes = new List<string>();
private readonly HashSet<string> _expanded = new HashSet<string>(); private readonly HashSet<string> _expanded = new HashSet<string>();
} }
} }

View file

@ -0,0 +1,111 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class CheckoutAndFastForward : Popup
{
public Models.Branch LocalBranch
{
get;
}
public Models.Branch RemoteBranch
{
get;
}
public bool DiscardLocalChanges
{
get;
set;
}
public bool IsRecurseSubmoduleVisible
{
get => _repo.Submodules.Count > 0;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public CheckoutAndFastForward(Repository repo, Models.Branch localBranch, Models.Branch remoteBranch)
{
_repo = repo;
LocalBranch = localBranch;
RemoteBranch = remoteBranch;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout and Fast-Forward '{LocalBranch.Name}' ...";
var log = _repo.CreateLog($"Checkout and Fast-Forward '{LocalBranch.Name}' ...");
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
{
var succ = false;
var needPopStash = false;
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, true, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, false, true);
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete();
CallUIThread(() =>
{
ProgressDescription = "Waiting for branch updated...";
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
Task.Delay(400).Wait();
return succ;
});
}
private Repository _repo;
}
}

View file

@ -66,6 +66,7 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
ProgressDescription = $"Cherry-Pick commit(s) ..."; ProgressDescription = $"Cherry-Pick commit(s) ...";
var log = _repo.CreateLog("Cherry-Pick"); var log = _repo.CreateLog("Cherry-Pick");

View file

@ -150,7 +150,7 @@ namespace SourceGit.ViewModels
CallUIThread(() => CallUIThread(() =>
{ {
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true); var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);
var launcher = App.GetLauncer(); var launcher = App.GetLauncher();
var page = null as LauncherPage; var page = null as LauncherPage;
foreach (var one in launcher.Pages) foreach (var one in launcher.Pages)
{ {

View file

@ -1,13 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
@ -56,7 +54,7 @@ namespace SourceGit.ViewModels
{ {
get; get;
private set; private set;
} = []; }
public List<string> Children public List<string> Children
{ {
@ -83,7 +81,7 @@ namespace SourceGit.ViewModels
{ {
if (SetProperty(ref _selectedChanges, value)) if (SetProperty(ref _selectedChanges, value))
{ {
if (value == null || value.Count != 1) if (value is not { Count: 1 })
DiffContext = null; DiffContext = null;
else else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, value[0]), _diffContext); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, value[0]), _diffContext);
@ -103,16 +101,20 @@ namespace SourceGit.ViewModels
set set
{ {
if (SetProperty(ref _searchChangeFilter, value)) if (SetProperty(ref _searchChangeFilter, value))
{
RefreshVisibleChanges(); RefreshVisibleChanges();
}
} }
} }
public string ViewRevisionFilePath
{
get => _viewRevisionFilePath;
private set => SetProperty(ref _viewRevisionFilePath, value);
}
public object ViewRevisionFileContent public object ViewRevisionFileContent
{ {
get => _viewRevisionFileContent; get => _viewRevisionFileContent;
set => SetProperty(ref _viewRevisionFileContent, value); private set => SetProperty(ref _viewRevisionFileContent, value);
} }
public string RevisionFileSearchFilter public string RevisionFileSearchFilter
@ -131,6 +133,12 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _revisionFileSearchSuggestion, value); private set => SetProperty(ref _revisionFileSearchSuggestion, value);
} }
public bool CanOpenRevisionFileWithDefaultEditor
{
get => _canOpenRevisionFileWithDefaultEditor;
private set => SetProperty(ref _canOpenRevisionFileWithDefaultEditor, value);
}
public CommitDetail(Repository repo) public CommitDetail(Repository repo)
{ {
_repo = repo; _repo = repo;
@ -193,26 +201,28 @@ namespace SourceGit.ViewModels
{ {
if (file == null) if (file == null)
{ {
ViewRevisionFilePath = string.Empty;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
CanOpenRevisionFileWithDefaultEditor = false;
return; return;
} }
ViewRevisionFilePath = file.Path;
switch (file.Type) switch (file.Type)
{ {
case Models.ObjectType.Blob: case Models.ObjectType.Blob:
CanOpenRevisionFileWithDefaultEditor = true;
Task.Run(() => Task.Run(() =>
{ {
var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result(); var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
if (isBinary) if (isBinary)
{ {
var ext = Path.GetExtension(file.Path); var imgDecoder = ImageSource.GetDecoder(file.Path);
if (IMG_EXTS.Contains(ext)) if (imgDecoder != Models.ImageDecoder.None)
{ {
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path); var source = ImageSource.FromRevision(_repo.FullPath, _commit.SHA, file.Path, imgDecoder);
var fileSize = stream.Length; var image = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size);
var bitmap = fileSize > 0 ? new Bitmap(stream) : null;
var imageType = ext!.Substring(1).ToUpper(CultureInfo.CurrentCulture);
var image = new Models.RevisionImageFile() { Image = bitmap, FileSize = fileSize, ImageType = imageType };
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image); Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image);
} }
else else
@ -227,13 +237,20 @@ namespace SourceGit.ViewModels
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path); var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
var content = new StreamReader(contentStream).ReadToEnd(); var content = new StreamReader(contentStream).ReadToEnd();
var matchLFS = REG_LFS_FORMAT().Match(content); var lfs = Models.LFSObject.Parse(content);
if (matchLFS.Success) if (lfs != null)
{ {
var obj = new Models.RevisionLFSObject() { Object = new Models.LFSObject() }; var imgDecoder = ImageSource.GetDecoder(file.Path);
obj.Object.Oid = matchLFS.Groups[1].Value; if (imgDecoder != Models.ImageDecoder.None)
obj.Object.Size = long.Parse(matchLFS.Groups[2].Value); {
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = obj); var combined = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = combined);
}
else
{
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = rlfs);
}
} }
else else
{ {
@ -243,40 +260,42 @@ namespace SourceGit.ViewModels
}); });
break; break;
case Models.ObjectType.Commit: case Models.ObjectType.Commit:
CanOpenRevisionFileWithDefaultEditor = false;
Task.Run(() => Task.Run(() =>
{ {
var submoduleRoot = Path.Combine(_repo.FullPath, file.Path); var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result(); var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
if (commit != null) var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result() : null;
var module = new Models.RevisionSubmodule()
{ {
var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result(); Commit = commit ?? new Models.Commit() { SHA = _commit.SHA },
var submodule = new Models.RevisionSubmodule() FullMessage = new Models.CommitFullMessage { Message = message }
{ };
Commit = commit,
FullMessage = new Models.CommitFullMessage { Message = body }
};
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = submodule); Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = module);
}
else
{
Dispatcher.UIThread.Invoke(() =>
{
ViewRevisionFileContent = new Models.RevisionSubmodule()
{
Commit = new Models.Commit() { SHA = file.SHA },
FullMessage = null,
};
});
}
}); });
break; break;
default: default:
CanOpenRevisionFileWithDefaultEditor = false;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
break; break;
} }
} }
public Task OpenRevisionFileWithDefaultEditor(string file)
{
return Task.Run(() =>
{
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file);
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
});
}
public ContextMenu CreateChangeContextMenu(Models.Change change) public ContextMenu CreateChangeContextMenu(Models.Change change)
{ {
var diffWithMerger = new MenuItem(); var diffWithMerger = new MenuItem();
@ -318,7 +337,7 @@ namespace SourceGit.ViewModels
blame.IsEnabled = change.Index != Models.ChangeState.Deleted; blame.IsEnabled = change.Index != Models.ChangeState.Deleted;
blame.Click += (_, ev) => blame.Click += (_, ev) =>
{ {
App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit.SHA), false); App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit), false);
ev.Handled = true; ev.Handled = true;
}; };
@ -426,13 +445,10 @@ namespace SourceGit.ViewModels
var openWith = new MenuItem(); var openWith = new MenuItem();
openWith.Header = App.Text("OpenWith"); openWith.Header = App.Text("OpenWith");
openWith.Icon = App.CreateMenuIcon("Icons.OpenWith"); openWith.Icon = App.CreateMenuIcon("Icons.OpenWith");
openWith.Click += (_, ev) => openWith.IsEnabled = file.Type == Models.ObjectType.Blob;
openWith.Click += async (_, ev) =>
{ {
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? ""; await OpenRevisionFileWithDefaultEditor(file.Path);
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
ev.Handled = true; ev.Handled = true;
}; };
@ -453,9 +469,9 @@ namespace SourceGit.ViewModels
if (selected.Count == 1) if (selected.Count == 1)
{ {
var folder = selected[0]; var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString(); var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path)); var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path)!);
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo); await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo));
} }
} }
catch (Exception e) catch (Exception e)
@ -486,7 +502,7 @@ namespace SourceGit.ViewModels
blame.IsEnabled = file.Type == Models.ObjectType.Blob; blame.IsEnabled = file.Type == Models.ObjectType.Blob;
blame.Click += (_, ev) => blame.Click += (_, ev) =>
{ {
App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit.SHA), false); App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit), false);
ev.Handled = true; ev.Handled = true;
}; };
@ -554,6 +570,8 @@ namespace SourceGit.ViewModels
SignInfo = null; SignInfo = null;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
ViewRevisionFilePath = string.Empty;
CanOpenRevisionFileWithDefaultEditor = false;
Children = null; Children = null;
RevisionFileSearchFilter = string.Empty; RevisionFileSearchFilter = string.Empty;
RevisionFileSearchSuggestion = null; RevisionFileSearchSuggestion = null;
@ -574,14 +592,14 @@ namespace SourceGit.ViewModels
if (!token.IsCancellationRequested) if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines }); Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines });
}); }, token);
Task.Run(() => Task.Run(() =>
{ {
var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result(); var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
if (!token.IsCancellationRequested) if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo); Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
}); }, token);
if (Preferences.Instance.ShowChildren) if (Preferences.Instance.ShowChildren)
{ {
@ -592,7 +610,7 @@ namespace SourceGit.ViewModels
var children = cmd.Result(); var children = cmd.Result();
if (!token.IsCancellationRequested) if (!token.IsCancellationRequested)
Dispatcher.UIThread.Post(() => Children = children); Dispatcher.UIThread.Post(() => Children = children);
}); }, token);
} }
Task.Run(() => Task.Run(() =>
@ -622,12 +640,12 @@ namespace SourceGit.ViewModels
SelectedChanges = null; SelectedChanges = null;
}); });
} }
}); }, token);
} }
private List<Models.InlineElement> ParseInlinesInMessage(string message) private Models.InlineElementCollector ParseInlinesInMessage(string message)
{ {
var inlines = new List<Models.InlineElement>(); var inlines = new Models.InlineElementCollector();
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules) if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
{ {
foreach (var rule in rules) foreach (var rule in rules)
@ -643,17 +661,7 @@ namespace SourceGit.ViewModels
var start = match.Index; var start = match.Index;
var len = match.Length; var len = match.Length;
var intersect = false; if (inlines.Intersect(start, len) != null)
foreach (var link in inlines)
{
if (link.Intersect(start, len))
{
intersect = true;
break;
}
}
if (intersect)
continue; continue;
var url = message.Substring(start, len); var url = message.Substring(start, len);
@ -670,17 +678,7 @@ namespace SourceGit.ViewModels
var start = match.Index; var start = match.Index;
var len = match.Length; var len = match.Length;
var intersect = false; if (inlines.Intersect(start, len) != null)
foreach (var link in inlines)
{
if (link.Intersect(start, len))
{
intersect = true;
break;
}
}
if (intersect)
continue; continue;
var sha = match.Groups[1].Value; var sha = match.Groups[1].Value;
@ -689,9 +687,7 @@ namespace SourceGit.ViewModels
inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha)); inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha));
} }
if (inlines.Count > 0) inlines.Sort();
inlines.Sort((l, r) => l.Start - r.Start);
return inlines; return inlines;
} }
@ -897,14 +893,6 @@ namespace SourceGit.ViewModels
[GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")] [GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")]
private static partial Regex REG_SHA_FORMAT(); private static partial Regex REG_SHA_FORMAT();
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
private static partial Regex REG_LFS_FORMAT();
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
{
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
};
private Repository _repo = null; private Repository _repo = null;
private Models.Commit _commit = null; private Models.Commit _commit = null;
private Models.CommitFullMessage _fullMessage = null; private Models.CommitFullMessage _fullMessage = null;
@ -915,11 +903,13 @@ namespace SourceGit.ViewModels
private List<Models.Change> _selectedChanges = null; private List<Models.Change> _selectedChanges = null;
private string _searchChangeFilter = string.Empty; private string _searchChangeFilter = string.Empty;
private DiffContext _diffContext = null; private DiffContext _diffContext = null;
private string _viewRevisionFilePath = string.Empty;
private object _viewRevisionFileContent = null; private object _viewRevisionFileContent = null;
private CancellationTokenSource _cancellationSource = null; private CancellationTokenSource _cancellationSource = null;
private bool _requestingRevisionFiles = false; private bool _requestingRevisionFiles = false;
private List<string> _revisionFiles = null; private List<string> _revisionFiles = null;
private string _revisionFileSearchFilter = string.Empty; private string _revisionFileSearchFilter = string.Empty;
private List<string> _revisionFileSearchSuggestion = null; private List<string> _revisionFileSearchSuggestion = null;
private bool _canOpenRevisionFileWithDefaultEditor = false;
} }
} }

View file

@ -29,8 +29,7 @@ namespace SourceGit.ViewModels
public ConfigureWorkspace() public ConfigureWorkspace()
{ {
Workspaces = new AvaloniaList<Workspace>(); Workspaces = new(Preferences.Instance.Workspaces);
Workspaces.AddRange(Preferences.Instance.Workspaces);
} }
public void Add() public void Add()

View file

@ -65,8 +65,7 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateTagName(string name, ValidationContext ctx) public static ValidationResult ValidateTagName(string name, ValidationContext ctx)
{ {
var creator = ctx.ObjectInstance as CreateTag; if (ctx.ObjectInstance is CreateTag creator)
if (creator != null)
{ {
var found = creator._repo.Tags.Find(x => x.Name == name); var found = creator._repo.Tags.Find(x => x.Name == name);
if (found != null) if (found != null)

View file

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Media.Imaging;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -14,7 +12,7 @@ namespace SourceGit.ViewModels
{ {
public string Title public string Title
{ {
get => _title; get;
} }
public bool IgnoreWhitespace public bool IgnoreWhitespace
@ -70,9 +68,9 @@ namespace SourceGit.ViewModels
} }
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null") if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
_title = _option.Path; Title = _option.Path;
else else
_title = $"{_option.OrgPath} → {_option.Path}"; Title = $"{_option.OrgPath} → {_option.Path}";
LoadDiffContent(); LoadDiffContent();
} }
@ -113,13 +111,10 @@ namespace SourceGit.ViewModels
Task.Run(() => Task.Run(() =>
{ {
// NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
// There is no way to tell a git-diff to use "ALL lines of context",
// so instead we set a very high number for the "lines of context" parameter.
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines; var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
var ignoreWS = Preferences.Instance.IgnoreWhitespaceChangesInDiff; var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
var latest = new Commands.Diff(_repo, _option, numLines, ignoreWS).Result(); var latest = new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).Result();
var info = new Info(_option, numLines, ignoreWS, latest); var info = new Info(_option, numLines, ignoreWhitespace, latest);
if (_info != null && info.IsSame(_info)) if (_info != null && info.IsSame(_info))
return; return;
@ -133,7 +128,7 @@ namespace SourceGit.ViewModels
if (count <= 3) if (count <= 3)
{ {
var submoduleDiff = new Models.SubmoduleDiff(); var submoduleDiff = new Models.SubmoduleDiff();
var submoduleRoot = $"{_repo}/{_option.Path}".Replace("\\", "/"); var submoduleRoot = $"{_repo}/{_option.Path}".Replace('\\', '/').TrimEnd('/');
isSubmodule = true; isSubmodule = true;
for (int i = 1; i < count; i++) for (int i = 1; i < count; i++)
{ {
@ -164,28 +159,39 @@ namespace SourceGit.ViewModels
else if (latest.IsBinary) else if (latest.IsBinary)
{ {
var oldPath = string.IsNullOrEmpty(_option.OrgPath) ? _option.Path : _option.OrgPath; var oldPath = string.IsNullOrEmpty(_option.OrgPath) ? _option.Path : _option.OrgPath;
var ext = Path.GetExtension(_option.Path); var imgDecoder = ImageSource.GetDecoder(_option.Path);
if (IMG_EXTS.Contains(ext)) if (imgDecoder != Models.ImageDecoder.None)
{ {
var imgDiff = new Models.ImageDiff(); var imgDiff = new Models.ImageDiff();
if (_option.Revisions.Count == 2) if (_option.Revisions.Count == 2)
{ {
(imgDiff.Old, imgDiff.OldFileSize) = BitmapFromRevisionFile(_repo, _option.Revisions[0], oldPath); var oldImage = ImageSource.FromRevision(_repo, _option.Revisions[0], oldPath, imgDecoder);
(imgDiff.New, imgDiff.NewFileSize) = BitmapFromRevisionFile(_repo, _option.Revisions[1], _option.Path); var newImage = ImageSource.FromRevision(_repo, _option.Revisions[1], _option.Path, imgDecoder);
imgDiff.Old = oldImage.Bitmap;
imgDiff.OldFileSize = oldImage.Size;
imgDiff.New = newImage.Bitmap;
imgDiff.NewFileSize = newImage.Size;
} }
else else
{ {
if (!oldPath.Equals("/dev/null", StringComparison.Ordinal)) if (!oldPath.Equals("/dev/null", StringComparison.Ordinal))
(imgDiff.Old, imgDiff.OldFileSize) = BitmapFromRevisionFile(_repo, "HEAD", oldPath); {
var oldImage = ImageSource.FromRevision(_repo, "HEAD", oldPath, imgDecoder);
imgDiff.Old = oldImage.Bitmap;
imgDiff.OldFileSize = oldImage.Size;
}
var fullPath = Path.Combine(_repo, _option.Path); var fullPath = Path.Combine(_repo, _option.Path);
if (File.Exists(fullPath)) if (File.Exists(fullPath))
{ {
imgDiff.New = new Bitmap(fullPath); var newImage = ImageSource.FromFile(fullPath, imgDecoder);
imgDiff.NewFileSize = new FileInfo(fullPath).Length; imgDiff.New = newImage.Bitmap;
imgDiff.NewFileSize = newImage.Size;
} }
} }
rs = imgDiff; rs = imgDiff;
} }
else else
@ -207,7 +213,11 @@ namespace SourceGit.ViewModels
} }
else if (latest.IsLFS) else if (latest.IsLFS)
{ {
rs = latest.LFSDiff; var imgDecoder = ImageSource.GetDecoder(_option.Path);
if (imgDecoder != Models.ImageDecoder.None)
rs = new LFSImageDiff(_repo, latest.LFSDiff, imgDecoder);
else
rs = latest.LFSDiff;
} }
else else
{ {
@ -226,45 +236,27 @@ namespace SourceGit.ViewModels
}); });
} }
private (Bitmap, long) BitmapFromRevisionFile(string repo, string revision, string file)
{
var stream = Commands.QueryFileContent.Run(repo, revision, file);
var size = stream.Length;
return size > 0 ? (new Bitmap(stream), size) : (null, size);
}
private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha) private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha)
{ {
var commit = new Commands.QuerySingleCommit(repo, sha).Result(); var commit = new Commands.QuerySingleCommit(repo, sha).Result();
if (commit != null) if (commit == null)
{ return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha } };
var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
return new Models.RevisionSubmodule()
{
Commit = commit,
FullMessage = new Models.CommitFullMessage { Message = body }
};
}
var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
return new Models.RevisionSubmodule() return new Models.RevisionSubmodule()
{ {
Commit = new Models.Commit() { SHA = sha }, Commit = commit,
FullMessage = null, FullMessage = new Models.CommitFullMessage { Message = body }
}; };
} }
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
{
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
};
private class Info private class Info
{ {
public string Argument { get; set; } public string Argument { get; }
public int UnifiedLines { get; set; } public int UnifiedLines { get; }
public bool IgnoreWhitespace { get; set; } public bool IgnoreWhitespace { get; }
public string OldHash { get; set; } public string OldHash { get; }
public string NewHash { get; set; } public string NewHash { get; }
public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result) public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result)
{ {
@ -287,7 +279,6 @@ namespace SourceGit.ViewModels
private readonly string _repo; private readonly string _repo;
private readonly Models.DiffOption _option = null; private readonly Models.DiffOption _option = null;
private string _title;
private string _fileModeChange = string.Empty; private string _fileModeChange = string.Empty;
private int _unifiedLines = 4; private int _unifiedLines = 4;
private bool _isTextDiff = false; private bool _isTextDiff = false;

View file

@ -46,10 +46,7 @@ namespace SourceGit.ViewModels
else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote)) else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote))
{ {
var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote); var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote);
if (def != null) SelectedRemote = def ?? _repo.Remotes[0];
SelectedRemote = def;
else
SelectedRemote = _repo.Remotes[0];
} }
else else
{ {
@ -88,7 +85,7 @@ namespace SourceGit.ViewModels
CallUIThread(() => CallUIThread(() =>
{ {
if (!string.IsNullOrEmpty(upstreamHead)) if (!string.IsNullOrEmpty(upstreamHead))
_repo.NavigateToCommitDelayed(upstreamHead); _repo.NavigateToCommit(upstreamHead, true);
_repo.MarkFetched(); _repo.MarkFetched();
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);

View file

@ -37,7 +37,7 @@ namespace SourceGit.ViewModels
var changedLocalBranchHead = new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).Result(); var changedLocalBranchHead = new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).Result();
CallUIThread(() => CallUIThread(() =>
{ {
_repo.NavigateToCommitDelayed(changedLocalBranchHead); _repo.NavigateToCommit(changedLocalBranchHead, true);
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
}); });

View file

@ -1,24 +1,22 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Media.Imaging;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels namespace SourceGit.ViewModels
{ {
public class FileHistoriesRevisionFile(string path, object content) public class FileHistoriesRevisionFile(string path, object content = null, bool canOpenWithDefaultEditor = false)
{ {
public string Path { get; set; } = path; public string Path { get; set; } = path;
public object Content { get; set; } = content; public object Content { get; set; } = content;
public bool CanOpenWithDefaultEditor { get; set; } = canOpenWithDefaultEditor;
} }
public partial class FileHistoriesSingleRevision : ObservableObject public class FileHistoriesSingleRevision : ObservableObject
{ {
public bool IsDiffMode public bool IsDiffMode
{ {
@ -47,9 +45,26 @@ namespace SourceGit.ViewModels
RefreshViewContent(); RefreshViewContent();
} }
public void ResetToSelectedRevision() public Task<bool> ResetToSelectedRevision()
{ {
new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}"); return Task.Run(() => new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}"));
}
public Task OpenWithDefaultEditor()
{
if (_viewContent is not FileHistoriesRevisionFile { CanOpenWithDefaultEditor: true })
return null;
return Task.Run(() =>
{
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, _file);
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_revision.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _revision.SHA, _file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
});
} }
private void RefreshViewContent() private void RefreshViewContent()
@ -65,7 +80,7 @@ namespace SourceGit.ViewModels
var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _revision.SHA, _file).Result(); var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _revision.SHA, _file).Result();
if (objs.Count == 0) if (objs.Count == 0)
{ {
ViewContent = new FileHistoriesRevisionFile(_file, null); ViewContent = new FileHistoriesRevisionFile(_file);
return; return;
} }
@ -78,21 +93,18 @@ namespace SourceGit.ViewModels
var isBinary = new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).Result(); var isBinary = new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).Result();
if (isBinary) if (isBinary)
{ {
var ext = Path.GetExtension(_file); var imgDecoder = ImageSource.GetDecoder(_file);
if (IMG_EXTS.Contains(ext)) if (imgDecoder != Models.ImageDecoder.None)
{ {
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file); var source = ImageSource.FromRevision(_repo.FullPath, _revision.SHA, _file, imgDecoder);
var fileSize = stream.Length; var image = new Models.RevisionImageFile(_file, source.Bitmap, source.Size);
var bitmap = fileSize > 0 ? new Bitmap(stream) : null; Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image, true));
var imageType = Path.GetExtension(_file).TrimStart('.').ToUpper(CultureInfo.CurrentCulture);
var image = new Models.RevisionImageFile() { Image = bitmap, FileSize = fileSize, ImageType = imageType };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
} }
else else
{ {
var size = new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).Result(); var size = new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).Result();
var binaryFile = new Models.RevisionBinaryFile() { Size = size }; var binaryFile = new Models.RevisionBinaryFile() { Size = size };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile)); Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile, true));
} }
return; return;
@ -100,18 +112,25 @@ namespace SourceGit.ViewModels
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file); var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
var content = new StreamReader(contentStream).ReadToEnd(); var content = new StreamReader(contentStream).ReadToEnd();
var matchLFS = REG_LFS_FORMAT().Match(content); var lfs = Models.LFSObject.Parse(content);
if (matchLFS.Success) if (lfs != null)
{ {
var lfs = new Models.RevisionLFSObject() { Object = new Models.LFSObject() }; var imgDecoder = ImageSource.GetDecoder(_file);
lfs.Object.Oid = matchLFS.Groups[1].Value; if (imgDecoder != Models.ImageDecoder.None)
lfs.Object.Size = long.Parse(matchLFS.Groups[2].Value); {
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, lfs)); var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder);
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, combined, true));
}
else
{
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs, true));
}
} }
else else
{ {
var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content }; var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, txt)); Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, txt, true));
} }
}); });
break; break;
@ -120,29 +139,18 @@ namespace SourceGit.ViewModels
{ {
var submoduleRoot = Path.Combine(_repo.FullPath, _file); var submoduleRoot = Path.Combine(_repo.FullPath, _file);
var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result(); var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
if (commit != null) var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result() : null;
var module = new Models.RevisionSubmodule()
{ {
var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result(); Commit = commit ?? new Models.Commit() { SHA = obj.SHA },
var module = new Models.RevisionSubmodule() FullMessage = new Models.CommitFullMessage { Message = message }
{ };
Commit = commit,
FullMessage = new Models.CommitFullMessage { Message = message } Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
};
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
}
else
{
var module = new Models.RevisionSubmodule()
{
Commit = new Models.Commit() { SHA = obj.SHA },
FullMessage = null
};
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
}
}); });
break; break;
default: default:
ViewContent = new FileHistoriesRevisionFile(_file, null); ViewContent = new FileHistoriesRevisionFile(_file);
break; break;
} }
} }
@ -153,18 +161,10 @@ namespace SourceGit.ViewModels
ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext); ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
} }
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
private static partial Regex REG_LFS_FORMAT();
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
{
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
};
private Repository _repo = null; private Repository _repo = null;
private string _file = null; private string _file = null;
private Models.Commit _revision = null; private Models.Commit _revision = null;
private bool _isDiffMode = true; private bool _isDiffMode = false;
private object _viewContent = null; private object _viewContent = null;
} }
@ -265,7 +265,6 @@ namespace SourceGit.ViewModels
public FileHistories(Repository repo, string file, string commit = null) public FileHistories(Repository repo, string file, string commit = null)
{ {
_repo = repo; _repo = repo;
_file = file;
Task.Run(() => Task.Run(() =>
{ {
@ -288,10 +287,10 @@ namespace SourceGit.ViewModels
switch (SelectedCommits.Count) switch (SelectedCommits.Count)
{ {
case 1: case 1:
ViewContent = new FileHistoriesSingleRevision(_repo, _file, SelectedCommits[0], _prevIsDiffMode); ViewContent = new FileHistoriesSingleRevision(_repo, file, SelectedCommits[0], _prevIsDiffMode);
break; break;
case 2: case 2:
ViewContent = new FileHistoriesCompareRevisions(_repo, _file, SelectedCommits[0], SelectedCommits[1]); ViewContent = new FileHistoriesCompareRevisions(_repo, file, SelectedCommits[0], SelectedCommits[1]);
break; break;
default: default:
ViewContent = SelectedCommits.Count; ViewContent = SelectedCommits.Count;
@ -317,11 +316,10 @@ namespace SourceGit.ViewModels
} }
private readonly Repository _repo = null; private readonly Repository _repo = null;
private readonly string _file = null;
private bool _isLoading = true; private bool _isLoading = true;
private bool _prevIsDiffMode = true; private bool _prevIsDiffMode = true;
private List<Models.Commit> _commits = null; private List<Models.Commit> _commits = null;
private Dictionary<string, string> _fullCommitMessages = new Dictionary<string, string>(); private Dictionary<string, string> _fullCommitMessages = new();
private object _viewContent = null; private object _viewContent = null;
} }
} }

View file

@ -0,0 +1,62 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class FilterModeInGraph : ObservableObject
{
public bool IsFiltered
{
get => _mode == Models.FilterMode.Included;
set => SetFilterMode(value ? Models.FilterMode.Included : Models.FilterMode.None);
}
public bool IsExcluded
{
get => _mode == Models.FilterMode.Excluded;
set => SetFilterMode(value ? Models.FilterMode.Excluded : Models.FilterMode.None);
}
public FilterModeInGraph(Repository repo, object target)
{
_repo = repo;
_target = target;
if (_target is Models.Branch b)
_mode = GetFilterMode(b.FullName);
else if (_target is Models.Tag t)
_mode = GetFilterMode(t.Name);
}
private Models.FilterMode GetFilterMode(string pattern)
{
foreach (var filter in _repo.Settings.HistoriesFilters)
{
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return filter.Mode;
}
return Models.FilterMode.None;
}
private void SetFilterMode(Models.FilterMode mode)
{
if (_mode != mode)
{
_mode = mode;
if (_target is Models.Branch branch)
_repo.SetBranchFilterMode(branch, _mode, false, true);
else if (_target is Models.Tag tag)
_repo.SetTagFilterMode(tag, _mode);
OnPropertyChanged(nameof(IsFiltered));
OnPropertyChanged(nameof(IsExcluded));
}
}
private Repository _repo = null;
private object _target = null;
private Models.FilterMode _mode = Models.FilterMode.None;
}
}

View file

@ -14,11 +14,6 @@ namespace SourceGit.ViewModels
{ {
public class Histories : ObservableObject, IDisposable public class Histories : ObservableObject, IDisposable
{ {
public Repository Repo
{
get => _repo;
}
public bool IsLoading public bool IsLoading
{ {
get => _isLoading; get => _isLoading;
@ -214,9 +209,56 @@ namespace SourceGit.ViewModels
} }
} }
public void DoubleTapped(Models.Commit commit) public bool CheckoutBranchByDecorator(Models.Decorator decorator)
{ {
if (commit == null || commit.IsCurrentHead) if (decorator == null)
return false;
if (decorator.Type == Models.DecoratorType.CurrentBranchHead ||
decorator.Type == Models.DecoratorType.CurrentCommitHead)
return true;
if (decorator.Type == Models.DecoratorType.LocalBranchHead)
{
var b = _repo.Branches.Find(x => x.Name == decorator.Name);
if (b == null)
return false;
_repo.CheckoutBranch(b);
return true;
}
if (decorator.Type == Models.DecoratorType.RemoteBranchHead)
{
var rb = _repo.Branches.Find(x => x.FriendlyName == decorator.Name);
if (rb == null)
return false;
var lb = _repo.Branches.Find(x => x.IsLocal && x.Upstream == rb.FullName);
if (lb == null || lb.TrackStatus.Ahead.Count > 0)
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new CreateBranch(_repo, rb));
}
else if (lb.TrackStatus.Behind.Count > 0)
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new CheckoutAndFastForward(_repo, lb, rb));
}
else if (!lb.IsCurrent)
{
_repo.CheckoutBranch(lb);
}
return true;
}
return false;
}
public void CheckoutBranchByCommit(Models.Commit commit)
{
if (commit.IsCurrentHead)
return; return;
var firstRemoteBranch = null as Models.Branch; var firstRemoteBranch = null as Models.Branch;
@ -224,16 +266,28 @@ namespace SourceGit.ViewModels
{ {
if (d.Type == Models.DecoratorType.LocalBranchHead) if (d.Type == Models.DecoratorType.LocalBranchHead)
{ {
var b = _repo.Branches.Find(x => x.FriendlyName == d.Name); var b = _repo.Branches.Find(x => x.Name == d.Name);
if (b != null) if (b == null)
continue;
_repo.CheckoutBranch(b);
return;
}
else if (d.Type == Models.DecoratorType.RemoteBranchHead)
{
var rb = _repo.Branches.Find(x => x.FriendlyName == d.Name);
if (rb == null)
continue;
var lb = _repo.Branches.Find(x => x.IsLocal && x.Upstream == rb.FullName);
if (lb is { TrackStatus.Ahead.Count: 0 })
{ {
_repo.CheckoutBranch(b); if (_repo.CanCreatePopup())
_repo.ShowPopup(new CheckoutAndFastForward(_repo, lb, rb));
return; return;
} }
}
else if (d.Type == Models.DecoratorType.RemoteBranchHead && firstRemoteBranch == null) firstRemoteBranch ??= rb;
{
firstRemoteBranch = _repo.Branches.Find(x => x.FriendlyName == d.Name);
} }
} }
@ -334,7 +388,7 @@ namespace SourceGit.ViewModels
log = _repo.CreateLog("Save as Patch"); log = _repo.CreateLog("Save as Patch");
var folder = picker[0]; var folder = picker[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString(); var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var succ = false; var succ = false;
for (var i = 0; i < selected.Count; i++) for (var i = 0; i < selected.Count; i++)
{ {
@ -547,9 +601,7 @@ namespace SourceGit.ViewModels
var parents = new List<Models.Commit>(); var parents = new List<Models.Commit>();
foreach (var sha in commit.Parents) foreach (var sha in commit.Parents)
{ {
var parent = _commits.Find(x => x.SHA == sha); var parent = _commits.Find(x => x.SHA == sha) ?? new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent == null)
parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent != null) if (parent != null)
parents.Add(parent); parents.Add(parent);
@ -614,6 +666,22 @@ namespace SourceGit.ViewModels
if (current.Head != commit.SHA) if (current.Head != commit.SHA)
{ {
if (current.TrackStatus.Ahead.Contains(commit.SHA))
{
var upstream = _repo.Branches.Find(x => x.FullName.Equals(current.Upstream, StringComparison.Ordinal));
var pushRevision = new MenuItem();
pushRevision.Header = App.Text("CommitCM.PushRevision", commit.SHA.Substring(0, 10), upstream.FriendlyName);
pushRevision.Icon = App.CreateMenuIcon("Icons.Push");
pushRevision.Click += (_, e) =>
{
if (_repo.CanCreatePopup())
_repo.ShowPopup(new PushRevision(_repo, commit, upstream));
e.Handled = true;
};
menu.Items.Add(pushRevision);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var compareWithHead = new MenuItem(); var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("CommitCM.CompareWithHead"); compareWithHead.Header = App.Text("CommitCM.CompareWithHead");
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare"); compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
@ -694,7 +762,7 @@ namespace SourceGit.ViewModels
log = _repo.CreateLog("Save as Patch"); log = _repo.CreateLog("Save as Patch");
var folder = selected[0]; var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString(); var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var saveTo = GetPatchFileName(folderPath, commit); var saveTo = GetPatchFileName(folderPath, commit);
var succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).Exec()); var succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).Exec());
if (succ) if (succ)
@ -809,116 +877,17 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
private Models.FilterMode GetFilterMode(string pattern)
{
foreach (var filter in _repo.Settings.HistoriesFilters)
{
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
return filter.Mode;
}
return Models.FilterMode.None;
}
private void FillBranchVisibilityMenu(MenuItem submenu, Models.Branch branch)
{
var visibility = new MenuItem();
visibility.Icon = App.CreateMenuIcon("Icons.Eye");
visibility.Header = App.Text("Repository.FilterCommits");
var exclude = new MenuItem();
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
exclude.Click += (_, e) =>
{
_repo.SetBranchFilterMode(branch, Models.FilterMode.Excluded, false, true);
e.Handled = true;
};
var filterMode = GetFilterMode(branch.FullName);
if (filterMode == Models.FilterMode.None)
{
var include = new MenuItem();
include.Icon = App.CreateMenuIcon("Icons.Filter");
include.Header = App.Text("Repository.FilterCommits.Include");
include.Click += (_, e) =>
{
_repo.SetBranchFilterMode(branch, Models.FilterMode.Included, false, true);
e.Handled = true;
};
visibility.Items.Add(include);
visibility.Items.Add(exclude);
}
else
{
var unset = new MenuItem();
unset.Header = App.Text("Repository.FilterCommits.Default");
unset.Click += (_, e) =>
{
_repo.SetBranchFilterMode(branch, Models.FilterMode.None, false, true);
e.Handled = true;
};
visibility.Items.Add(exclude);
visibility.Items.Add(unset);
}
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
}
private void FillTagVisibilityMenu(MenuItem submenu, Models.Tag tag)
{
var visibility = new MenuItem();
visibility.Icon = App.CreateMenuIcon("Icons.Eye");
visibility.Header = App.Text("Repository.FilterCommits");
var exclude = new MenuItem();
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
exclude.Click += (_, e) =>
{
_repo.SetTagFilterMode(tag, Models.FilterMode.Excluded);
e.Handled = true;
};
var filterMode = GetFilterMode(tag.Name);
if (filterMode == Models.FilterMode.None)
{
var include = new MenuItem();
include.Icon = App.CreateMenuIcon("Icons.Filter");
include.Header = App.Text("Repository.FilterCommits.Include");
include.Click += (_, e) =>
{
_repo.SetTagFilterMode(tag, Models.FilterMode.Included);
e.Handled = true;
};
visibility.Items.Add(include);
visibility.Items.Add(exclude);
}
else
{
var unset = new MenuItem();
unset.Header = App.Text("Repository.FilterCommits.Default");
unset.Click += (_, e) =>
{
_repo.SetTagFilterMode(tag, Models.FilterMode.None);
e.Handled = true;
};
visibility.Items.Add(exclude);
visibility.Items.Add(unset);
}
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
}
private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current) private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current)
{ {
var submenu = new MenuItem(); var submenu = new MenuItem();
submenu.Icon = App.CreateMenuIcon("Icons.Branch"); submenu.Icon = App.CreateMenuIcon("Icons.Branch");
submenu.Header = current.Name; submenu.Header = current.Name;
FillBranchVisibilityMenu(submenu, current); var visibility = new MenuItem();
visibility.Classes.Add("filter_mode_switcher");
visibility.Header = new FilterModeInGraph(_repo, current);
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
if (!string.IsNullOrEmpty(current.Upstream)) if (!string.IsNullOrEmpty(current.Upstream))
{ {
@ -1015,7 +984,11 @@ namespace SourceGit.ViewModels
submenu.Icon = App.CreateMenuIcon("Icons.Branch"); submenu.Icon = App.CreateMenuIcon("Icons.Branch");
submenu.Header = branch.Name; submenu.Header = branch.Name;
FillBranchVisibilityMenu(submenu, branch); var visibility = new MenuItem();
visibility.Classes.Add("filter_mode_switcher");
visibility.Header = new FilterModeInGraph(_repo, branch);
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
if (!_repo.IsBare) if (!_repo.IsBare)
{ {
@ -1105,7 +1078,11 @@ namespace SourceGit.ViewModels
submenu.Icon = App.CreateMenuIcon("Icons.Branch"); submenu.Icon = App.CreateMenuIcon("Icons.Branch");
submenu.Header = name; submenu.Header = name;
FillBranchVisibilityMenu(submenu, branch); var visibility = new MenuItem();
visibility.Classes.Add("filter_mode_switcher");
visibility.Header = new FilterModeInGraph(_repo, branch);
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
var checkout = new MenuItem(); var checkout = new MenuItem();
checkout.Header = App.Text("BranchCM.Checkout", name); checkout.Header = App.Text("BranchCM.Checkout", name);
@ -1162,7 +1139,11 @@ namespace SourceGit.ViewModels
submenu.Icon = App.CreateMenuIcon("Icons.Tag"); submenu.Icon = App.CreateMenuIcon("Icons.Tag");
submenu.MinWidth = 200; submenu.MinWidth = 200;
FillTagVisibilityMenu(submenu, tag); var visibility = new MenuItem();
visibility.Classes.Add("filter_mode_switcher");
visibility.Header = new FilterModeInGraph(_repo, tag);
submenu.Items.Add(visibility);
submenu.Items.Add(new MenuItem() { Header = "-" });
var push = new MenuItem(); var push = new MenuItem();
push.Header = App.Text("TagCM.Push", tag.Name); push.Header = App.Text("TagCM.Push", tag.Name);

View file

@ -0,0 +1,180 @@
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using BitMiracle.LibTiff.Classic;
using Pfim;
namespace SourceGit.ViewModels
{
public class ImageSource
{
public Bitmap Bitmap { get; }
public long Size { get; }
public ImageSource(Bitmap bitmap, long size)
{
Bitmap = bitmap;
Size = size;
}
public static Models.ImageDecoder GetDecoder(string file)
{
var ext = (Path.GetExtension(file) ?? ".invalid_img").ToLower(CultureInfo.CurrentCulture);
switch (ext)
{
case ".ico":
case ".bmp":
case ".gif":
case ".jpg":
case ".jpeg":
case ".png":
case ".webp":
return Models.ImageDecoder.Builtin;
case ".tga":
case ".dds":
return Models.ImageDecoder.Pfim;
case ".tif":
case ".tiff":
return Models.ImageDecoder.Tiff;
default:
return Models.ImageDecoder.None;
}
}
public static ImageSource FromFile(string fullpath, Models.ImageDecoder decoder)
{
using (var stream = File.OpenRead(fullpath))
return LoadFromStream(stream, decoder);
}
public static ImageSource FromRevision(string repo, string revision, string file, Models.ImageDecoder decoder)
{
var stream = Commands.QueryFileContent.Run(repo, revision, file);
return LoadFromStream(stream, decoder);
}
public static ImageSource FromLFSObject(string repo, Models.LFSObject lfs, Models.ImageDecoder decoder)
{
if (string.IsNullOrEmpty(lfs.Oid) || lfs.Size == 0)
return new ImageSource(null, 0);
var stream = Commands.QueryFileContent.FromLFS(repo, lfs.Oid, lfs.Size);
return LoadFromStream(stream, decoder);
}
private static ImageSource LoadFromStream(Stream stream, Models.ImageDecoder decoder)
{
var size = stream.Length;
if (size > 0)
{
try
{
switch (decoder)
{
case Models.ImageDecoder.Builtin:
return DecodeWithAvalonia(stream, size);
case Models.ImageDecoder.Pfim:
return DecodeWithPfim(stream, size);
case Models.ImageDecoder.Tiff:
return DecodeWithTiff(stream, size);
}
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
}
return new ImageSource(null, 0);
}
private static ImageSource DecodeWithAvalonia(Stream stream, long size)
{
var bitmap = new Bitmap(stream);
return new ImageSource(bitmap, size);
}
private static ImageSource DecodeWithPfim(Stream stream, long size)
{
using (var pfiImage = Pfimage.FromStream(stream))
{
var data = pfiImage.Data;
var stride = pfiImage.Stride;
var pixelFormat = PixelFormats.Bgra8888;
var alphaFormat = AlphaFormat.Opaque;
switch (pfiImage.Format)
{
case ImageFormat.Rgb8:
pixelFormat = PixelFormats.Gray8;
break;
case ImageFormat.R5g5b5:
case ImageFormat.R5g5b5a1:
pixelFormat = PixelFormats.Bgr555;
break;
case ImageFormat.R5g6b5:
pixelFormat = PixelFormats.Bgr565;
break;
case ImageFormat.Rgb24:
pixelFormat = PixelFormats.Bgr24;
break;
case ImageFormat.Rgba16:
var pixels2 = pfiImage.DataLen / 2;
data = new byte[pixels2 * 4];
stride = pfiImage.Width * 4;
for (var i = 0; i < pixels2; i++)
{
var src = BitConverter.ToUInt16(pfiImage.Data, i * 2);
data[i * 4 + 0] = (byte)Math.Round((src & 0x0F) / 15F * 255); // B
data[i * 4 + 1] = (byte)Math.Round(((src >> 4) & 0x0F) / 15F * 255); // G
data[i * 4 + 2] = (byte)Math.Round(((src >> 8) & 0x0F) / 15F * 255); // R
data[i * 4 + 3] = (byte)Math.Round(((src >> 12) & 0x0F) / 15F * 255); // A
}
alphaFormat = AlphaFormat.Premul;
break;
case ImageFormat.Rgba32:
alphaFormat = AlphaFormat.Premul;
break;
default:
return new ImageSource(null, 0);
}
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
var pixelSize = new PixelSize(pfiImage.Width, pfiImage.Height);
var dpi = new Vector(96, 96);
var bitmap = new Bitmap(pixelFormat, alphaFormat, ptr, pixelSize, dpi, stride);
return new ImageSource(bitmap, size);
}
}
private static ImageSource DecodeWithTiff(Stream stream, long size)
{
using (var tiff = Tiff.ClientOpen($"{Guid.NewGuid()}.tif", "r", stream, new TiffStream()))
{
if (tiff == null)
return new ImageSource(null, 0);
var width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
var height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
var pixels = new int[width * height];
// Currently only supports image when its `BITSPERSAMPLE` is one in [1,2,4,8,16]
tiff.ReadRGBAImageOriented(width, height, pixels, Orientation.TOPLEFT);
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(pixels, 0);
var pixelSize = new PixelSize(width, height);
var dpi = new Vector(96, 96);
var bitmap = new Bitmap(PixelFormats.Rgba8888, AlphaFormat.Premul, ptr, pixelSize, dpi, width * 4);
return new ImageSource(bitmap, size);
}
}
}
}

View file

@ -4,7 +4,7 @@ namespace SourceGit.ViewModels
{ {
public abstract class InProgressContext public abstract class InProgressContext
{ {
public InProgressContext(string repo, string cmd) protected InProgressContext(string repo, string cmd)
{ {
_repo = repo; _repo = repo;
_cmd = cmd; _cmd = cmd;

View file

@ -31,7 +31,7 @@ namespace SourceGit.ViewModels
[Required(ErrorMessage = "Feature prefix is required!!!")] [Required(ErrorMessage = "Feature prefix is required!!!")]
[RegularExpression(@"^[\w\-\.]+/$", ErrorMessage = "Bad feature prefix format!")] [RegularExpression(@"^[\w\-\.]+/$", ErrorMessage = "Bad feature prefix format!")]
public string FeturePrefix public string FeaturePrefix
{ {
get => _featurePrefix; get => _featurePrefix;
set => SetProperty(ref _featurePrefix, value, true); set => SetProperty(ref _featurePrefix, value, true);

View file

@ -106,7 +106,7 @@ namespace SourceGit.ViewModels
set set
{ {
if (SetProperty(ref _selectedItem, value)) if (SetProperty(ref _selectedItem, value))
DetailContext.Commit = value != null ? value.Commit : null; DetailContext.Commit = value?.Commit;
} }
} }

View file

@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class LFSImageDiff : ObservableObject
{
public Models.LFSDiff LFS
{
get;
}
public Models.ImageDiff Image
{
get => _image;
private set => SetProperty(ref _image, value);
}
public LFSImageDiff(string repo, Models.LFSDiff lfs, Models.ImageDecoder decoder)
{
LFS = lfs;
Task.Run(() =>
{
var oldImage = ImageSource.FromLFSObject(repo, lfs.Old, decoder);
var newImage = ImageSource.FromLFSObject(repo, lfs.New, decoder);
var img = new Models.ImageDiff()
{
Old = oldImage.Bitmap,
OldFileSize = oldImage.Size,
New = newImage.Bitmap,
NewFileSize = newImage.Size
};
Dispatcher.UIThread.Invoke(() => Image = img);
});
}
private Models.ImageDiff _image;
}
}

View file

@ -65,17 +65,14 @@ namespace SourceGit.ViewModels
var repos = ActiveWorkspace.Repositories.ToArray(); var repos = ActiveWorkspace.Repositories.ToArray();
foreach (var repo in repos) foreach (var repo in repos)
{ {
var node = pref.FindNode(repo); var node = pref.FindNode(repo) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = repo, Id = repo,
Name = Path.GetFileName(repo), Name = Path.GetFileName(repo),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
OpenRepositoryInTab(node, null); OpenRepositoryInTab(node, null);
} }
@ -184,17 +181,14 @@ namespace SourceGit.ViewModels
var repos = to.Repositories.ToArray(); var repos = to.Repositories.ToArray();
foreach (var repo in repos) foreach (var repo in repos)
{ {
var node = pref.FindNode(repo); var node = pref.FindNode(repo) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = repo, Id = repo,
Name = Path.GetFileName(repo), Name = Path.GetFileName(repo),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
OpenRepositoryInTab(node, null); OpenRepositoryInTab(node, null);
} }
@ -290,23 +284,15 @@ namespace SourceGit.ViewModels
return; return;
} }
if (page == null) page ??= _activePage;
page = _activePage;
var removeIdx = Pages.IndexOf(page); var removeIdx = Pages.IndexOf(page);
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);
if (removeIdx == activeIdx) if (removeIdx == activeIdx)
{
ActivePage = Pages[removeIdx > 0 ? removeIdx - 1 : removeIdx + 1]; ActivePage = Pages[removeIdx > 0 ? removeIdx - 1 : removeIdx + 1];
CloseRepositoryInTab(page);
Pages.RemoveAt(removeIdx);
}
else
{
CloseRepositoryInTab(page);
Pages.RemoveAt(removeIdx);
}
CloseRepositoryInTab(page);
Pages.RemoveAt(removeIdx);
GC.Collect(); GC.Collect();
} }
@ -360,7 +346,7 @@ namespace SourceGit.ViewModels
if (!Path.Exists(node.Id)) if (!Path.Exists(node.Id))
{ {
App.RaiseException(node.Id, "Repository does NOT exists any more. Please remove it."); App.RaiseException(node.Id, "Repository does NOT exist any more. Please remove it.");
return; return;
} }
@ -421,7 +407,7 @@ namespace SourceGit.ViewModels
foreach (var page in Pages) foreach (var page in Pages)
{ {
var id = page.Node.Id.Replace("\\", "/"); var id = page.Node.Id.Replace('\\', '/').TrimEnd('/');
if (id == pageId) if (id == pageId)
{ {
page.Notifications.Add(notification); page.Notifications.Add(notification);

View file

@ -87,7 +87,7 @@ namespace SourceGit.ViewModels
public bool CanCreatePopup() public bool CanCreatePopup()
{ {
return _popup == null || !_popup.InProgress; return _popup is not { InProgress: true };
} }
public void StartPopup(Popup popup) public void StartPopup(Popup popup)

View file

@ -21,6 +21,12 @@ namespace SourceGit.ViewModels
set; set;
} }
public bool Edit
{
get;
set;
} = false;
public Merge(Repository repo, Models.Branch source, string into, bool forceFastForward) public Merge(Repository repo, Models.Branch source, string into, bool forceFastForward)
{ {
_repo = repo; _repo = repo;
@ -54,6 +60,7 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
ProgressDescription = $"Merging '{_sourceName}' into '{Into}' ..."; ProgressDescription = $"Merging '{_sourceName}' into '{Into}' ...";
var log = _repo.CreateLog($"Merging '{_sourceName}' into '{Into}'"); var log = _repo.CreateLog($"Merging '{_sourceName}' into '{Into}'");
@ -61,13 +68,13 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg).Use(log).Exec(); new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, Edit).Use(log).Exec();
log.Complete(); log.Complete();
var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result(); var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result();
CallUIThread(() => CallUIThread(() =>
{ {
_repo.NavigateToCommitDelayed(head); _repo.NavigateToCommit(head, true);
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
}); });
return true; return true;

View file

@ -41,6 +41,7 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
ProgressDescription = "Merge head(s) ..."; ProgressDescription = "Merge head(s) ...";
var log = _repo.CreateLog("Merge Multiple Heads"); var log = _repo.CreateLog("Merge Multiple Heads");
@ -48,7 +49,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = new Commands.Merge( new Commands.Merge(
_repo.FullPath, _repo.FullPath,
ConvertTargetToMergeSources(), ConvertTargetToMergeSources(),
AutoCommit, AutoCommit,
@ -56,7 +57,7 @@ namespace SourceGit.ViewModels
log.Complete(); log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ; return true;
}); });
} }
@ -71,12 +72,10 @@ namespace SourceGit.ViewModels
} }
else if (t is Models.Commit commit) else if (t is Models.Commit commit)
{ {
var d = commit.Decorators.Find(x => var d = commit.Decorators.Find(x => x.Type is
{ Models.DecoratorType.LocalBranchHead or
return x.Type == Models.DecoratorType.LocalBranchHead || Models.DecoratorType.RemoteBranchHead or
x.Type == Models.DecoratorType.RemoteBranchHead || Models.DecoratorType.Tag);
x.Type == Models.DecoratorType.Tag;
});
if (d != null) if (d != null)
ret.Add(d.Name); ret.Add(d.Name);

View file

@ -261,6 +261,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _useBlockNavigationInDiffView, value); set => SetProperty(ref _useBlockNavigationInDiffView, value);
} }
public int LFSImageActiveIdx
{
get => _lfsImageActiveIdx;
set => SetProperty(ref _lfsImageActiveIdx, value);
}
public Models.ChangeViewMode UnstagedChangeViewMode public Models.ChangeViewMode UnstagedChangeViewMode
{ {
get => _unstagedChangeViewMode; get => _unstagedChangeViewMode;
@ -430,16 +436,21 @@ namespace SourceGit.ViewModels
{ {
var collection = to == null ? RepositoryNodes : to.SubNodes; var collection = to == null ? RepositoryNodes : to.SubNodes;
collection.Add(node); collection.Add(node);
collection.Sort((l, r) => SortNodes(collection);
if (save)
Save();
}
public void SortNodes(List<RepositoryNode> collection)
{
collection?.Sort((l, r) =>
{ {
if (l.IsRepository != r.IsRepository) if (l.IsRepository != r.IsRepository)
return l.IsRepository ? 1 : -1; return l.IsRepository ? 1 : -1;
return string.Compare(l.Name, r.Name, StringComparison.Ordinal); return Models.NumericSort.Compare(l.Name, r.Name);
}); });
if (save)
Save();
} }
public RepositoryNode FindNode(string id) public RepositoryNode FindNode(string id)
@ -447,11 +458,9 @@ namespace SourceGit.ViewModels
return FindNodeRecursive(id, RepositoryNodes); return FindNodeRecursive(id, RepositoryNodes);
} }
public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode) public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode, bool save = true)
{ {
var normalized = repo.Replace('\\', '/'); var normalized = repo.Replace('\\', '/').TrimEnd('/');
if (normalized.EndsWith("/"))
normalized = normalized.TrimEnd('/');
var node = FindNodeRecursive(normalized, RepositoryNodes); var node = FindNodeRecursive(normalized, RepositoryNodes);
if (node == null) if (node == null)
@ -464,11 +473,11 @@ namespace SourceGit.ViewModels
IsRepository = true, IsRepository = true,
}; };
AddNode(node, parent, true); AddNode(node, parent, save);
} }
else if (shouldMoveNode) else if (shouldMoveNode)
{ {
MoveNode(node, parent, true); MoveNode(node, parent, save);
} }
return node; return node;
@ -499,22 +508,13 @@ namespace SourceGit.ViewModels
public void SortByRenamedNode(RepositoryNode node) public void SortByRenamedNode(RepositoryNode node)
{ {
var container = FindNodeContainer(node, RepositoryNodes); var container = FindNodeContainer(node, RepositoryNodes);
container?.Sort((l, r) => SortNodes(container);
{
if (l.IsRepository != r.IsRepository)
return l.IsRepository ? 1 : -1;
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
});
Save(); Save();
} }
public void AutoRemoveInvalidNode() public void AutoRemoveInvalidNode()
{ {
var changed = RemoveInvalidRepositoriesRecursive(RepositoryNodes); RemoveInvalidRepositoriesRecursive(RepositoryNodes);
if (changed)
Save();
} }
public void Save() public void Save()
@ -584,6 +584,13 @@ namespace SourceGit.ViewModels
} }
} }
private void SortNodesRecursive(List<RepositoryNode> collection)
{
SortNodes(collection);
foreach (var node in collection)
SortNodesRecursive(node.SubNodes);
}
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection) private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
{ {
foreach (var node in collection) foreach (var node in collection)
@ -661,7 +668,7 @@ namespace SourceGit.ViewModels
private string _themeOverrides = string.Empty; private string _themeOverrides = string.Empty;
private string _defaultFontFamily = string.Empty; private string _defaultFontFamily = string.Empty;
private string _monospaceFontFamily = string.Empty; private string _monospaceFontFamily = string.Empty;
private bool _onlyUseMonoFontInEditor = false; private bool _onlyUseMonoFontInEditor = true;
private double _defaultFontSize = 13; private double _defaultFontSize = 13;
private double _editorFontSize = 13; private double _editorFontSize = 13;
private int _editorTabWidth = 4; private int _editorTabWidth = 4;
@ -687,6 +694,7 @@ namespace SourceGit.ViewModels
private bool _showHiddenSymbolsInDiffView = false; private bool _showHiddenSymbolsInDiffView = false;
private bool _useFullTextDiff = false; private bool _useFullTextDiff = false;
private bool _useBlockNavigationInDiffView = false; private bool _useBlockNavigationInDiffView = false;
private int _lfsImageActiveIdx = 0;
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List; private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List; private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;

View file

@ -7,7 +7,7 @@ namespace SourceGit.ViewModels
public class Pull : Popup public class Pull : Popup
{ {
public List<Models.Remote> Remotes => _repo.Remotes; public List<Models.Remote> Remotes => _repo.Remotes;
public Models.Branch Current => _current; public Models.Branch Current { get; }
public bool HasSpecifiedRemoteBranch public bool HasSpecifiedRemoteBranch
{ {
@ -64,7 +64,7 @@ namespace SourceGit.ViewModels
public Pull(Repository repo, Models.Branch specifiedRemoteBranch) public Pull(Repository repo, Models.Branch specifiedRemoteBranch)
{ {
_repo = repo; _repo = repo;
_current = repo.CurrentBranch; Current = repo.CurrentBranch;
if (specifiedRemoteBranch != null) if (specifiedRemoteBranch != null)
{ {
@ -84,12 +84,12 @@ namespace SourceGit.ViewModels
else else
{ {
var autoSelectedRemote = null as Models.Remote; var autoSelectedRemote = null as Models.Remote;
if (!string.IsNullOrEmpty(_current.Upstream)) if (!string.IsNullOrEmpty(Current.Upstream))
{ {
var remoteNameEndIdx = _current.Upstream.IndexOf('/', 13); var remoteNameEndIdx = Current.Upstream.IndexOf('/', 13);
if (remoteNameEndIdx > 0) if (remoteNameEndIdx > 0)
{ {
var remoteName = _current.Upstream.Substring(13, remoteNameEndIdx - 13); var remoteName = Current.Upstream.Substring(13, remoteNameEndIdx - 13);
autoSelectedRemote = _repo.Remotes.Find(x => x.Name == remoteName); autoSelectedRemote = _repo.Remotes.Find(x => x.Name == remoteName);
} }
} }
@ -146,7 +146,7 @@ namespace SourceGit.ViewModels
bool rs = new Commands.Pull( bool rs = new Commands.Pull(
_repo.FullPath, _repo.FullPath,
_selectedRemote.Name, _selectedRemote.Name,
!string.IsNullOrEmpty(_current.Upstream) && _current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name, !string.IsNullOrEmpty(Current.Upstream) && Current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name,
UseRebase).Use(log).Exec(); UseRebase).Use(log).Exec();
if (rs) if (rs)
@ -167,7 +167,7 @@ namespace SourceGit.ViewModels
var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result(); var head = new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").Result();
CallUIThread(() => CallUIThread(() =>
{ {
_repo.NavigateToCommitDelayed(head); _repo.NavigateToCommit(head, true);
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
}); });
@ -188,12 +188,12 @@ namespace SourceGit.ViewModels
RemoteBranches = branches; RemoteBranches = branches;
var autoSelectedBranch = false; var autoSelectedBranch = false;
if (!string.IsNullOrEmpty(_current.Upstream) && if (!string.IsNullOrEmpty(Current.Upstream) &&
_current.Upstream.StartsWith($"refs/remotes/{remoteName}/", System.StringComparison.Ordinal)) Current.Upstream.StartsWith($"refs/remotes/{remoteName}/", System.StringComparison.Ordinal))
{ {
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (_current.Upstream == branch.FullName) if (Current.Upstream == branch.FullName)
{ {
SelectedBranch = branch; SelectedBranch = branch;
autoSelectedBranch = true; autoSelectedBranch = true;
@ -206,7 +206,7 @@ namespace SourceGit.ViewModels
{ {
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (_current.Name == branch.Name) if (Current.Name == branch.Name)
{ {
SelectedBranch = branch; SelectedBranch = branch;
autoSelectedBranch = true; autoSelectedBranch = true;
@ -220,7 +220,6 @@ namespace SourceGit.ViewModels
} }
private readonly Repository _repo = null; private readonly Repository _repo = null;
private readonly Models.Branch _current = null;
private Models.Remote _selectedRemote = null; private Models.Remote _selectedRemote = null;
private List<Models.Branch> _remoteBranches = null; private List<Models.Branch> _remoteBranches = null;
private Models.Branch _selectedBranch = null; private Models.Branch _selectedBranch = null;

View file

@ -0,0 +1,59 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class PushRevision : Popup
{
public Models.Commit Revision
{
get;
}
public Models.Branch RemoteBranch
{
get;
}
public bool Force
{
get;
set;
}
public PushRevision(Repository repo, Models.Commit revision, Models.Branch remoteBranch)
{
_repo = repo;
Revision = revision;
RemoteBranch = remoteBranch;
Force = false;
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Push {Revision.SHA.Substring(0, 10)} -> {RemoteBranch.FriendlyName} ...";
var log = _repo.CreateLog("Push Revision");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Push(
_repo.FullPath,
Revision.SHA,
RemoteBranch.Remote,
RemoteBranch.Name,
false,
false,
false,
Force).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
}
private readonly Repository _repo;
}
}

View file

@ -43,6 +43,7 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
ProgressDescription = "Rebasing ..."; ProgressDescription = "Rebasing ...";
var log = _repo.CreateLog("Rebase"); var log = _repo.CreateLog("Rebase");

View file

@ -30,7 +30,7 @@ namespace SourceGit.ViewModels
{ {
if (value != null) if (value != null)
{ {
var normalized = value.Replace('\\', '/'); var normalized = value.Replace('\\', '/').TrimEnd('/');
SetProperty(ref _fullpath, normalized); SetProperty(ref _fullpath, normalized);
} }
else else
@ -127,12 +127,12 @@ namespace SourceGit.ViewModels
public bool OnlyHighlightCurrentBranchInHistories public bool OnlyHighlightCurrentBranchInHistories
{ {
get => _settings.OnlyHighlighCurrentBranchInHistories; get => _settings.OnlyHighlightCurrentBranchInHistories;
set set
{ {
if (value != _settings.OnlyHighlighCurrentBranchInHistories) if (value != _settings.OnlyHighlightCurrentBranchInHistories)
{ {
_settings.OnlyHighlighCurrentBranchInHistories = value; _settings.OnlyHighlightCurrentBranchInHistories = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -172,7 +172,7 @@ namespace SourceGit.ViewModels
private set private set
{ {
var oldHead = _currentBranch?.Head; var oldHead = _currentBranch?.Head;
if (SetProperty(ref _currentBranch, value)) if (SetProperty(ref _currentBranch, value) && value != null)
{ {
if (oldHead != _currentBranch.Head && _workingCopy is { UseAmend: true }) if (oldHead != _currentBranch.Head && _workingCopy is { UseAmend: true })
_workingCopy.UseAmend = false; _workingCopy.UseAmend = false;
@ -434,6 +434,21 @@ namespace SourceGit.ViewModels
} }
} }
public bool IsSortingLocalBranchByName
{
get => _settings.LocalBranchSortMode == Models.BranchSortMode.Name;
}
public bool IsSortingRemoteBranchByName
{
get => _settings.RemoteBranchSortMode == Models.BranchSortMode.Name;
}
public bool IsSortingTagsByName
{
get => _settings.TagSortMode == Models.TagSortMode.Name;
}
public InProgressContext InProgressContext public InProgressContext InProgressContext
{ {
get => _workingCopy?.InProgressContext; get => _workingCopy?.InProgressContext;
@ -499,7 +514,7 @@ namespace SourceGit.ViewModels
{ {
// For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR. // For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR.
var gitDirForWatcher = _gitDir; var gitDirForWatcher = _gitDir;
if (_gitDir.Replace("\\", "/").IndexOf("/worktrees/", StringComparison.Ordinal) > 0) if (_gitDir.Replace('\\', '/').IndexOf("/worktrees/", StringComparison.Ordinal) > 0)
{ {
var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result();
if (!string.IsNullOrEmpty(commonDir)) if (!string.IsNullOrEmpty(commonDir))
@ -721,11 +736,8 @@ namespace SourceGit.ViewModels
{ {
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
foreach (var url in urls) foreach (var (name, addr) in urls)
{ {
var name = url.Key;
var addr = url.Value;
var item = new MenuItem(); var item = new MenuItem();
item.Header = App.Text("Repository.Visit", name); item.Header = App.Text("Repository.Visit", name);
item.Icon = App.CreateMenuIcon("Icons.Remotes"); item.Icon = App.CreateMenuIcon("Icons.Remotes");
@ -772,7 +784,7 @@ namespace SourceGit.ViewModels
if (_currentBranch == null) if (_currentBranch == null)
{ {
App.RaiseException(_fullpath, "Can NOT found current branch!!!"); App.RaiseException(_fullpath, "Can NOT find current branch!!!");
return; return;
} }
@ -796,7 +808,7 @@ namespace SourceGit.ViewModels
if (_currentBranch == null) if (_currentBranch == null)
{ {
App.RaiseException(_fullpath, "Can NOT found current branch!!!"); App.RaiseException(_fullpath, "Can NOT find current branch!!!");
return; return;
} }
@ -913,24 +925,23 @@ namespace SourceGit.ViewModels
_lastFetchTime = DateTime.Now; _lastFetchTime = DateTime.Now;
} }
public void NavigateToCommit(string sha) public void NavigateToCommit(string sha, bool isDelayMode = false)
{ {
if (_histories != null) if (isDelayMode)
{
_navigateToCommitDelayed = sha;
}
else if (_histories != null)
{ {
SelectedViewIndex = 0; SelectedViewIndex = 0;
_histories.NavigateTo(sha); _histories.NavigateTo(sha);
} }
} }
public void NavigateToCommitDelayed(string sha) public void ClearCommitMessage()
{ {
_navigateToCommitDelayed = sha; if (_workingCopy is not null)
} _workingCopy.CommitMessage = string.Empty;
public void NavigateToCurrentHead()
{
if (_currentBranch != null)
NavigateToCommit(_currentBranch.Head);
} }
public void ClearHistoriesFilter() public void ClearHistoriesFilter()
@ -1079,6 +1090,7 @@ namespace SourceGit.ViewModels
var succ = new Commands.Bisect(_fullpath, subcmd).Use(log).Exec(); var succ = new Commands.Bisect(_fullpath, subcmd).Use(log).Exec();
log.Complete(); log.Complete();
var head = new Commands.QueryRevisionByRefName(_fullpath, "HEAD").Result();
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
if (!succ) if (!succ)
@ -1087,6 +1099,7 @@ namespace SourceGit.ViewModels
App.SendNotification(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim()); App.SendNotification(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim());
MarkBranchesDirtyManually(); MarkBranchesDirtyManually();
NavigateToCommit(head, true);
SetWatcherEnabled(true); SetWatcherEnabled(true);
IsBisectCommandRunning = false; IsBisectCommandRunning = false;
}); });
@ -1120,7 +1133,8 @@ namespace SourceGit.ViewModels
if (_workingCopy != null) if (_workingCopy != null)
_workingCopy.HasRemotes = remotes.Count > 0; _workingCopy.HasRemotes = remotes.Count > 0;
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !CurrentBranch.TrackStatus.IsVisible); var hasPendingPullOrPush = CurrentBranch?.TrackStatus.IsVisible ?? false;
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !hasPendingPullOrPush);
}); });
} }
@ -1259,6 +1273,7 @@ namespace SourceGit.ViewModels
if (_workingCopy == null) if (_workingCopy == null)
return; return;
changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
_workingCopy.SetData(changes); _workingCopy.SetData(changes);
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
@ -1288,7 +1303,7 @@ namespace SourceGit.ViewModels
{ {
if (_currentBranch == null) if (_currentBranch == null)
{ {
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit."); App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
return; return;
} }
@ -1300,7 +1315,7 @@ namespace SourceGit.ViewModels
{ {
if (branch.IsLocal) if (branch.IsLocal)
{ {
var worktree = _worktrees.Find(x => x.Branch == branch.FullName); var worktree = _worktrees.Find(x => x.Branch.Equals(branch.FullName, StringComparison.Ordinal));
if (worktree != null) if (worktree != null)
{ {
OpenWorktree(worktree); OpenWorktree(worktree);
@ -1325,9 +1340,13 @@ namespace SourceGit.ViewModels
{ {
foreach (var b in _branches) foreach (var b in _branches)
{ {
if (b.IsLocal && b.Upstream == branch.FullName) if (b.IsLocal &&
b.Upstream.Equals(branch.FullName, StringComparison.Ordinal) &&
b.TrackStatus.Ahead.Count == 0)
{ {
if (!b.IsCurrent) if (b.TrackStatus.Behind.Count > 0)
ShowPopup(new CheckoutAndFastForward(this, b, branch));
else if (!b.IsCurrent)
CheckoutBranch(b); CheckoutBranch(b);
return; return;
@ -1338,6 +1357,12 @@ namespace SourceGit.ViewModels
} }
} }
public void DeleteBranch(Models.Branch branch)
{
if (CanCreatePopup())
ShowPopup(new DeleteBranch(this, branch));
}
public void DeleteMultipleBranches(List<Models.Branch> branches, bool isLocal) public void DeleteMultipleBranches(List<Models.Branch> branches, bool isLocal)
{ {
if (CanCreatePopup()) if (CanCreatePopup())
@ -1354,7 +1379,7 @@ namespace SourceGit.ViewModels
{ {
if (_currentBranch == null) if (_currentBranch == null)
{ {
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit."); App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
return; return;
} }
@ -1362,12 +1387,24 @@ namespace SourceGit.ViewModels
ShowPopup(new CreateTag(this, _currentBranch)); ShowPopup(new CreateTag(this, _currentBranch));
} }
public void DeleteTag(Models.Tag tag)
{
if (CanCreatePopup())
ShowPopup(new DeleteTag(this, tag));
}
public void AddRemote() public void AddRemote()
{ {
if (CanCreatePopup()) if (CanCreatePopup())
ShowPopup(new AddRemote(this)); ShowPopup(new AddRemote(this));
} }
public void DeleteRemote(Models.Remote remote)
{
if (CanCreatePopup())
ShowPopup(new DeleteRemote(this, remote));
}
public void AddSubmodule() public void AddSubmodule()
{ {
if (CanCreatePopup()) if (CanCreatePopup())
@ -1387,21 +1424,18 @@ namespace SourceGit.ViewModels
return; return;
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule)); var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
var normalizedPath = root.Replace("\\", "/"); var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
var node = Preferences.Instance.FindNode(normalizedPath); var node = Preferences.Instance.FindNode(normalizedPath) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = normalizedPath, Id = normalizedPath,
Name = Path.GetFileName(normalizedPath), Name = Path.GetFileName(normalizedPath),
Bookmark = selfPage.Node.Bookmark, Bookmark = selfPage.Node.Bookmark,
IsRepository = true, IsRepository = true,
}; };
}
App.GetLauncer().OpenRepositoryInTab(node, null); App.GetLauncher().OpenRepositoryInTab(node, null);
} }
public void AddWorktree() public void AddWorktree()
@ -1418,22 +1452,19 @@ namespace SourceGit.ViewModels
public void OpenWorktree(Models.Worktree worktree) public void OpenWorktree(Models.Worktree worktree)
{ {
var node = Preferences.Instance.FindNode(worktree.FullPath); var node = Preferences.Instance.FindNode(worktree.FullPath) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = worktree.FullPath, Id = worktree.FullPath,
Name = Path.GetFileName(worktree.FullPath), Name = Path.GetFileName(worktree.FullPath),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
App.GetLauncer()?.OpenRepositoryInTab(node, null); App.GetLauncher()?.OpenRepositoryInTab(node, null);
} }
public List<Models.OpenAIService> GetPreferedOpenAIServices() public List<Models.OpenAIService> GetPreferredOpenAIServices()
{ {
var services = Preferences.Instance.OpenAIServices; var services = Preferences.Instance.OpenAIServices;
if (services == null || services.Count == 0) if (services == null || services.Count == 0)
@ -1442,11 +1473,11 @@ namespace SourceGit.ViewModels
if (services.Count == 1) if (services.Count == 1)
return [services[0]]; return [services[0]];
var prefered = _settings.PreferedOpenAIService; var preferred = _settings.PreferredOpenAIService;
var all = new List<Models.OpenAIService>(); var all = new List<Models.OpenAIService>();
foreach (var service in services) foreach (var service in services)
{ {
if (service.Name.Equals(prefered, StringComparison.Ordinal)) if (service.Name.Equals(preferred, StringComparison.Ordinal))
return [service]; return [service];
all.Add(service); all.Add(service);
@ -2209,7 +2240,7 @@ namespace SourceGit.ViewModels
} }
var compareWithHead = new MenuItem(); var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("BranchCM.CompareWithHead"); compareWithHead.Header = App.Text("BranchCM.CompareWithCurrent", _currentBranch.Name);
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare"); compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
compareWithHead.Click += (_, _) => compareWithHead.Click += (_, _) =>
{ {
@ -2380,9 +2411,15 @@ namespace SourceGit.ViewModels
var changeMode = new Action<Models.BranchSortMode>(m => var changeMode = new Action<Models.BranchSortMode>(m =>
{ {
if (local) if (local)
{
_settings.LocalBranchSortMode = m; _settings.LocalBranchSortMode = m;
OnPropertyChanged(nameof(IsSortingLocalBranchByName));
}
else else
{
_settings.RemoteBranchSortMode = m; _settings.RemoteBranchSortMode = m;
OnPropertyChanged(nameof(IsSortingRemoteBranchByName));
}
var builder = BuildBranchTree(_branches, _remotes); var builder = BuildBranchTree(_branches, _remotes);
LocalBranchTrees = builder.Locals; LocalBranchTrees = builder.Locals;
@ -2414,6 +2451,7 @@ namespace SourceGit.ViewModels
}; };
var menu = new ContextMenu(); var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
menu.Items.Add(byNameAsc); menu.Items.Add(byNameAsc);
menu.Items.Add(byCommitterDate); menu.Items.Add(byCommitterDate);
return menu; return menu;
@ -2422,11 +2460,12 @@ namespace SourceGit.ViewModels
public ContextMenu CreateContextMenuForTagSortMode() public ContextMenu CreateContextMenuForTagSortMode()
{ {
var mode = _settings.TagSortMode; var mode = _settings.TagSortMode;
var changeMode = new Action<Models.TagSortMode>((m) => var changeMode = new Action<Models.TagSortMode>(m =>
{ {
if (_settings.TagSortMode != m) if (_settings.TagSortMode != m)
{ {
_settings.TagSortMode = m; _settings.TagSortMode = m;
OnPropertyChanged(nameof(IsSortingTagsByName));
VisibleTags = BuildVisibleTags(); VisibleTags = BuildVisibleTags();
} }
}); });
@ -2441,30 +2480,20 @@ namespace SourceGit.ViewModels
ev.Handled = true; ev.Handled = true;
}; };
var byNameAsc = new MenuItem(); var byName = new MenuItem();
byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc"); byName.Header = App.Text("Repository.Tags.OrderByName");
if (mode == Models.TagSortMode.NameInAscending) if (mode == Models.TagSortMode.Name)
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check"); byName.Icon = App.CreateMenuIcon("Icons.Check");
byNameAsc.Click += (_, ev) => byName.Click += (_, ev) =>
{ {
changeMode(Models.TagSortMode.NameInAscending); changeMode(Models.TagSortMode.Name);
ev.Handled = true;
};
var byNameDes = new MenuItem();
byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes");
if (mode == Models.TagSortMode.NameInDescending)
byNameDes.Icon = App.CreateMenuIcon("Icons.Check");
byNameDes.Click += (_, ev) =>
{
changeMode(Models.TagSortMode.NameInDescending);
ev.Handled = true; ev.Handled = true;
}; };
var menu = new ContextMenu(); var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
menu.Items.Add(byCreatorDate); menu.Items.Add(byCreatorDate);
menu.Items.Add(byNameAsc); menu.Items.Add(byName);
menu.Items.Add(byNameDes);
return menu; return menu;
} }
@ -2588,7 +2617,7 @@ namespace SourceGit.ViewModels
private LauncherPage GetOwnerPage() private LauncherPage GetOwnerPage()
{ {
var launcher = App.GetLauncer(); var launcher = App.GetLauncher();
if (launcher == null) if (launcher == null)
return null; return null;
@ -2637,11 +2666,8 @@ namespace SourceGit.ViewModels
case Models.TagSortMode.CreatorDate: case Models.TagSortMode.CreatorDate:
_tags.Sort((l, r) => r.CreatorDate.CompareTo(l.CreatorDate)); _tags.Sort((l, r) => r.CreatorDate.CompareTo(l.CreatorDate));
break; break;
case Models.TagSortMode.NameInAscending:
_tags.Sort((l, r) => Models.NumericSort.Compare(l.Name, r.Name));
break;
default: default:
_tags.Sort((l, r) => Models.NumericSort.Compare(r.Name, l.Name)); _tags.Sort((l, r) => Models.NumericSort.Compare(l.Name, r.Name));
break; break;
} }
@ -2712,10 +2738,7 @@ namespace SourceGit.ViewModels
{ {
foreach (var node in nodes) foreach (var node in nodes)
{ {
if (filters.TryGetValue(node.Path, out var value)) node.FilterMode = filters.GetValueOrDefault(node.Path, Models.FilterMode.None);
node.FilterMode = value;
else
node.FilterMode = Models.FilterMode.None;
if (!node.IsBranch) if (!node.IsBranch)
UpdateBranchTreeFilterMode(node.Children, filters); UpdateBranchTreeFilterMode(node.Children, filters);
@ -2726,10 +2749,7 @@ namespace SourceGit.ViewModels
{ {
foreach (var tag in _tags) foreach (var tag in _tags)
{ {
if (filters.TryGetValue(tag.Name, out var value)) tag.FilterMode = filters.GetValueOrDefault(tag.Name, Models.FilterMode.None);
tag.FilterMode = value;
else
tag.FilterMode = Models.FilterMode.None;
} }
} }
@ -2918,7 +2938,7 @@ namespace SourceGit.ViewModels
private List<string> _matchedFilesForSearching = null; private List<string> _matchedFilesForSearching = null;
private string _filter = string.Empty; private string _filter = string.Empty;
private object _lockRemotes = new object(); private readonly Lock _lockRemotes = new();
private List<Models.Remote> _remotes = new List<Models.Remote>(); private List<Models.Remote> _remotes = new List<Models.Remote>();
private List<Models.Branch> _branches = new List<Models.Branch>(); private List<Models.Branch> _branches = new List<Models.Branch>();
private Models.Branch _currentBranch = null; private Models.Branch _currentBranch = null;

View file

@ -127,10 +127,10 @@ namespace SourceGit.ViewModels
private set; private set;
} }
public string PreferedOpenAIService public string PreferredOpenAIService
{ {
get => _repo.Settings.PreferedOpenAIService; get => _repo.Settings.PreferredOpenAIService;
set => _repo.Settings.PreferedOpenAIService = value; set => _repo.Settings.PreferredOpenAIService = value;
} }
public AvaloniaList<Models.CustomAction> CustomActions public AvaloniaList<Models.CustomAction> CustomActions
@ -156,8 +156,8 @@ namespace SourceGit.ViewModels
foreach (var service in Preferences.Instance.OpenAIServices) foreach (var service in Preferences.Instance.OpenAIServices)
AvailableOpenAIServices.Add(service.Name); AvailableOpenAIServices.Add(service.Name);
if (AvailableOpenAIServices.IndexOf(PreferedOpenAIService) == -1) if (!AvailableOpenAIServices.Contains(PreferredOpenAIService))
PreferedOpenAIService = "---"; PreferredOpenAIService = "---";
_cached = new Commands.Config(repo.FullPath).ListAll(); _cached = new Commands.Config(repo.FullPath).ListAll();
if (_cached.TryGetValue("user.name", out var name)) if (_cached.TryGetValue("user.name", out var name))
@ -304,6 +304,18 @@ namespace SourceGit.ViewModels
SelectedCustomAction = null; SelectedCustomAction = null;
} }
public void MoveSelectedCustomActionUp()
{
if (_selectedCustomAction != null)
_repo.Settings.MoveCustomActionUp(_selectedCustomAction);
}
public void MoveSelectedCustomActionDown()
{
if (_selectedCustomAction != null)
_repo.Settings.MoveCustomActionDown(_selectedCustomAction);
}
public void Save() public void Save()
{ {
SetIfChanged("user.name", UserName, ""); SetIfChanged("user.name", UserName, "");

View file

@ -13,7 +13,7 @@ namespace SourceGit.ViewModels
get => _id; get => _id;
set set
{ {
var normalized = value.Replace('\\', '/'); var normalized = value.Replace('\\', '/').TrimEnd('/');
SetProperty(ref _id, normalized); SetProperty(ref _id, normalized);
} }
} }
@ -70,14 +70,14 @@ namespace SourceGit.ViewModels
public void Edit() public void Edit()
{ {
var activePage = App.GetLauncer().ActivePage; var activePage = App.GetLauncher().ActivePage;
if (activePage != null && activePage.CanCreatePopup()) if (activePage != null && activePage.CanCreatePopup())
activePage.Popup = new EditRepositoryNode(this); activePage.Popup = new EditRepositoryNode(this);
} }
public void AddSubFolder() public void AddSubFolder()
{ {
var activePage = App.GetLauncer().ActivePage; var activePage = App.GetLauncher().ActivePage;
if (activePage != null && activePage.CanCreatePopup()) if (activePage != null && activePage.CanCreatePopup())
activePage.Popup = new CreateGroup(this); activePage.Popup = new CreateGroup(this);
} }
@ -98,7 +98,7 @@ namespace SourceGit.ViewModels
public void Delete() public void Delete()
{ {
var activePage = App.GetLauncer().ActivePage; var activePage = App.GetLauncher().ActivePage;
if (activePage != null && activePage.CanCreatePopup()) if (activePage != null && activePage.CanCreatePopup())
activePage.Popup = new DeleteRepositoryNode(this); activePage.Popup = new DeleteRepositoryNode(this);
} }

Some files were not shown because too many files have changed in this diff Show more