Compare commits
99 Commits
pre-0.41
...
fix-skip-h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8cffa314e | ||
|
|
4ec41c4414 | ||
|
|
b2ff09ec0c | ||
|
|
dd6bfa1680 | ||
|
|
0a5e9b2d60 | ||
|
|
8b99a3c949 | ||
|
|
af6d072cc6 | ||
|
|
7270dea48d | ||
|
|
69153acfdb | ||
|
|
b4fbfd20cb | ||
|
|
ef99e47d09 | ||
|
|
580818e935 | ||
|
|
1c098ff82a | ||
|
|
34f8f7293c | ||
|
|
caad553502 | ||
|
|
723b92916d | ||
|
|
653994845e | ||
|
|
bbad3a70ce | ||
|
|
1869fda800 | ||
|
|
5396a70661 | ||
|
|
82a3d33ce3 | ||
|
|
325800a72e | ||
|
|
9f8ae76189 | ||
|
|
8a77e51576 | ||
|
|
145795c0b0 | ||
|
|
cbe6dd7b2f | ||
|
|
b6ca9090f4 | ||
|
|
5d13e3cf76 | ||
|
|
9e5ceaa1ec | ||
|
|
ba0c00b5d1 | ||
|
|
145fb6191c | ||
|
|
7e14d88dc9 | ||
|
|
e6a07b3f03 | ||
|
|
28923fc9d0 | ||
|
|
19bef17042 | ||
|
|
170c4ecb8c | ||
|
|
de1c495704 | ||
|
|
fccfbf1f63 | ||
|
|
05fb12b1d5 | ||
|
|
9cf1ca10a2 | ||
|
|
dc6863b83d | ||
|
|
13af335b37 | ||
|
|
92aab21d3a | ||
|
|
e6ef1642fa | ||
|
|
84333eebc3 | ||
|
|
7f6eea2a55 | ||
|
|
06624e85d6 | ||
|
|
5616d6a9bc | ||
|
|
5c3aacb4cb | ||
|
|
2b5c814080 | ||
|
|
4ba85608c8 | ||
|
|
a63c660f28 | ||
|
|
fab7ca2b58 | ||
|
|
7b0e06d885 | ||
|
|
426375b7cd | ||
|
|
f933a2f7ec | ||
|
|
ed61b9a7f2 | ||
|
|
d8c1eb879b | ||
|
|
c02408bba0 | ||
|
|
f3dba743f0 | ||
|
|
53f0c4aeff | ||
|
|
84e82ea8b6 | ||
|
|
8487bc397d | ||
|
|
93aee0dca0 | ||
|
|
4d8b8b647a | ||
|
|
2385c1d111 | ||
|
|
5d509efe19 | ||
|
|
b9a75ee0ed | ||
|
|
d102f12304 | ||
|
|
6396d1ce03 | ||
|
|
c59e6b6451 | ||
|
|
1cedfa463b | ||
|
|
9b035aed67 | ||
|
|
ce9cdd8d78 | ||
|
|
f774b7eb5c | ||
|
|
e4b4b6d5f4 | ||
|
|
93251db67e | ||
|
|
de52a68b53 | ||
|
|
42ebf1947a | ||
|
|
c995e7ef2e | ||
|
|
04fcb78c0c | ||
|
|
bd8518355e | ||
|
|
f93cb54b5d | ||
|
|
0b70dfbf46 | ||
|
|
38876ba141 | ||
|
|
57786fbb1f | ||
|
|
e295ccefab | ||
|
|
1fdcc29277 | ||
|
|
6da9d55e47 | ||
|
|
ba85f93fb3 | ||
|
|
cdbec3997d | ||
|
|
fb675b79f8 | ||
|
|
f30be824b3 | ||
|
|
e1c3ef6629 | ||
|
|
a70bb0a7aa | ||
|
|
7718cb009b | ||
|
|
1337a943fe | ||
|
|
471ea39758 | ||
|
|
c3f0b5cb4a |
18
.github/workflows/sponsors.yml
vendored
18
.github/workflows/sponsors.yml
vendored
@@ -15,14 +15,14 @@ jobs:
|
||||
uses: JamesIves/github-sponsors-readme-action@v1.2.2
|
||||
with:
|
||||
token: ${{ secrets.SPONSORS_TOKEN }}
|
||||
file: 'README.md'
|
||||
file: "README.md"
|
||||
if: ${{ github.repository == 'jesseduffield/lazygit' }}
|
||||
|
||||
- name: Commit and push if changed
|
||||
run: |-
|
||||
git diff
|
||||
git config --global user.email "actions@users.noreply.github.com"
|
||||
git config --global user.name "README-bot"
|
||||
git add README.md
|
||||
git commit -m "Updated README.md" || exit 0
|
||||
git push
|
||||
- name: Create Pull Request 🚀
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
commit-message: "README.md: Update Sponsors"
|
||||
title: "README.md: Update Sponsors"
|
||||
author: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
|
||||
labels: "ignore-for-release"
|
||||
delete-branch: true
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,9 +6,6 @@
|
||||
# Hidden
|
||||
.*
|
||||
|
||||
# TODO
|
||||
TODO.*
|
||||
|
||||
# Notes
|
||||
*.notes
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ If you want to change the config directory:
|
||||
JSON schema is available for `config.yml` so that IntelliSense in Visual Studio Code (completion and error checking) is automatically enabled when the [YAML Red Hat][yaml] extension is installed. However, note that automatic schema detection only works if your config file is in one of the standard paths mentioned above. If you override the path to the file, you can still make IntelliSense work by adding
|
||||
|
||||
```yaml
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/lazygit.json
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/jesseduffield/lazygit/master/schema/config.json
|
||||
```
|
||||
|
||||
to the top of your config file or via [Visual Studio Code settings.json config][settings].
|
||||
@@ -87,6 +87,10 @@ gui:
|
||||
animateExplosion: true # shows an explosion animation when nuking the working tree
|
||||
portraitMode: 'auto' # one of 'auto' | 'never' | 'always'
|
||||
filterMode: 'substring' # one of 'substring' | 'fuzzy'; see 'Filtering' section below
|
||||
spinner:
|
||||
frames: ['|', '/', '-', '\\']
|
||||
rate: 50 # spinner rate in milliseconds
|
||||
statusPanelView: 'dashboard' # one of 'dashboard' | 'allBranchesLog'
|
||||
git:
|
||||
paging:
|
||||
colorArg: always
|
||||
|
||||
@@ -6,7 +6,7 @@ You can add custom command keybindings in your config.yml (accessible by pressin
|
||||
customCommands:
|
||||
- key: '<c-r>'
|
||||
context: 'commits'
|
||||
command: 'hub browse -- "commit/{{.SelectedLocalCommit.Sha}}"'
|
||||
command: 'hub browse -- "commit/{{.SelectedLocalCommit.Hash}}"'
|
||||
- key: 'a'
|
||||
context: 'files'
|
||||
command: "git {{if .SelectedFile.HasUnstagedChanges}} add {{else}} reset {{end}} {{.SelectedFile.Name | quote}}"
|
||||
@@ -305,7 +305,7 @@ SelectedWorktree
|
||||
CheckedOutBranch
|
||||
```
|
||||
|
||||
To see what fields are available on e.g. the `SelectedFile`, see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/commands/models/file.go) (all the modelling lives in the same directory). Note that the custom commands feature does not guarantee backwards compatibility (until we hit Lazygit version 1.0 of course) which means a field you're accessing on an object may no longer be available from one release to the next. Typically however, all you'll need is `{{.SelectedFile.Name}}`, `{{.SelectedLocalCommit.Sha}}` and `{{.SelectedLocalBranch.Name}}`. In the future we will likely introduce a tighter interface that exposes a limited set of fields for each model.
|
||||
To see what fields are available on e.g. the `SelectedFile`, see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/commands/models/file.go) (all the modelling lives in the same directory). Note that the custom commands feature does not guarantee backwards compatibility (until we hit Lazygit version 1.0 of course) which means a field you're accessing on an object may no longer be available from one release to the next. Typically however, all you'll need is `{{.SelectedFile.Name}}`, `{{.SelectedLocalCommit.Hash}}` and `{{.SelectedLocalBranch.Name}}`. In the future we will likely introduce a tighter interface that exposes a limited set of fields for each model.
|
||||
|
||||
## Keybinding collisions
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ go utils.Safe(f)
|
||||
|
||||
Where `utils.Safe` is a helper function that ensures we clean up the gui if the goroutine panics.
|
||||
|
||||
### Programmatically enqueing a UI event
|
||||
### Programmatically enqueueing a UI event
|
||||
|
||||
This is invoked with `self.c.OnUIThread(f)`. Internally, it creates a task before enqueuing the function as an event (including the task in the event struct) and once that event is processed by the event queue (and any other pending events are processed) the task is removed from the map by calling `task.Done()`.
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||
| `` <c-o> `` | Copy commit hash to clipboard | |
|
||||
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||
| `` b `` | View bisect options | |
|
||||
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
@@ -245,7 +245,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||
| `` <c-o> `` | Copy commit hash to clipboard | |
|
||||
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Open commit in browser | |
|
||||
@@ -313,7 +313,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||
| `` <c-o> `` | Copy commit hash to clipboard | |
|
||||
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Open commit in browser | |
|
||||
|
||||
@@ -66,7 +66,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||
| `` <c-o> `` | コミットのhashをクリップボードにコピー | |
|
||||
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | ブラウザでコミットを開く | |
|
||||
@@ -93,7 +93,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||
| `` <c-o> `` | コミットのhashをクリップボードにコピー | |
|
||||
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||
| `` b `` | View bisect options | |
|
||||
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
@@ -343,7 +343,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||
| `` <c-o> `` | コミットのhashをクリップボードにコピー | |
|
||||
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | ブラウザでコミットを開く | |
|
||||
|
||||
@@ -53,7 +53,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
|
||||
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 브라우저에서 커밋 열기 | |
|
||||
@@ -83,7 +83,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
|
||||
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 브라우저에서 커밋 열기 | |
|
||||
@@ -256,7 +256,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||
| `` <c-o> `` | 커밋 해시를 클립보드에 복사 | |
|
||||
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
|
||||
| `` b `` | Bisect 옵션 보기 | |
|
||||
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
|
||||
@@ -139,7 +139,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||
| `` <c-o> `` | Kopieer commit hash naar klembord | |
|
||||
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
|
||||
| `` b `` | View bisect options | |
|
||||
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
@@ -223,7 +223,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||
| `` <c-o> `` | Kopieer commit hash naar klembord | |
|
||||
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Open commit in browser | |
|
||||
@@ -313,7 +313,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||
| `` <c-o> `` | Kopieer commit hash naar klembord | |
|
||||
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Open commit in browser | |
|
||||
|
||||
@@ -53,7 +53,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
|
||||
| `` <c-o> `` | Kopiuj hash commita do schowka | |
|
||||
| `` <c-r> `` | Resetuj wybrane (cherry-picked) commity | |
|
||||
| `` b `` | Zobacz opcje bisect | |
|
||||
| `` s `` | Scal | Scal wybrany commit z commitami poniżej. Wiadomość wybranego commita zostanie dołączona do commita poniżej. |
|
||||
@@ -255,7 +255,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita,
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
|
||||
| `` <c-o> `` | Kopiuj hash commita do schowka | |
|
||||
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
|
||||
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
|
||||
| `` o `` | Otwórz commit w przeglądarce | |
|
||||
@@ -295,7 +295,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita,
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Kopiuj SHA commita do schowka | |
|
||||
| `` <c-o> `` | Kopiuj hash commita do schowka | |
|
||||
| `` <space> `` | Przełącz | Przełącz wybrany commit jako odłączoną HEAD. |
|
||||
| `` y `` | Kopiuj atrybut commita do schowka | Kopiuj atrybut commita do schowka (np. hash, URL, różnice, wiadomość, autor). |
|
||||
| `` o `` | Otwórz commit w przeglądarce | |
|
||||
|
||||
@@ -123,7 +123,7 @@ _Связки клавиш_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
|
||||
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Открыть коммит в браузере | |
|
||||
@@ -140,7 +140,7 @@ _Связки клавиш_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
|
||||
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
|
||||
| `` b `` | Просмотреть параметры бинарного поиска | |
|
||||
| `` s `` | Объединить коммиты (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
@@ -219,7 +219,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||
| `` <c-o> `` | Скопировать hash коммита в буфер обмена | |
|
||||
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | Открыть коммит в браузере | |
|
||||
|
||||
@@ -53,7 +53,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||
| `` <c-o> `` | 将提交的 hash 复制到剪贴板 | |
|
||||
| `` <space> `` | 检出 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 在浏览器中打开提交 | |
|
||||
@@ -106,7 +106,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||
| `` <c-o> `` | 将提交的 hash 复制到剪贴板 | |
|
||||
| `` <space> `` | 检出 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 在浏览器中打开提交 | |
|
||||
@@ -137,7 +137,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||
| `` <c-o> `` | 将提交的 hash 复制到剪贴板 | |
|
||||
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
|
||||
| `` b `` | 查看二分查找选项 | |
|
||||
| `` s `` | 压缩 | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
|
||||
@@ -121,7 +121,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
|
||||
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 在瀏覽器中開啟提交 | |
|
||||
@@ -162,7 +162,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
|
||||
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
|
||||
| `` b `` | 查看二分選項 | |
|
||||
| `` s `` | 壓縮 (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||
@@ -236,7 +236,7 @@ If you would instead like to start an interactive rebase from the selected commi
|
||||
|
||||
| Key | Action | Info |
|
||||
|-----|--------|-------------|
|
||||
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||
| `` <c-o> `` | 複製提交 hash 到剪貼簿 | |
|
||||
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
|
||||
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||
| `` o `` | 在瀏覽器中開啟提交 | |
|
||||
|
||||
11
go.mod
11
go.mod
@@ -8,7 +8,6 @@ require (
|
||||
github.com/aybabtme/humanlog v0.4.1
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||
github.com/creack/pty v1.1.11
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5
|
||||
github.com/gdamore/tcell/v2 v2.7.4
|
||||
github.com/go-errors/errors v1.5.1
|
||||
github.com/gookit/color v1.4.2
|
||||
@@ -16,11 +15,10 @@ require (
|
||||
github.com/integrii/flaggy v1.4.0
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||
github.com/jesseduffield/yaml v2.1.0+incompatible
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
||||
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3
|
||||
github.com/kyokomi/emoji/v2 v2.2.8
|
||||
@@ -35,6 +33,7 @@ require (
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/afero v1.9.5
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778
|
||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8
|
||||
@@ -48,7 +47,7 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/fatih/color v1.9.0 // indirect
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/gdamore/encoding v1.0.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.0.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
@@ -74,8 +73,8 @@ require (
|
||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
21
go.sum
21
go.sum
@@ -84,11 +84,10 @@ github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9
|
||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5 h1:Bhzd/vz/6Qm3udfkd6NO9fWfD3TpwR9ucp3N75/J5I8=
|
||||
github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
||||
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
||||
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
||||
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
@@ -187,16 +186,14 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de h1:2ww1SWgakihE8hFxZ7L3agVeGpA6qwW5vdnhFUXKMQo=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513 h1:Y1bw5iItrsDCumATc/rklIJ/6K+68ieiWZJedhrNuXo=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20240418080333-8cd33929c513/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e/go.mod h1:u60qdFGXRd36jyEXxetz0vQceQIxzI13lIo3EFUDf4I=
|
||||
github.com/jesseduffield/yaml v2.1.0+incompatible h1:HWQJ1gIv2zHKbDYNp0Jwjlj24K8aqpFHnMCynY1EpmE=
|
||||
github.com/jesseduffield/yaml v2.1.0+incompatible/go.mod h1:w0xGhOSIJCGYYW+hnFPTutCy5aACpkcwbmORt5axGqk=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@@ -282,6 +279,8 @@ github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2 h1:RTNWemd/9z9A5L/AggEP3OdhRz5dXETB/wdAlYF0SuM=
|
||||
github.com/stefanhaller/git-todo-parser v0.0.7-0.20240406123903-fd957137b6e2/go.mod h1:HFt9hGqMzgQ+gVxMKcvTvGaFz4Y0yYycqqAp2V3wcJY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -471,14 +470,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// Sometimes lazygit will be invoked in daemon mode from a parent lazygit process.
|
||||
@@ -33,12 +33,14 @@ const (
|
||||
DaemonKindUnknown DaemonKind = iota
|
||||
|
||||
DaemonKindExitImmediately
|
||||
DaemonKindRemoveUpdateRefsForCopiedBranch
|
||||
DaemonKindCherryPick
|
||||
DaemonKindMoveTodosUp
|
||||
DaemonKindMoveTodosDown
|
||||
DaemonKindInsertBreak
|
||||
DaemonKindChangeTodoActions
|
||||
DaemonKindMoveFixupCommitDown
|
||||
DaemonKindWriteRebaseTodo
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -52,13 +54,15 @@ func getInstruction() Instruction {
|
||||
jsonData := os.Getenv(DaemonInstructionEnvKey)
|
||||
|
||||
mapping := map[DaemonKind]func(string) Instruction{
|
||||
DaemonKindExitImmediately: deserializeInstruction[*ExitImmediatelyInstruction],
|
||||
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
||||
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
||||
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
||||
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||
DaemonKindExitImmediately: deserializeInstruction[*ExitImmediatelyInstruction],
|
||||
DaemonKindRemoveUpdateRefsForCopiedBranch: deserializeInstruction[*RemoveUpdateRefsForCopiedBranchInstruction],
|
||||
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
||||
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
||||
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
||||
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||
DaemonKindWriteRebaseTodo: deserializeInstruction[*WriteRebaseTodoInstruction],
|
||||
}
|
||||
|
||||
return mapping[getDaemonKind()](jsonData)
|
||||
@@ -155,6 +159,26 @@ func NewExitImmediatelyInstruction() Instruction {
|
||||
return &ExitImmediatelyInstruction{}
|
||||
}
|
||||
|
||||
type RemoveUpdateRefsForCopiedBranchInstruction struct{}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) Kind() DaemonKind {
|
||||
return DaemonKindRemoveUpdateRefsForCopiedBranch
|
||||
}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) SerializedInstructions() string {
|
||||
return serializeInstruction(self)
|
||||
}
|
||||
|
||||
func (self *RemoveUpdateRefsForCopiedBranchInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func NewRemoveUpdateRefsForCopiedBranchInstruction() Instruction {
|
||||
return &RemoveUpdateRefsForCopiedBranchInstruction{}
|
||||
}
|
||||
|
||||
type CherryPickCommitsInstruction struct {
|
||||
Todo string
|
||||
}
|
||||
@@ -210,7 +234,7 @@ func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
changes := lo.Map(self.Changes, func(c ChangeTodoAction, _ int) utils.TodoChange {
|
||||
return utils.TodoChange{
|
||||
Sha: c.Sha,
|
||||
Hash: c.Hash,
|
||||
OldAction: todo.Pick,
|
||||
NewAction: c.NewAction,
|
||||
}
|
||||
@@ -220,18 +244,18 @@ func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
|
||||
})
|
||||
}
|
||||
|
||||
// Takes the sha of some commit, and the sha of a fixup commit that was created
|
||||
// Takes the hash of some commit, and the hash of a fixup commit that was created
|
||||
// at the end of the branch, then moves the fixup commit down to right after the
|
||||
// original commit, changing its type to "fixup"
|
||||
type MoveFixupCommitDownInstruction struct {
|
||||
OriginalSha string
|
||||
FixupSha string
|
||||
OriginalHash string
|
||||
FixupHash string
|
||||
}
|
||||
|
||||
func NewMoveFixupCommitDownInstruction(originalSha string, fixupSha string) Instruction {
|
||||
func NewMoveFixupCommitDownInstruction(originalHash string, fixupHash string) Instruction {
|
||||
return &MoveFixupCommitDownInstruction{
|
||||
OriginalSha: originalSha,
|
||||
FixupSha: fixupSha,
|
||||
OriginalHash: originalHash,
|
||||
FixupHash: fixupHash,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,17 +269,17 @@ func (self *MoveFixupCommitDownInstruction) SerializedInstructions() string {
|
||||
|
||||
func (self *MoveFixupCommitDownInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
return utils.MoveFixupCommitDown(path, self.OriginalSha, self.FixupSha, getCommentChar())
|
||||
return utils.MoveFixupCommitDown(path, self.OriginalHash, self.FixupHash, getCommentChar())
|
||||
})
|
||||
}
|
||||
|
||||
type MoveTodosUpInstruction struct {
|
||||
Shas []string
|
||||
Hashes []string
|
||||
}
|
||||
|
||||
func NewMoveTodosUpInstruction(shas []string) Instruction {
|
||||
func NewMoveTodosUpInstruction(hashes []string) Instruction {
|
||||
return &MoveTodosUpInstruction{
|
||||
Shas: shas,
|
||||
Hashes: hashes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +292,9 @@ func (self *MoveTodosUpInstruction) SerializedInstructions() string {
|
||||
}
|
||||
|
||||
func (self *MoveTodosUpInstruction) run(common *common.Common) error {
|
||||
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
|
||||
todosToMove := lo.Map(self.Hashes, func(hash string, _ int) utils.Todo {
|
||||
return utils.Todo{
|
||||
Sha: sha,
|
||||
Hash: hash,
|
||||
Action: todo.Pick,
|
||||
}
|
||||
})
|
||||
@@ -281,12 +305,12 @@ func (self *MoveTodosUpInstruction) run(common *common.Common) error {
|
||||
}
|
||||
|
||||
type MoveTodosDownInstruction struct {
|
||||
Shas []string
|
||||
Hashes []string
|
||||
}
|
||||
|
||||
func NewMoveTodosDownInstruction(shas []string) Instruction {
|
||||
func NewMoveTodosDownInstruction(hashes []string) Instruction {
|
||||
return &MoveTodosDownInstruction{
|
||||
Shas: shas,
|
||||
Hashes: hashes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,9 +323,9 @@ func (self *MoveTodosDownInstruction) SerializedInstructions() string {
|
||||
}
|
||||
|
||||
func (self *MoveTodosDownInstruction) run(common *common.Common) error {
|
||||
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
|
||||
todosToMove := lo.Map(self.Hashes, func(hash string, _ int) utils.Todo {
|
||||
return utils.Todo{
|
||||
Sha: sha,
|
||||
Hash: hash,
|
||||
Action: todo.Pick,
|
||||
}
|
||||
})
|
||||
@@ -330,3 +354,27 @@ func (self *InsertBreakInstruction) run(common *common.Common) error {
|
||||
return utils.PrependStrToTodoFile(path, []byte("break\n"))
|
||||
})
|
||||
}
|
||||
|
||||
type WriteRebaseTodoInstruction struct {
|
||||
TodosFileContent []byte
|
||||
}
|
||||
|
||||
func NewWriteRebaseTodoInstruction(todosFileContent []byte) Instruction {
|
||||
return &WriteRebaseTodoInstruction{
|
||||
TodosFileContent: todosFileContent,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) Kind() DaemonKind {
|
||||
return DaemonKindWriteRebaseTodo
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) SerializedInstructions() string {
|
||||
return serializeInstruction(self)
|
||||
}
|
||||
|
||||
func (self *WriteRebaseTodoInstruction) run(common *common.Common) error {
|
||||
return handleInteractiveRebase(common, func(path string) error {
|
||||
return os.WriteFile(path, self.TodosFileContent, 0o644)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/env"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type TodoLine struct {
|
||||
@@ -21,7 +22,7 @@ func (self *TodoLine) ToString() string {
|
||||
if self.Action == "break" {
|
||||
return self.Action + "\n"
|
||||
} else {
|
||||
return self.Action + " " + self.Commit.Sha + " " + self.Commit.Name + "\n"
|
||||
return self.Action + " " + self.Commit.Hash + " " + self.Commit.Name + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +35,7 @@ func TodoLinesToString(todoLines []TodoLine) string {
|
||||
}
|
||||
|
||||
type ChangeTodoAction struct {
|
||||
Sha string
|
||||
Hash string
|
||||
NewAction todo.TodoCommand
|
||||
}
|
||||
|
||||
@@ -44,6 +45,10 @@ func handleInteractiveRebase(common *common.Common, f func(path string) error) e
|
||||
path := os.Args[1]
|
||||
|
||||
if strings.HasSuffix(path, "git-rebase-todo") {
|
||||
err := utils.RemoveUpdateRefsForCopiedBranch(path, getCommentChar())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f(path)
|
||||
} else if strings.HasSuffix(path, filepath.Join(gitDir(), "COMMIT_EDITMSG")) { // TODO: test
|
||||
// if we are rebasing and squashing, we'll see a COMMIT_EDITMSG
|
||||
|
||||
@@ -263,7 +263,7 @@ func mergeBuildInfo(buildInfo *BuildInfo) {
|
||||
buildInfo.Commit = revision.Value
|
||||
// if lazygit was built from source we'll show the version as the
|
||||
// abbreviated commit hash
|
||||
buildInfo.Version = utils.ShortSha(revision.Value)
|
||||
buildInfo.Version = utils.ShortHash(revision.Value)
|
||||
}
|
||||
|
||||
// if version hasn't been set we assume that neither has the date
|
||||
|
||||
@@ -76,7 +76,7 @@ func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
|
||||
return info
|
||||
}
|
||||
|
||||
sha := strings.TrimSpace(string(fileContent))
|
||||
hash := strings.TrimSpace(string(fileContent))
|
||||
|
||||
if name == info.newTerm {
|
||||
status = BisectStatusNew
|
||||
@@ -86,7 +86,7 @@ func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
|
||||
status = BisectStatusSkipped
|
||||
}
|
||||
|
||||
info.statusMap[sha] = status
|
||||
info.statusMap[hash] = status
|
||||
}
|
||||
|
||||
currentContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_EXPECTED_REV"))
|
||||
@@ -94,8 +94,8 @@ func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
|
||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||
return info
|
||||
}
|
||||
currentSha := strings.TrimSpace(string(currentContent))
|
||||
info.current = currentSha
|
||||
currentHash := strings.TrimSpace(string(currentContent))
|
||||
info.current = currentHash
|
||||
|
||||
return info
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func (self *BisectCommands) StartWithTerms(oldTerm string, newTerm string) error
|
||||
}
|
||||
|
||||
// tells us whether we've found our problem commit(s). We return a string slice of
|
||||
// commit sha's if we're done, and that slice may have more that one item if
|
||||
// commit hashes if we're done, and that slice may have more that one item if
|
||||
// skipped commits are involved.
|
||||
func (self *BisectCommands) IsDone() (bool, []string, error) {
|
||||
info := self.GetInfo()
|
||||
@@ -143,8 +143,8 @@ func (self *BisectCommands) IsDone() (bool, []string, error) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
newSha := info.GetNewSha()
|
||||
if newSha == "" {
|
||||
newHash := info.GetNewHash()
|
||||
if newHash == "" {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
@@ -153,14 +153,14 @@ func (self *BisectCommands) IsDone() (bool, []string, error) {
|
||||
done := false
|
||||
candidates := []string{}
|
||||
|
||||
cmdArgs := NewGitCmd("rev-list").Arg(newSha).ToArgv()
|
||||
cmdArgs := NewGitCmd("rev-list").Arg(newHash).ToArgv()
|
||||
err := self.cmd.New(cmdArgs).RunAndProcessLines(func(line string) (bool, error) {
|
||||
sha := strings.TrimSpace(line)
|
||||
hash := strings.TrimSpace(line)
|
||||
|
||||
if status, ok := info.statusMap[sha]; ok {
|
||||
if status, ok := info.statusMap[hash]; ok {
|
||||
switch status {
|
||||
case BisectStatusSkipped, BisectStatusNew:
|
||||
candidates = append(candidates, sha)
|
||||
candidates = append(candidates, hash)
|
||||
return false, nil
|
||||
case BisectStatusOld:
|
||||
done = true
|
||||
@@ -185,7 +185,7 @@ func (self *BisectCommands) IsDone() (bool, []string, error) {
|
||||
// render the commits from the bad commit.
|
||||
func (self *BisectCommands) ReachableFromStart(bisectInfo *BisectInfo) bool {
|
||||
cmdArgs := NewGitCmd("merge-base").
|
||||
Arg("--is-ancestor", bisectInfo.GetNewSha(), bisectInfo.GetStartSha()).
|
||||
Arg("--is-ancestor", bisectInfo.GetNewHash(), bisectInfo.GetStartHash()).
|
||||
ToArgv()
|
||||
|
||||
err := self.cmd.New(cmdArgs).DontLog().Run()
|
||||
|
||||
@@ -29,10 +29,10 @@ type BisectInfo struct {
|
||||
newTerm string // 'bad' by default
|
||||
oldTerm string // 'good' by default
|
||||
|
||||
// map of commit sha's to their status
|
||||
// map of commit hashes to their status
|
||||
statusMap map[string]BisectStatus
|
||||
|
||||
// the sha of the commit that's under test
|
||||
// the hash of the commit that's under test
|
||||
current string
|
||||
}
|
||||
|
||||
@@ -49,26 +49,26 @@ func NewNullBisectInfo() *BisectInfo {
|
||||
return &BisectInfo{started: false}
|
||||
}
|
||||
|
||||
func (self *BisectInfo) GetNewSha() string {
|
||||
for sha, status := range self.statusMap {
|
||||
func (self *BisectInfo) GetNewHash() string {
|
||||
for hash, status := range self.statusMap {
|
||||
if status == BisectStatusNew {
|
||||
return sha
|
||||
return hash
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *BisectInfo) GetCurrentSha() string {
|
||||
func (self *BisectInfo) GetCurrentHash() string {
|
||||
return self.current
|
||||
}
|
||||
|
||||
func (self *BisectInfo) GetStartSha() string {
|
||||
func (self *BisectInfo) GetStartHash() string {
|
||||
return self.start
|
||||
}
|
||||
|
||||
func (self *BisectInfo) Status(commitSha string) (BisectStatus, bool) {
|
||||
status, ok := self.statusMap[commitSha]
|
||||
func (self *BisectInfo) Status(commitHash string) (BisectStatus, bool) {
|
||||
status, ok := self.statusMap[commitHash]
|
||||
return status, ok
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func (self *BisectInfo) Bisecting() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if self.GetNewSha() == "" {
|
||||
if self.GetNewHash() == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -65,10 +65,10 @@ func (self *BranchCommands) CurrentBranchInfo() (BranchInfo, error) {
|
||||
for _, line := range utils.SplitLines(output) {
|
||||
split := strings.Split(strings.TrimRight(line, "\r\n"), "\x00")
|
||||
if len(split) == 3 && split[0] == "*" {
|
||||
sha := split[1]
|
||||
hash := split[1]
|
||||
displayName := split[2]
|
||||
return BranchInfo{
|
||||
RefName: sha,
|
||||
RefName: hash,
|
||||
DisplayName: displayName,
|
||||
DetachedHead: true,
|
||||
}, nil
|
||||
|
||||
@@ -22,7 +22,13 @@ func NewCommitCommands(gitCommon *GitCommon) *CommitCommands {
|
||||
|
||||
// ResetAuthor resets the author of the topmost commit
|
||||
func (self *CommitCommands) ResetAuthor() error {
|
||||
message, err := self.GetCommitMessage("HEAD")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(message, skipHookPrefix), "--no-verify").
|
||||
Arg("--allow-empty", "--only", "--no-edit", "--amend", "--reset-author").
|
||||
ToArgv()
|
||||
|
||||
@@ -31,7 +37,14 @@ func (self *CommitCommands) ResetAuthor() error {
|
||||
|
||||
// Sets the commit's author to the supplied value. Value is expected to be of the form 'Name <Email>'
|
||||
func (self *CommitCommands) SetAuthor(value string) error {
|
||||
message, err := self.GetCommitMessage("HEAD")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(message, skipHookPrefix), "--no-verify").
|
||||
Arg("--allow-empty", "--only", "--no-edit", "--amend", "--author="+value).
|
||||
ToArgv()
|
||||
|
||||
@@ -39,15 +52,18 @@ func (self *CommitCommands) SetAuthor(value string) error {
|
||||
}
|
||||
|
||||
// Add a commit's coauthor using Github/Gitlab Co-authored-by metadata. Value is expected to be of the form 'Name <Email>'
|
||||
func (self *CommitCommands) AddCoAuthor(sha string, author string) error {
|
||||
message, err := self.GetCommitMessage(sha)
|
||||
func (self *CommitCommands) AddCoAuthor(hash string, author string) error {
|
||||
message, err := self.GetCommitMessage(hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message = AddCoAuthorToMessage(message, author)
|
||||
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(message, skipHookPrefix), "--no-verify").
|
||||
Arg("--allow-empty", "--amend", "--only", "-m", message).
|
||||
ToArgv()
|
||||
|
||||
@@ -74,8 +90,8 @@ func AddCoAuthorToDescription(description string, author string) string {
|
||||
}
|
||||
|
||||
// ResetToCommit reset to commit
|
||||
func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars []string) error {
|
||||
cmdArgs := NewGitCmd("reset").Arg("--"+strength, sha).ToArgv()
|
||||
func (self *CommitCommands) ResetToCommit(hash string, strength string, envVars []string) error {
|
||||
cmdArgs := NewGitCmd("reset").Arg("--"+strength, hash).ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).
|
||||
// prevents git from prompting us for input which would freeze the program
|
||||
@@ -100,11 +116,15 @@ func (self *CommitCommands) CommitCmdObj(summary string, description string) osc
|
||||
}
|
||||
|
||||
func (self *CommitCommands) RewordLastCommitInEditorCmdObj() oscommands.ICmdObj {
|
||||
return self.cmd.New(NewGitCmd("commit").Arg("--allow-empty", "--amend", "--only").ToArgv())
|
||||
|
||||
return self.cmd.New(NewGitCmd("commit").
|
||||
// TODO: how to decide if we should add --no-verify if we're using the editor?
|
||||
Arg("--allow-empty", "--amend", "--only").ToArgv())
|
||||
}
|
||||
|
||||
func (self *CommitCommands) RewordLastCommitInEditorWithMessageFileCmdObj(tmpMessageFile string) oscommands.ICmdObj {
|
||||
return self.cmd.New(NewGitCmd("commit").
|
||||
// TODO: how to decide if we should add --no-verify if we're using the editor?
|
||||
Arg("--allow-empty", "--amend", "--only", "--edit", "--file="+tmpMessageFile).ToArgv())
|
||||
}
|
||||
|
||||
@@ -120,7 +140,10 @@ func (self *CommitCommands) CommitInEditorWithMessageFileCmdObj(tmpMessageFile s
|
||||
func (self *CommitCommands) RewordLastCommit(summary string, description string) error {
|
||||
messageArgs := self.commitMessageArgs(summary, description)
|
||||
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(summary, skipHookPrefix), "--no-verify").
|
||||
Arg("--allow-empty", "--amend", "--only").
|
||||
Arg(messageArgs...).
|
||||
ToArgv()
|
||||
@@ -155,26 +178,28 @@ func (self *CommitCommands) signoffFlag() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitMessage(commitSha string) (string, error) {
|
||||
func (self *CommitCommands) GetCommitMessage(commitHash string) (string, error) {
|
||||
cmdArgs := NewGitCmd("log").
|
||||
Arg("--format=%B", "--max-count=1", commitSha).
|
||||
Arg("--format=%B", "--max-count=1", commitHash).
|
||||
Config("log.showsignature=false").
|
||||
ToArgv()
|
||||
|
||||
message, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
return strings.ReplaceAll(strings.TrimSpace(message), "\r\n", "\n"), err
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitSubject(commitSha string) (string, error) {
|
||||
func (self *CommitCommands) GetCommitSubject(commitHash string) (string, error) {
|
||||
cmdArgs := NewGitCmd("log").
|
||||
Arg("--format=%s", "--max-count=1", commitSha).
|
||||
Arg("--format=%s", "--max-count=1", commitHash).
|
||||
Config("log.showsignature=false").
|
||||
ToArgv()
|
||||
|
||||
subject, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
return strings.TrimSpace(subject), err
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitDiff(commitSha string) (string, error) {
|
||||
cmdArgs := NewGitCmd("show").Arg("--no-color", commitSha).ToArgv()
|
||||
func (self *CommitCommands) GetCommitDiff(commitHash string) (string, error) {
|
||||
cmdArgs := NewGitCmd("show").Arg("--no-color", commitHash).ToArgv()
|
||||
|
||||
diff, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
return diff, err
|
||||
@@ -185,9 +210,9 @@ type Author struct {
|
||||
Email string
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitAuthor(commitSha string) (Author, error) {
|
||||
func (self *CommitCommands) GetCommitAuthor(commitHash string) (Author, error) {
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Arg("--no-patch", "--pretty=format:'%an%x00%ae'", commitSha).
|
||||
Arg("--no-patch", "--pretty=format:'%an%x00%ae'", commitHash).
|
||||
ToArgv()
|
||||
|
||||
output, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
@@ -204,14 +229,14 @@ func (self *CommitCommands) GetCommitAuthor(commitSha string) (Author, error) {
|
||||
return author, err
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitMessageFirstLine(sha string) (string, error) {
|
||||
return self.GetCommitMessagesFirstLine([]string{sha})
|
||||
func (self *CommitCommands) GetCommitMessageFirstLine(hash string) (string, error) {
|
||||
return self.GetCommitMessagesFirstLine([]string{hash})
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitMessagesFirstLine(shas []string) (string, error) {
|
||||
func (self *CommitCommands) GetCommitMessagesFirstLine(hashes []string) (string, error) {
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Arg("--no-patch", "--pretty=format:%s").
|
||||
Arg(shas...).
|
||||
Arg(hashes...).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
@@ -222,19 +247,19 @@ func (self *CommitCommands) GetCommitMessagesFirstLine(shas []string) (string, e
|
||||
// cd50c79ae Preserve the commit message correctly even if the description has blank lines
|
||||
// 3ebba5f32 Add test demonstrating a bug with preserving the commit message
|
||||
// 9a423c388 Remove unused function
|
||||
func (self *CommitCommands) GetShasAndCommitMessagesFirstLine(shas []string) (string, error) {
|
||||
func (self *CommitCommands) GetHashesAndCommitMessagesFirstLine(hashes []string) (string, error) {
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Arg("--no-patch", "--pretty=format:%h %s").
|
||||
Arg(shas...).
|
||||
Arg(hashes...).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
}
|
||||
|
||||
func (self *CommitCommands) GetCommitsOneline(shas []string) (string, error) {
|
||||
func (self *CommitCommands) GetCommitsOneline(hashes []string) (string, error) {
|
||||
cmdArgs := NewGitCmd("show").
|
||||
Arg("--no-patch", "--oneline").
|
||||
Arg(shas...).
|
||||
Arg(hashes...).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||
@@ -246,14 +271,22 @@ func (self *CommitCommands) AmendHead() error {
|
||||
}
|
||||
|
||||
func (self *CommitCommands) AmendHeadCmdObj() oscommands.ICmdObj {
|
||||
message, err := self.GetCommitMessage("HEAD")
|
||||
if err != nil {
|
||||
// TODO: what to do here? we can't return err
|
||||
// return err
|
||||
}
|
||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||
|
||||
cmdArgs := NewGitCmd("commit").
|
||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(message, skipHookPrefix), "--no-verify").
|
||||
Arg("--amend", "--no-edit", "--allow-empty").
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs)
|
||||
}
|
||||
|
||||
func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands.ICmdObj {
|
||||
func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) oscommands.ICmdObj {
|
||||
contextSize := self.AppState.DiffContextSize
|
||||
|
||||
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||
@@ -267,7 +300,7 @@ func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands
|
||||
Arg("--stat").
|
||||
Arg("--decorate").
|
||||
Arg("-p").
|
||||
Arg(sha).
|
||||
Arg(hash).
|
||||
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||
ArgIf(filterPath != "", "--", filterPath).
|
||||
Dir(self.repoPaths.worktreePath).
|
||||
@@ -276,23 +309,23 @@ func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands
|
||||
return self.cmd.New(cmdArgs).DontLog()
|
||||
}
|
||||
|
||||
// Revert reverts the selected commit by sha
|
||||
func (self *CommitCommands) Revert(sha string) error {
|
||||
cmdArgs := NewGitCmd("revert").Arg(sha).ToArgv()
|
||||
// Revert reverts the selected commit by hash
|
||||
func (self *CommitCommands) Revert(hash string) error {
|
||||
cmdArgs := NewGitCmd("revert").Arg(hash).ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
}
|
||||
|
||||
func (self *CommitCommands) RevertMerge(sha string, parentNumber int) error {
|
||||
cmdArgs := NewGitCmd("revert").Arg(sha, "-m", fmt.Sprintf("%d", parentNumber)).
|
||||
func (self *CommitCommands) RevertMerge(hash string, parentNumber int) error {
|
||||
cmdArgs := NewGitCmd("revert").Arg(hash, "-m", fmt.Sprintf("%d", parentNumber)).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
}
|
||||
|
||||
// CreateFixupCommit creates a commit that fixes up a previous commit
|
||||
func (self *CommitCommands) CreateFixupCommit(sha string) error {
|
||||
cmdArgs := NewGitCmd("commit").Arg("--fixup=" + sha).ToArgv()
|
||||
func (self *CommitCommands) CreateFixupCommit(hash string) error {
|
||||
cmdArgs := NewGitCmd("commit").Arg("--fixup=" + hash).ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/common"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// context:
|
||||
@@ -129,7 +129,7 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
||||
}
|
||||
|
||||
for _, commit := range commits {
|
||||
if commit.Sha == firstPushedCommit {
|
||||
if commit.Hash == firstPushedCommit {
|
||||
passedFirstPushedCommit = true
|
||||
}
|
||||
if commit.Status != models.StatusRebasing {
|
||||
@@ -198,14 +198,14 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// extractCommitFromLine takes a line from a git log and extracts the sha, message, date, and tag if present
|
||||
// extractCommitFromLine takes a line from a git log and extracts the hash, message, date, and tag if present
|
||||
// then puts them into a commit object
|
||||
// example input:
|
||||
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
|
||||
func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool) *models.Commit {
|
||||
split := strings.SplitN(line, "\x00", 8)
|
||||
|
||||
sha := split[0]
|
||||
hash := split[0]
|
||||
unixTimestamp := split[1]
|
||||
authorName := split[2]
|
||||
authorEmail := split[3]
|
||||
@@ -241,7 +241,7 @@ func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool
|
||||
}
|
||||
|
||||
return &models.Commit{
|
||||
Sha: sha,
|
||||
Hash: hash,
|
||||
Name: message,
|
||||
Tags: tags,
|
||||
ExtraInfo: extraInfo,
|
||||
@@ -260,8 +260,8 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
commitShas := lo.FilterMap(commits, func(commit *models.Commit, _ int) (string, bool) {
|
||||
return commit.Sha, commit.Sha != ""
|
||||
commitHashes := lo.FilterMap(commits, func(commit *models.Commit, _ int) (string, bool) {
|
||||
return commit.Hash, commit.Hash != ""
|
||||
})
|
||||
|
||||
// note that we're not filtering these as we do non-rebasing commits just because
|
||||
@@ -270,14 +270,14 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
||||
NewGitCmd("show").
|
||||
Config("log.showSignature=false").
|
||||
Arg("--no-patch", "--oneline", "--abbrev=20", prettyFormat).
|
||||
Arg(commitShas...).
|
||||
Arg(commitHashes...).
|
||||
ToArgv(),
|
||||
).DontLog()
|
||||
|
||||
fullCommits := map[string]*models.Commit{}
|
||||
err := cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
||||
commit := self.extractCommitFromLine(line, false)
|
||||
fullCommits[commit.Sha] = commit
|
||||
fullCommits[commit.Hash] = commit
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -285,23 +285,23 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
||||
}
|
||||
|
||||
findFullCommit := lo.Ternary(self.version.IsOlderThan(2, 25, 2),
|
||||
func(sha string) *models.Commit {
|
||||
func(hash string) *models.Commit {
|
||||
for s, c := range fullCommits {
|
||||
if strings.HasPrefix(s, sha) {
|
||||
if strings.HasPrefix(s, hash) {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(sha string) *models.Commit {
|
||||
return fullCommits[sha]
|
||||
func(hash string) *models.Commit {
|
||||
return fullCommits[hash]
|
||||
})
|
||||
|
||||
hydratedCommits := make([]*models.Commit, 0, len(commits))
|
||||
for _, rebasingCommit := range commits {
|
||||
if rebasingCommit.Sha == "" {
|
||||
if rebasingCommit.Hash == "" {
|
||||
hydratedCommits = append(hydratedCommits, rebasingCommit)
|
||||
} else if commit := findFullCommit(rebasingCommit.Sha); commit != nil {
|
||||
} else if commit := findFullCommit(rebasingCommit.Hash); commit != nil {
|
||||
commit.Action = rebasingCommit.Action
|
||||
commit.Status = rebasingCommit.Status
|
||||
hydratedCommits = append(hydratedCommits, commit)
|
||||
@@ -337,9 +337,9 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod
|
||||
|
||||
// See if the current commit couldn't be applied because it conflicted; if
|
||||
// so, add a fake entry for it
|
||||
if conflictedCommitSha := self.getConflictedCommit(todos); conflictedCommitSha != "" {
|
||||
if conflictedCommitHash := self.getConflictedCommit(todos); conflictedCommitHash != "" {
|
||||
commits = append(commits, &models.Commit{
|
||||
Sha: conflictedCommitSha,
|
||||
Hash: conflictedCommitHash,
|
||||
Name: "",
|
||||
Status: models.StatusRebasing,
|
||||
Action: models.ActionConflict,
|
||||
@@ -354,7 +354,7 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod
|
||||
continue
|
||||
}
|
||||
commits = utils.Prepend(commits, &models.Commit{
|
||||
Sha: t.Commit,
|
||||
Hash: t.Commit,
|
||||
Name: t.Msg,
|
||||
Status: models.StatusRebasing,
|
||||
Action: t.Command,
|
||||
@@ -458,8 +458,8 @@ func setCommitMergedStatuses(ancestor string, commits []*models.Commit) {
|
||||
|
||||
passedAncestor := false
|
||||
for i, commit := range commits {
|
||||
// some commits aren't really commits and don't have sha's, such as the update-ref todo
|
||||
if commit.Sha != "" && strings.HasPrefix(ancestor, commit.Sha) {
|
||||
// some commits aren't really commits and don't have hashes, such as the update-ref todo
|
||||
if commit.Hash != "" && strings.HasPrefix(ancestor, commit.Hash) {
|
||||
passedAncestor = true
|
||||
}
|
||||
if commit.Status != models.StatusPushed && commit.Status != models.StatusUnpushed {
|
||||
@@ -559,7 +559,7 @@ func ignoringWarnings(commandOutput string) string {
|
||||
return lastLine
|
||||
}
|
||||
|
||||
// getFirstPushedCommit returns the first commit SHA which has been pushed to the ref's upstream.
|
||||
// getFirstPushedCommit returns the first commit hash which has been pushed to the ref's upstream.
|
||||
// all commits above this are deemed unpushed and marked as such.
|
||||
func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
|
||||
output, err := self.cmd.New(
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestGetCommits(t *testing.T) {
|
||||
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Hash: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Name: "better typing for rebase mode",
|
||||
Status: models.StatusUnpushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -100,7 +100,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164",
|
||||
Hash: "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164",
|
||||
Name: "fix logging",
|
||||
Status: models.StatusPushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -114,7 +114,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "e94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c",
|
||||
Hash: "e94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c",
|
||||
Name: "refactor",
|
||||
Status: models.StatusPushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -128,7 +128,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "d8084cd558925eb7c9c38afeed5725c21653ab90",
|
||||
Hash: "d8084cd558925eb7c9c38afeed5725c21653ab90",
|
||||
Name: "WIP",
|
||||
Status: models.StatusPushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -142,7 +142,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "65f910ebd85283b5cce9bf67d03d3f1a9ea3813a",
|
||||
Hash: "65f910ebd85283b5cce9bf67d03d3f1a9ea3813a",
|
||||
Name: "WIP",
|
||||
Status: models.StatusPushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -156,7 +156,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "26c07b1ab33860a1a7591a0638f9925ccf497ffa",
|
||||
Hash: "26c07b1ab33860a1a7591a0638f9925ccf497ffa",
|
||||
Name: "WIP",
|
||||
Status: models.StatusMerged,
|
||||
Action: models.ActionNone,
|
||||
@@ -170,7 +170,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "3d4470a6c072208722e5ae9a54bcb9634959a1c5",
|
||||
Hash: "3d4470a6c072208722e5ae9a54bcb9634959a1c5",
|
||||
Name: "WIP",
|
||||
Status: models.StatusMerged,
|
||||
Action: models.ActionNone,
|
||||
@@ -184,7 +184,7 @@ func TestGetCommits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "053a66a7be3da43aacdc7aa78e1fe757b82c4dd2",
|
||||
Hash: "053a66a7be3da43aacdc7aa78e1fe757b82c4dd2",
|
||||
Name: "refactoring the config struct",
|
||||
Status: models.StatusMerged,
|
||||
Action: models.ActionNone,
|
||||
@@ -221,7 +221,7 @@ func TestGetCommits(t *testing.T) {
|
||||
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Hash: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Name: "better typing for rebase mode",
|
||||
Status: models.StatusUnpushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -260,7 +260,7 @@ func TestGetCommits(t *testing.T) {
|
||||
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Hash: "0eea75e8c631fba6b58135697835d58ba4c18dbc",
|
||||
Name: "better typing for rebase mode",
|
||||
Status: models.StatusUnpushed,
|
||||
Action: models.ActionNone,
|
||||
@@ -339,14 +339,14 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
todos []todo.Todo
|
||||
doneTodos []todo.Todo
|
||||
amendFileExists bool
|
||||
expectedSha string
|
||||
expectedHash string
|
||||
}{
|
||||
{
|
||||
testName: "no done todos",
|
||||
todos: []todo.Todo{},
|
||||
doneTodos: []todo.Todo{},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "common case (conflict)",
|
||||
@@ -362,7 +362,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "fa1afe1",
|
||||
expectedHash: "fa1afe1",
|
||||
},
|
||||
{
|
||||
testName: "last command was 'break'",
|
||||
@@ -371,7 +371,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
{Command: todo.Break},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "last command was 'exec'",
|
||||
@@ -383,7 +383,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "last command was 'reword'",
|
||||
@@ -392,7 +392,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
{Command: todo.Reword},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "'pick' was rescheduled",
|
||||
@@ -409,7 +409,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "'pick' was rescheduled, buggy git version",
|
||||
@@ -434,7 +434,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "conflicting 'pick' after 'exec'",
|
||||
@@ -459,7 +459,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "fa1afe1",
|
||||
expectedHash: "fa1afe1",
|
||||
},
|
||||
{
|
||||
testName: "'edit' with amend file",
|
||||
@@ -471,7 +471,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: true,
|
||||
expectedSha: "",
|
||||
expectedHash: "",
|
||||
},
|
||||
{
|
||||
testName: "'edit' without amend file",
|
||||
@@ -483,7 +483,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
amendFileExists: false,
|
||||
expectedSha: "fa1afe1",
|
||||
expectedHash: "fa1afe1",
|
||||
},
|
||||
}
|
||||
for _, scenario := range scenarios {
|
||||
@@ -503,8 +503,8 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
sha := builder.getConflictedCommitImpl(scenario.todos, scenario.doneTodos, scenario.amendFileExists)
|
||||
assert.Equal(t, scenario.expectedSha, sha)
|
||||
hash := builder.getConflictedCommitImpl(scenario.todos, scenario.doneTodos, scenario.amendFileExists)
|
||||
assert.Equal(t, scenario.expectedHash, hash)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -521,29 +521,29 @@ func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
||||
{
|
||||
testName: "basic",
|
||||
commits: []*models.Commit{
|
||||
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Sha: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Hash: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
},
|
||||
ancestor: "67890",
|
||||
expectedCommits: []*models.Commit{
|
||||
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Sha: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusMerged},
|
||||
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusMerged},
|
||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Hash: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusMerged},
|
||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusMerged},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "with update-ref",
|
||||
commits: []*models.Commit{
|
||||
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Sha: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Hash: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
},
|
||||
ancestor: "deadbeef",
|
||||
expectedCommits: []*models.Commit{
|
||||
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Sha: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||
{Hash: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ func TestCommitCommitEditorCmdObj(t *testing.T) {
|
||||
func TestCommitCreateFixupCommit(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
sha string
|
||||
hash string
|
||||
runner *oscommands.FakeCmdObjRunner
|
||||
test func(error)
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func TestCommitCreateFixupCommit(t *testing.T) {
|
||||
scenarios := []scenario{
|
||||
{
|
||||
testName: "valid case",
|
||||
sha: "12345",
|
||||
hash: "12345",
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"commit", "--fixup=12345"}, "", nil),
|
||||
test: func(err error) {
|
||||
@@ -174,7 +174,7 @@ func TestCommitCreateFixupCommit(t *testing.T) {
|
||||
s := s
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
instance := buildCommitCommands(commonDeps{runner: s.runner})
|
||||
s.test(instance.CreateFixupCommit(s.sha))
|
||||
s.test(instance.CreateFixupCommit(s.hash))
|
||||
s.runner.CheckForMissingCalls()
|
||||
})
|
||||
}
|
||||
@@ -337,7 +337,7 @@ func TestGetCommitMsg(t *testing.T) {
|
||||
s := s
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
instance := buildCommitCommands(commonDeps{
|
||||
runner: oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1", "deadbeef"}, s.input, nil),
|
||||
runner: oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"-c", "log.showsignature=false", "log", "--format=%B", "--max-count=1", "deadbeef"}, s.input, nil),
|
||||
})
|
||||
|
||||
output, err := instance.GetCommitMessage("deadbeef")
|
||||
@@ -358,14 +358,14 @@ func TestGetCommitMessageFromHistory(t *testing.T) {
|
||||
scenarios := []scenario{
|
||||
{
|
||||
"Empty message",
|
||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "", nil).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1"}, "", nil),
|
||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "", nil).ExpectGitArgs([]string{"-c", "log.showsignature=false", "log", "--format=%B", "--max-count=1"}, "", nil),
|
||||
func(output string, err error) {
|
||||
assert.Error(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
"Default case to retrieve a commit in history",
|
||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "sha3 \n", nil).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1", "sha3"}, `use generics to DRY up context code`, nil),
|
||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "hash3 \n", nil).ExpectGitArgs([]string{"-c", "log.showsignature=false", "log", "--format=%B", "--max-count=1", "hash3"}, `use generics to DRY up context code`, nil),
|
||||
func(output string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "use generics to DRY up context code", output)
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type PatchCommands struct {
|
||||
@@ -157,13 +157,13 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s
|
||||
baseIndex := sourceCommitIdx + 1
|
||||
|
||||
changes := []daemon.ChangeTodoAction{
|
||||
{Sha: commits[sourceCommitIdx].Sha, NewAction: todo.Edit},
|
||||
{Sha: commits[destinationCommitIdx].Sha, NewAction: todo.Edit},
|
||||
{Hash: commits[sourceCommitIdx].Hash, NewAction: todo.Edit},
|
||||
{Hash: commits[destinationCommitIdx].Hash, NewAction: todo.Edit},
|
||||
}
|
||||
self.os.LogCommand(logTodoChanges(changes), false)
|
||||
|
||||
err := self.rebase.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: commits[baseIndex].Sha,
|
||||
baseHashOrRoot: commits[baseIndex].Hash,
|
||||
overrideEditor: true,
|
||||
instruction: daemon.NewChangeTodoActionsInstruction(changes),
|
||||
}).Run()
|
||||
@@ -219,7 +219,7 @@ func (self *PatchCommands) MovePatchToSelectedCommit(commits []*models.Commit, s
|
||||
|
||||
func (self *PatchCommands) MovePatchIntoIndex(commits []*models.Commit, commitIdx int, stash bool) error {
|
||||
if stash {
|
||||
if err := self.stash.Push(self.Tr.StashPrefix + commits[commitIdx].Sha); err != nil {
|
||||
if err := self.stash.Push(self.Tr.StashPrefix + commits[commitIdx].Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -324,7 +324,7 @@ func (self *PatchCommands) diffHeadAgainstCommit(commit *models.Commit) (string,
|
||||
cmdArgs := NewGitCmd("diff").
|
||||
Config("diff.noprefix=false").
|
||||
Arg("--no-ext-diff").
|
||||
Arg("HEAD.." + commit.Sha).
|
||||
Arg("HEAD.." + commit.Hash).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).RunWithOutput()
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
type RebaseCommands struct {
|
||||
@@ -56,14 +56,14 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, su
|
||||
|
||||
func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (oscommands.ICmdObj, error) {
|
||||
changes := []daemon.ChangeTodoAction{{
|
||||
Sha: commits[index].Sha,
|
||||
Hash: commits[index].Hash,
|
||||
NewAction: todo.Reword,
|
||||
}}
|
||||
self.os.LogCommand(logTodoChanges(changes), false)
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: getBaseShaOrRoot(commits, index+1),
|
||||
instruction: daemon.NewChangeTodoActionsInstruction(changes),
|
||||
baseHashOrRoot: getBaseHashOrRoot(commits, index+1),
|
||||
instruction: daemon.NewChangeTodoActionsInstruction(changes),
|
||||
}), nil
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (self *RebaseCommands) SetCommitAuthor(commits []*models.Commit, index int,
|
||||
|
||||
func (self *RebaseCommands) AddCommitCoAuthor(commits []*models.Commit, index int, value string) error {
|
||||
return self.GenericAmend(commits, index, func() error {
|
||||
return self.commit.AddCoAuthor(commits[index].Sha, value)
|
||||
return self.commit.AddCoAuthor(commits[index].Hash, value)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -106,29 +106,29 @@ func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f
|
||||
}
|
||||
|
||||
func (self *RebaseCommands) MoveCommitsDown(commits []*models.Commit, startIdx int, endIdx int) error {
|
||||
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+2)
|
||||
baseHashOrRoot := getBaseHashOrRoot(commits, endIdx+2)
|
||||
|
||||
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||
return commit.Sha
|
||||
hashes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||
return commit.Hash
|
||||
})
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: baseShaOrRoot,
|
||||
instruction: daemon.NewMoveTodosDownInstruction(shas),
|
||||
baseHashOrRoot: baseHashOrRoot,
|
||||
instruction: daemon.NewMoveTodosDownInstruction(hashes),
|
||||
overrideEditor: true,
|
||||
}).Run()
|
||||
}
|
||||
|
||||
func (self *RebaseCommands) MoveCommitsUp(commits []*models.Commit, startIdx int, endIdx int) error {
|
||||
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+1)
|
||||
baseHashOrRoot := getBaseHashOrRoot(commits, endIdx+1)
|
||||
|
||||
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||
return commit.Sha
|
||||
hashes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||
return commit.Hash
|
||||
})
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: baseShaOrRoot,
|
||||
instruction: daemon.NewMoveTodosUpInstruction(shas),
|
||||
baseHashOrRoot: baseHashOrRoot,
|
||||
instruction: daemon.NewMoveTodosUpInstruction(hashes),
|
||||
overrideEditor: true,
|
||||
}).Run()
|
||||
}
|
||||
@@ -139,11 +139,11 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx
|
||||
baseIndex++
|
||||
}
|
||||
|
||||
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
|
||||
baseHashOrRoot := getBaseHashOrRoot(commits, baseIndex)
|
||||
|
||||
changes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) daemon.ChangeTodoAction {
|
||||
return daemon.ChangeTodoAction{
|
||||
Sha: commit.Sha,
|
||||
Hash: commit.Hash,
|
||||
NewAction: action,
|
||||
}
|
||||
})
|
||||
@@ -151,7 +151,7 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx
|
||||
self.os.LogCommand(logTodoChanges(changes), false)
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: baseShaOrRoot,
|
||||
baseHashOrRoot: baseHashOrRoot,
|
||||
overrideEditor: true,
|
||||
instruction: daemon.NewChangeTodoActionsInstruction(changes),
|
||||
}).Run()
|
||||
@@ -166,8 +166,8 @@ func (self *RebaseCommands) EditRebase(branchRef string) error {
|
||||
)
|
||||
self.os.LogCommand(msg, false)
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: branchRef,
|
||||
instruction: daemon.NewInsertBreakInstruction(),
|
||||
baseHashOrRoot: branchRef,
|
||||
instruction: daemon.NewInsertBreakInstruction(),
|
||||
}).Run()
|
||||
}
|
||||
|
||||
@@ -181,21 +181,21 @@ func (self *RebaseCommands) EditRebaseFromBaseCommit(targetBranchName string, ba
|
||||
)
|
||||
self.os.LogCommand(msg, false)
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: baseCommit,
|
||||
onto: targetBranchName,
|
||||
instruction: daemon.NewInsertBreakInstruction(),
|
||||
baseHashOrRoot: baseCommit,
|
||||
onto: targetBranchName,
|
||||
instruction: daemon.NewInsertBreakInstruction(),
|
||||
}).Run()
|
||||
}
|
||||
|
||||
func logTodoChanges(changes []daemon.ChangeTodoAction) string {
|
||||
changeTodoStr := strings.Join(lo.Map(changes, func(c daemon.ChangeTodoAction, _ int) string {
|
||||
return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
|
||||
return fmt.Sprintf("%s:%s", c.Hash, c.NewAction)
|
||||
}), "\n")
|
||||
return fmt.Sprintf("Changing TODO actions:\n%s", changeTodoStr)
|
||||
}
|
||||
|
||||
type PrepareInteractiveRebaseCommandOpts struct {
|
||||
baseShaOrRoot string
|
||||
baseHashOrRoot string
|
||||
onto string
|
||||
instruction daemon.Instruction
|
||||
overrideEditor bool
|
||||
@@ -204,7 +204,7 @@ type PrepareInteractiveRebaseCommandOpts struct {
|
||||
|
||||
// PrepareInteractiveRebaseCommand returns the cmd for an interactive rebase
|
||||
// we tell git to run lazygit to edit the todo list, and we pass the client
|
||||
// lazygit a todo string to write to the todo file
|
||||
// lazygit instructions what to do with the todo file
|
||||
func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteractiveRebaseCommandOpts) oscommands.ICmdObj {
|
||||
ex := oscommands.GetLazygitPath()
|
||||
|
||||
@@ -216,7 +216,7 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
||||
Arg("--no-autosquash").
|
||||
ArgIf(self.version.IsAtLeast(2, 22, 0), "--rebase-merges").
|
||||
ArgIf(opts.onto != "", "--onto", opts.onto).
|
||||
Arg(opts.baseShaOrRoot).
|
||||
Arg(opts.baseHashOrRoot).
|
||||
ToArgv()
|
||||
|
||||
debug := "FALSE"
|
||||
@@ -233,7 +233,7 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
||||
if opts.instruction != nil {
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(opts.instruction)...)
|
||||
} else {
|
||||
gitSequenceEditor = "true"
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(daemon.NewRemoveUpdateRefsForCopiedBranchInstruction())...)
|
||||
}
|
||||
|
||||
cmdObj.AddEnvVars(
|
||||
@@ -250,25 +250,55 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
||||
return cmdObj
|
||||
}
|
||||
|
||||
// GitRebaseEditTodo runs "git rebase --edit-todo", saving the given todosFileContent to the file
|
||||
func (self *RebaseCommands) GitRebaseEditTodo(todosFileContent []byte) error {
|
||||
ex := oscommands.GetLazygitPath()
|
||||
|
||||
cmdArgs := NewGitCmd("rebase").
|
||||
Arg("--edit-todo").
|
||||
ToArgv()
|
||||
|
||||
debug := "FALSE"
|
||||
if self.Debug {
|
||||
debug = "TRUE"
|
||||
}
|
||||
|
||||
self.Log.WithField("command", cmdArgs).Debug("RunCommand")
|
||||
|
||||
cmdObj := self.cmd.New(cmdArgs)
|
||||
|
||||
cmdObj.AddEnvVars(daemon.ToEnvVars(daemon.NewWriteRebaseTodoInstruction(todosFileContent))...)
|
||||
|
||||
cmdObj.AddEnvVars(
|
||||
"DEBUG="+debug,
|
||||
"LANG=en_US.UTF-8", // Force using EN as language
|
||||
"LC_ALL=en_US.UTF-8", // Force using EN as language
|
||||
"GIT_EDITOR="+ex,
|
||||
"GIT_SEQUENCE_EDITOR="+ex,
|
||||
)
|
||||
|
||||
return cmdObj.Run()
|
||||
}
|
||||
|
||||
// AmendTo amends the given commit with whatever files are staged
|
||||
func (self *RebaseCommands) AmendTo(commits []*models.Commit, commitIndex int) error {
|
||||
commit := commits[commitIndex]
|
||||
|
||||
if err := self.commit.CreateFixupCommit(commit.Sha); err != nil {
|
||||
if err := self.commit.CreateFixupCommit(commit.Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the sha of the commit we just created
|
||||
// Get the hash of the commit we just created
|
||||
cmdArgs := NewGitCmd("rev-parse").Arg("--verify", "HEAD").ToArgv()
|
||||
fixupSha, err := self.cmd.New(cmdArgs).RunWithOutput()
|
||||
fixupHash, err := self.cmd.New(cmdArgs).RunWithOutput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: getBaseShaOrRoot(commits, commitIndex+1),
|
||||
baseHashOrRoot: getBaseHashOrRoot(commits, commitIndex+1),
|
||||
overrideEditor: true,
|
||||
instruction: daemon.NewMoveFixupCommitDownInstruction(commit.Sha, fixupSha),
|
||||
instruction: daemon.NewMoveFixupCommitDownInstruction(commit.Hash, fixupHash),
|
||||
}).Run()
|
||||
}
|
||||
|
||||
@@ -276,7 +306,7 @@ func todoFromCommit(commit *models.Commit) utils.Todo {
|
||||
if commit.Action == todo.UpdateRef {
|
||||
return utils.Todo{Ref: commit.Name, Action: commit.Action}
|
||||
} else {
|
||||
return utils.Todo{Sha: commit.Sha, Action: commit.Action}
|
||||
return utils.Todo{Hash: commit.Hash, Action: commit.Action}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +314,7 @@ func todoFromCommit(commit *models.Commit) utils.Todo {
|
||||
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand) error {
|
||||
commitsWithAction := lo.Map(commits, func(commit *models.Commit, _ int) utils.TodoChange {
|
||||
return utils.TodoChange{
|
||||
Sha: commit.Sha,
|
||||
Hash: commit.Hash,
|
||||
OldAction: commit.Action,
|
||||
NewAction: action,
|
||||
}
|
||||
@@ -302,11 +332,16 @@ func (self *RebaseCommands) DeleteUpdateRefTodos(commits []*models.Commit) error
|
||||
return todoFromCommit(commit)
|
||||
})
|
||||
|
||||
return utils.DeleteTodos(
|
||||
todosFileContent, err := utils.DeleteTodos(
|
||||
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"),
|
||||
todosToDelete,
|
||||
self.config.GetCoreCommentChar(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.GitRebaseEditTodo(todosFileContent)
|
||||
}
|
||||
|
||||
func (self *RebaseCommands) MoveTodosDown(commits []*models.Commit) error {
|
||||
@@ -329,13 +364,13 @@ func (self *RebaseCommands) MoveTodosUp(commits []*models.Commit) error {
|
||||
|
||||
// SquashAllAboveFixupCommits squashes all fixup! commits above the given one
|
||||
func (self *RebaseCommands) SquashAllAboveFixupCommits(commit *models.Commit) error {
|
||||
shaOrRoot := commit.Sha + "^"
|
||||
hashOrRoot := commit.Hash + "^"
|
||||
if commit.IsFirstCommit() {
|
||||
shaOrRoot = "--root"
|
||||
hashOrRoot = "--root"
|
||||
}
|
||||
|
||||
cmdArgs := NewGitCmd("rebase").
|
||||
Arg("--interactive", "--rebase-merges", "--autostash", "--autosquash", shaOrRoot).
|
||||
Arg("--interactive", "--rebase-merges", "--autostash", "--autosquash", hashOrRoot).
|
||||
ToArgv()
|
||||
|
||||
return self.runSkipEditorCommand(self.cmd.New(cmdArgs))
|
||||
@@ -358,13 +393,13 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(
|
||||
}
|
||||
|
||||
changes := []daemon.ChangeTodoAction{{
|
||||
Sha: commits[commitIndex].Sha,
|
||||
Hash: commits[commitIndex].Hash,
|
||||
NewAction: todo.Edit,
|
||||
}}
|
||||
self.os.LogCommand(logTodoChanges(changes), false)
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: getBaseShaOrRoot(commits, commitIndex+1),
|
||||
baseHashOrRoot: getBaseHashOrRoot(commits, commitIndex+1),
|
||||
overrideEditor: true,
|
||||
keepCommitsThatBecomeEmpty: keepCommitsThatBecomeEmpty,
|
||||
instruction: daemon.NewChangeTodoActionsInstruction(changes),
|
||||
@@ -373,13 +408,13 @@ func (self *RebaseCommands) BeginInteractiveRebaseForCommit(
|
||||
|
||||
// RebaseBranch interactive rebases onto a branch
|
||||
func (self *RebaseCommands) RebaseBranch(branchName string) error {
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{baseShaOrRoot: branchName}).Run()
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{baseHashOrRoot: branchName}).Run()
|
||||
}
|
||||
|
||||
func (self *RebaseCommands) RebaseBranchFromBaseCommit(targetBranchName string, baseCommit string) error {
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: baseCommit,
|
||||
onto: targetBranchName,
|
||||
baseHashOrRoot: baseCommit,
|
||||
onto: targetBranchName,
|
||||
}).Run()
|
||||
}
|
||||
|
||||
@@ -468,10 +503,10 @@ func (self *RebaseCommands) DiscardOldFileChanges(commits []*models.Commit, comm
|
||||
return self.ContinueRebase()
|
||||
}
|
||||
|
||||
// CherryPickCommits begins an interactive rebase with the given shas being cherry picked onto HEAD
|
||||
// CherryPickCommits begins an interactive rebase with the given hashes being cherry picked onto HEAD
|
||||
func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error {
|
||||
commitLines := lo.Map(commits, func(commit *models.Commit, _ int) string {
|
||||
return fmt.Sprintf("%s %s", utils.ShortSha(commit.Sha), commit.Name)
|
||||
return fmt.Sprintf("%s %s", utils.ShortHash(commit.Hash), commit.Name)
|
||||
})
|
||||
msg := utils.ResolvePlaceholderString(
|
||||
self.Tr.Log.CherryPickCommits,
|
||||
@@ -482,8 +517,8 @@ func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error {
|
||||
self.os.LogCommand(msg, false)
|
||||
|
||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||
baseShaOrRoot: "HEAD",
|
||||
instruction: daemon.NewCherryPickCommitsInstruction(commits),
|
||||
baseHashOrRoot: "HEAD",
|
||||
instruction: daemon.NewCherryPickCommitsInstruction(commits),
|
||||
}).Run()
|
||||
}
|
||||
|
||||
@@ -503,13 +538,13 @@ func (self *RebaseCommands) CherryPickCommitsDuringRebase(commits []*models.Comm
|
||||
|
||||
// we can't start an interactive rebase from the first commit without passing the
|
||||
// '--root' arg
|
||||
func getBaseShaOrRoot(commits []*models.Commit, index int) string {
|
||||
func getBaseHashOrRoot(commits []*models.Commit, index int) string {
|
||||
// We assume that the commits slice contains the initial commit of the repo.
|
||||
// Technically this assumption could prove false, but it's unlikely you'll
|
||||
// be starting a rebase from 300 commits ago (which is the original commit limit
|
||||
// at time of writing)
|
||||
if index < len(commits) {
|
||||
return commits[index].Sha
|
||||
return commits[index].Hash
|
||||
} else {
|
||||
return "--root"
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
|
||||
{
|
||||
testName: "returns error when using gpg",
|
||||
gitConfigMockResponses: map[string]string{"commit.gpgsign": "true"},
|
||||
commits: []*models.Commit{{Name: "commit", Sha: "123456"}},
|
||||
commits: []*models.Commit{{Name: "commit", Hash: "123456"}},
|
||||
commitIndex: 0,
|
||||
fileName: []string{"test999.txt"},
|
||||
runner: oscommands.NewFakeRunner(t),
|
||||
@@ -143,8 +143,8 @@ func TestRebaseDiscardOldFileChanges(t *testing.T) {
|
||||
testName: "checks out file if it already existed",
|
||||
gitConfigMockResponses: nil,
|
||||
commits: []*models.Commit{
|
||||
{Name: "commit", Sha: "123456"},
|
||||
{Name: "commit2", Sha: "abcdef"},
|
||||
{Name: "commit", Hash: "123456"},
|
||||
{Name: "commit2", Hash: "abcdef"},
|
||||
},
|
||||
commitIndex: 0,
|
||||
fileName: []string{"test999.txt"},
|
||||
|
||||
@@ -45,7 +45,7 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
|
||||
}
|
||||
|
||||
// note that the unix timestamp here is the timestamp of the COMMIT, not the reflog entry itself,
|
||||
// so two consecutive reflog entries may have both the same SHA and therefore same timestamp.
|
||||
// so two consecutive reflog entries may have both the same hash and therefore same timestamp.
|
||||
// We use the reflog message to disambiguate, and fingers crossed that we never see the same of those
|
||||
// twice in a row. Reason being that it would mean we'd be erroneously exiting early.
|
||||
if lastReflogCommit != nil && self.sameReflogCommit(commit, lastReflogCommit) {
|
||||
@@ -65,7 +65,7 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
|
||||
}
|
||||
|
||||
func (self *ReflogCommitLoader) sameReflogCommit(a *models.Commit, b *models.Commit) bool {
|
||||
return a.Sha == b.Sha && a.UnixTimestamp == b.UnixTimestamp && a.Name == b.Name
|
||||
return a.Hash == b.Hash && a.UnixTimestamp == b.UnixTimestamp && a.Name == b.Name
|
||||
}
|
||||
|
||||
func (self *ReflogCommitLoader) parseLine(line string) (*models.Commit, bool) {
|
||||
@@ -83,7 +83,7 @@ func (self *ReflogCommitLoader) parseLine(line string) (*models.Commit, bool) {
|
||||
}
|
||||
|
||||
return &models.Commit{
|
||||
Sha: fields[0],
|
||||
Hash: fields[0],
|
||||
Name: fields[2],
|
||||
UnixTimestamp: int64(unixTimestamp),
|
||||
Status: models.StatusReflog,
|
||||
|
||||
@@ -50,35 +50,35 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
lastReflogCommit: nil,
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from A to B",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
Parents: []string{"51baa8c1"},
|
||||
},
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from B to A",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
Parents: []string{"51baa8c1"},
|
||||
},
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from A to B",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
Parents: []string{"51baa8c1"},
|
||||
},
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from master to A",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
Parents: []string{"51baa8c1"},
|
||||
},
|
||||
{
|
||||
Sha: "f4ddf2f0d4be4ccc7efa",
|
||||
Hash: "f4ddf2f0d4be4ccc7efa",
|
||||
Name: "checkout: moving from A to master",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643149435,
|
||||
@@ -94,7 +94,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p"}, reflogOutput, nil),
|
||||
|
||||
lastReflogCommit: &models.Commit{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from B to A",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
@@ -102,7 +102,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
},
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from A to B",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
@@ -118,7 +118,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p", "--follow", "--", "path"}, reflogOutput, nil),
|
||||
|
||||
lastReflogCommit: &models.Commit{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from B to A",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
@@ -127,7 +127,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
filterPath: "path",
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from A to B",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
@@ -143,7 +143,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p", "--author=John Doe <john@doe.com>"}, reflogOutput, nil),
|
||||
|
||||
lastReflogCommit: &models.Commit{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from B to A",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
@@ -152,7 +152,7 @@ func TestGetReflogCommits(t *testing.T) {
|
||||
filterAuthor: "John Doe <john@doe.com>",
|
||||
expectedCommits: []*models.Commit{
|
||||
{
|
||||
Sha: "c3c4b66b64c97ffeecde",
|
||||
Hash: "c3c4b66b64c97ffeecde",
|
||||
Name: "checkout: moving from A to B",
|
||||
Status: models.StatusReflog,
|
||||
UnixTimestamp: 1643150483,
|
||||
|
||||
@@ -60,24 +60,24 @@ func (self *StashCommands) Push(message string) error {
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
}
|
||||
|
||||
func (self *StashCommands) Store(sha string, message string) error {
|
||||
func (self *StashCommands) Store(hash string, message string) error {
|
||||
trimmedMessage := strings.Trim(message, " \t")
|
||||
|
||||
cmdArgs := NewGitCmd("stash").Arg("store").
|
||||
ArgIf(trimmedMessage != "", "-m", trimmedMessage).
|
||||
Arg(sha).
|
||||
Arg(hash).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
}
|
||||
|
||||
func (self *StashCommands) Sha(index int) (string, error) {
|
||||
func (self *StashCommands) Hash(index int) (string, error) {
|
||||
cmdArgs := NewGitCmd("rev-parse").
|
||||
Arg(fmt.Sprintf("refs/stash@{%d}", index)).
|
||||
ToArgv()
|
||||
|
||||
sha, _, err := self.cmd.New(cmdArgs).DontLog().RunWithOutputs()
|
||||
return strings.Trim(sha, "\r\n"), err
|
||||
hash, _, err := self.cmd.New(cmdArgs).DontLog().RunWithOutputs()
|
||||
return strings.Trim(hash, "\r\n"), err
|
||||
}
|
||||
|
||||
func (self *StashCommands) ShowStashEntryCmdObj(index int) oscommands.ICmdObj {
|
||||
@@ -179,7 +179,7 @@ func (self *StashCommands) StashIncludeUntrackedChanges(message string) error {
|
||||
}
|
||||
|
||||
func (self *StashCommands) Rename(index int, message string) error {
|
||||
sha, err := self.Sha(index)
|
||||
hash, err := self.Hash(index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -188,7 +188,7 @@ func (self *StashCommands) Rename(index int, message string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = self.Store(sha, message)
|
||||
err = self.Store(hash, message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestStashSave(t *testing.T) {
|
||||
func TestStashStore(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
sha string
|
||||
hash string
|
||||
message string
|
||||
expected []string
|
||||
}
|
||||
@@ -55,19 +55,19 @@ func TestStashStore(t *testing.T) {
|
||||
scenarios := []scenario{
|
||||
{
|
||||
testName: "Non-empty message",
|
||||
sha: "0123456789abcdef",
|
||||
hash: "0123456789abcdef",
|
||||
message: "New stash name",
|
||||
expected: []string{"stash", "store", "-m", "New stash name", "0123456789abcdef"},
|
||||
},
|
||||
{
|
||||
testName: "Empty message",
|
||||
sha: "0123456789abcdef",
|
||||
hash: "0123456789abcdef",
|
||||
message: "",
|
||||
expected: []string{"stash", "store", "0123456789abcdef"},
|
||||
},
|
||||
{
|
||||
testName: "Space message",
|
||||
sha: "0123456789abcdef",
|
||||
hash: "0123456789abcdef",
|
||||
message: " ",
|
||||
expected: []string{"stash", "store", "0123456789abcdef"},
|
||||
},
|
||||
@@ -80,20 +80,20 @@ func TestStashStore(t *testing.T) {
|
||||
ExpectGitArgs(s.expected, "", nil)
|
||||
instance := buildStashCommands(commonDeps{runner: runner})
|
||||
|
||||
assert.NoError(t, instance.Store(s.sha, s.message))
|
||||
assert.NoError(t, instance.Store(s.hash, s.message))
|
||||
runner.CheckForMissingCalls()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStashSha(t *testing.T) {
|
||||
func TestStashHash(t *testing.T) {
|
||||
runner := oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"rev-parse", "refs/stash@{5}"}, "14d94495194651adfd5f070590df566c11d28243\n", nil)
|
||||
instance := buildStashCommands(commonDeps{runner: runner})
|
||||
|
||||
sha, err := instance.Sha(5)
|
||||
hash, err := instance.Hash(5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "14d94495194651adfd5f070590df566c11d28243", sha)
|
||||
assert.Equal(t, "14d94495194651adfd5f070590df566c11d28243", hash)
|
||||
runner.CheckForMissingCalls()
|
||||
}
|
||||
|
||||
@@ -153,8 +153,8 @@ func TestStashRename(t *testing.T) {
|
||||
testName string
|
||||
index int
|
||||
message string
|
||||
expectedShaCmd []string
|
||||
shaResult string
|
||||
expectedHashCmd []string
|
||||
hashResult string
|
||||
expectedDropCmd []string
|
||||
expectedStoreCmd []string
|
||||
}
|
||||
@@ -164,8 +164,8 @@ func TestStashRename(t *testing.T) {
|
||||
testName: "Default case",
|
||||
index: 3,
|
||||
message: "New message",
|
||||
expectedShaCmd: []string{"rev-parse", "refs/stash@{3}"},
|
||||
shaResult: "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd\n",
|
||||
expectedHashCmd: []string{"rev-parse", "refs/stash@{3}"},
|
||||
hashResult: "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd\n",
|
||||
expectedDropCmd: []string{"stash", "drop", "stash@{3}"},
|
||||
expectedStoreCmd: []string{"stash", "store", "-m", "New message", "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd"},
|
||||
},
|
||||
@@ -173,8 +173,8 @@ func TestStashRename(t *testing.T) {
|
||||
testName: "Empty message",
|
||||
index: 4,
|
||||
message: "",
|
||||
expectedShaCmd: []string{"rev-parse", "refs/stash@{4}"},
|
||||
shaResult: "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd\n",
|
||||
expectedHashCmd: []string{"rev-parse", "refs/stash@{4}"},
|
||||
hashResult: "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd\n",
|
||||
expectedDropCmd: []string{"stash", "drop", "stash@{4}"},
|
||||
expectedStoreCmd: []string{"stash", "store", "f0d0f20f2f61ffd6d6bfe0752deffa38845a3edd"},
|
||||
},
|
||||
@@ -184,7 +184,7 @@ func TestStashRename(t *testing.T) {
|
||||
s := s
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
runner := oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs(s.expectedShaCmd, s.shaResult, nil).
|
||||
ExpectGitArgs(s.expectedHashCmd, s.hashResult, nil).
|
||||
ExpectGitArgs(s.expectedDropCmd, "", nil).
|
||||
ExpectGitArgs(s.expectedStoreCmd, "", nil)
|
||||
instance := buildStashCommands(commonDeps{runner: runner})
|
||||
|
||||
@@ -3,6 +3,7 @@ package git_commands
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
@@ -232,7 +233,8 @@ func (self *WorkingTreeCommands) Ignore(filename string) error {
|
||||
|
||||
// Exclude adds a file to the .git/info/exclude for the repo
|
||||
func (self *WorkingTreeCommands) Exclude(filename string) error {
|
||||
return self.os.AppendLineToFile(".git/info/exclude", filename)
|
||||
excludeFile := path.Join(self.repoPaths.repoGitDirPath, "info", "exclude")
|
||||
return self.os.AppendLineToFile(excludeFile, filename)
|
||||
}
|
||||
|
||||
// WorktreeFileDiff returns the diff of a file
|
||||
@@ -311,8 +313,8 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve
|
||||
}
|
||||
|
||||
// CheckoutFile checks out the file for the given commit
|
||||
func (self *WorkingTreeCommands) CheckoutFile(commitSha, fileName string) error {
|
||||
cmdArgs := NewGitCmd("checkout").Arg(commitSha, "--", fileName).
|
||||
func (self *WorkingTreeCommands) CheckoutFile(commitHash, fileName string) error {
|
||||
cmdArgs := NewGitCmd("checkout").Arg(commitHash, "--", fileName).
|
||||
ToArgv()
|
||||
|
||||
return self.cmd.New(cmdArgs).Run()
|
||||
|
||||
@@ -397,18 +397,18 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
||||
|
||||
func TestWorkingTreeCheckoutFile(t *testing.T) {
|
||||
type scenario struct {
|
||||
testName string
|
||||
commitSha string
|
||||
fileName string
|
||||
runner *oscommands.FakeCmdObjRunner
|
||||
test func(error)
|
||||
testName string
|
||||
commitHash string
|
||||
fileName string
|
||||
runner *oscommands.FakeCmdObjRunner
|
||||
test func(error)
|
||||
}
|
||||
|
||||
scenarios := []scenario{
|
||||
{
|
||||
testName: "typical case",
|
||||
commitSha: "11af912",
|
||||
fileName: "test999.txt",
|
||||
testName: "typical case",
|
||||
commitHash: "11af912",
|
||||
fileName: "test999.txt",
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"checkout", "11af912", "--", "test999.txt"}, "", nil),
|
||||
test: func(err error) {
|
||||
@@ -416,9 +416,9 @@ func TestWorkingTreeCheckoutFile(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "returns error if there is one",
|
||||
commitSha: "11af912",
|
||||
fileName: "test999.txt",
|
||||
testName: "returns error if there is one",
|
||||
commitHash: "11af912",
|
||||
fileName: "test999.txt",
|
||||
runner: oscommands.NewFakeRunner(t).
|
||||
ExpectGitArgs([]string{"checkout", "11af912", "--", "test999.txt"}, "", errors.New("error")),
|
||||
test: func(err error) {
|
||||
@@ -432,7 +432,7 @@ func TestWorkingTreeCheckoutFile(t *testing.T) {
|
||||
t.Run(s.testName, func(t *testing.T) {
|
||||
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner})
|
||||
|
||||
s.test(instance.CheckoutFile(s.commitSha, s.fileName))
|
||||
s.test(instance.CheckoutFile(s.commitHash, s.fileName))
|
||||
s.runner.CheckForMissingCalls()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ var githubServiceDef = ServiceDefinition{
|
||||
provider: "github",
|
||||
pullRequestURLIntoDefaultBranch: "/compare/{{.From}}?expand=1",
|
||||
pullRequestURLIntoTargetBranch: "/compare/{{.To}}...{{.From}}?expand=1",
|
||||
commitURL: "/commit/{{.CommitSha}}",
|
||||
commitURL: "/commit/{{.CommitHash}}",
|
||||
regexStrings: defaultUrlRegexStrings,
|
||||
repoURLTemplate: defaultRepoURLTemplate,
|
||||
}
|
||||
@@ -23,7 +23,7 @@ var bitbucketServiceDef = ServiceDefinition{
|
||||
provider: "bitbucket",
|
||||
pullRequestURLIntoDefaultBranch: "/pull-requests/new?source={{.From}}&t=1",
|
||||
pullRequestURLIntoTargetBranch: "/pull-requests/new?source={{.From}}&dest={{.To}}&t=1",
|
||||
commitURL: "/commits/{{.CommitSha}}",
|
||||
commitURL: "/commits/{{.CommitHash}}",
|
||||
regexStrings: []string{
|
||||
`^(?:https?|ssh)://.*/(?P<owner>.*)/(?P<repo>.*?)(?:\.git)?$`,
|
||||
`^.*@.*:(?P<owner>.*)/(?P<repo>.*?)(?:\.git)?$`,
|
||||
@@ -35,7 +35,7 @@ var gitLabServiceDef = ServiceDefinition{
|
||||
provider: "gitlab",
|
||||
pullRequestURLIntoDefaultBranch: "/-/merge_requests/new?merge_request[source_branch]={{.From}}",
|
||||
pullRequestURLIntoTargetBranch: "/-/merge_requests/new?merge_request[source_branch]={{.From}}&merge_request[target_branch]={{.To}}",
|
||||
commitURL: "/-/commit/{{.CommitSha}}",
|
||||
commitURL: "/-/commit/{{.CommitHash}}",
|
||||
regexStrings: defaultUrlRegexStrings,
|
||||
repoURLTemplate: defaultRepoURLTemplate,
|
||||
}
|
||||
@@ -44,7 +44,7 @@ var azdoServiceDef = ServiceDefinition{
|
||||
provider: "azuredevops",
|
||||
pullRequestURLIntoDefaultBranch: "/pullrequestcreate?sourceRef={{.From}}",
|
||||
pullRequestURLIntoTargetBranch: "/pullrequestcreate?sourceRef={{.From}}&targetRef={{.To}}",
|
||||
commitURL: "/commit/{{.CommitSha}}",
|
||||
commitURL: "/commit/{{.CommitHash}}",
|
||||
regexStrings: []string{
|
||||
`^git@ssh.dev.azure.com.*/(?P<org>.*)/(?P<project>.*)/(?P<repo>.*?)(?:\.git)?$`,
|
||||
`^https://.*@dev.azure.com/(?P<org>.*?)/(?P<project>.*?)/_git/(?P<repo>.*?)(?:\.git)?$`,
|
||||
@@ -56,7 +56,7 @@ var bitbucketServerServiceDef = ServiceDefinition{
|
||||
provider: "bitbucketServer",
|
||||
pullRequestURLIntoDefaultBranch: "/pull-requests?create&sourceBranch={{.From}}",
|
||||
pullRequestURLIntoTargetBranch: "/pull-requests?create&targetBranch={{.To}}&sourceBranch={{.From}}",
|
||||
commitURL: "/commits/{{.CommitSha}}",
|
||||
commitURL: "/commits/{{.CommitHash}}",
|
||||
regexStrings: []string{
|
||||
`^ssh://git@.*/(?P<project>.*)/(?P<repo>.*?)(?:\.git)?$`,
|
||||
`^https://.*/scm/(?P<project>.*)/(?P<repo>.*?)(?:\.git)?$`,
|
||||
@@ -68,7 +68,7 @@ var giteaServiceDef = ServiceDefinition{
|
||||
provider: "gitea",
|
||||
pullRequestURLIntoDefaultBranch: "/compare/{{.From}}",
|
||||
pullRequestURLIntoTargetBranch: "/compare/{{.To}}...{{.From}}",
|
||||
commitURL: "/commit/{{.CommitSha}}",
|
||||
commitURL: "/commit/{{.CommitHash}}",
|
||||
regexStrings: defaultUrlRegexStrings,
|
||||
repoURLTemplate: defaultRepoURLTemplate,
|
||||
}
|
||||
|
||||
@@ -51,13 +51,13 @@ func (self *HostingServiceMgr) GetPullRequestURL(from string, to string) (string
|
||||
}
|
||||
}
|
||||
|
||||
func (self *HostingServiceMgr) GetCommitURL(commitSha string) (string, error) {
|
||||
func (self *HostingServiceMgr) GetCommitURL(commitHash string) (string, error) {
|
||||
gitService, err := self.getService()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pullRequestURL := gitService.getCommitURL(commitSha)
|
||||
pullRequestURL := gitService.getCommitURL(commitHash)
|
||||
|
||||
return pullRequestURL, nil
|
||||
}
|
||||
@@ -174,8 +174,8 @@ func (self *Service) getPullRequestURLIntoTargetBranch(from string, to string) s
|
||||
return self.resolveUrl(self.pullRequestURLIntoTargetBranch, map[string]string{"From": from, "To": to})
|
||||
}
|
||||
|
||||
func (self *Service) getCommitURL(commitSha string) string {
|
||||
return self.resolveUrl(self.commitURL, map[string]string{"CommitSha": commitSha})
|
||||
func (self *Service) getCommitURL(commitHash string) string {
|
||||
return self.resolveUrl(self.commitURL, map[string]string{"CommitHash": commitHash})
|
||||
}
|
||||
|
||||
func (self *Service) resolveUrl(templateString string, args map[string]string) string {
|
||||
|
||||
@@ -3,8 +3,8 @@ package models
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// Special commit hash for empty tree object
|
||||
@@ -43,7 +43,7 @@ const (
|
||||
|
||||
// Commit : A git commit
|
||||
type Commit struct {
|
||||
Sha string
|
||||
Hash string
|
||||
Name string
|
||||
Status CommitStatus
|
||||
Action todo.TodoCommand
|
||||
@@ -54,20 +54,20 @@ type Commit struct {
|
||||
UnixTimestamp int64
|
||||
Divergence Divergence // set to DivergenceNone unless we are showing the divergence view
|
||||
|
||||
// SHAs of parent commits (will be multiple if it's a merge commit)
|
||||
// Hashes of parent commits (will be multiple if it's a merge commit)
|
||||
Parents []string
|
||||
}
|
||||
|
||||
func (c *Commit) ShortSha() string {
|
||||
return utils.ShortSha(c.Sha)
|
||||
func (c *Commit) ShortHash() string {
|
||||
return utils.ShortHash(c.Hash)
|
||||
}
|
||||
|
||||
func (c *Commit) FullRefName() string {
|
||||
return c.Sha
|
||||
return c.Hash
|
||||
}
|
||||
|
||||
func (c *Commit) RefName() string {
|
||||
return c.Sha
|
||||
return c.Hash
|
||||
}
|
||||
|
||||
func (c *Commit) ParentRefName() string {
|
||||
@@ -86,7 +86,7 @@ func (c *Commit) ID() string {
|
||||
}
|
||||
|
||||
func (c *Commit) Description() string {
|
||||
return fmt.Sprintf("%s %s", c.Sha[:7], c.Name)
|
||||
return fmt.Sprintf("%s %s", c.Hash[:7], c.Name)
|
||||
}
|
||||
|
||||
func (c *Commit) IsMerge() bool {
|
||||
|
||||
@@ -220,9 +220,6 @@ func (self *cmdObjRunner) runAndStreamAux(
|
||||
cmdObj ICmdObj,
|
||||
onRun func(*cmdHandler, io.Writer),
|
||||
) error {
|
||||
// if we're streaming this we don't want any fancy terminal stuff
|
||||
cmdObj.AddEnvVars("TERM=dumb")
|
||||
|
||||
cmdWriter := self.guiIO.newCmdWriterFn()
|
||||
|
||||
if cmdObj.ShouldLog() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -86,7 +86,7 @@ func CopyDir(src string, dst string) (err error) {
|
||||
return err
|
||||
}
|
||||
if !si.IsDir() {
|
||||
return fmt.Errorf("source is not a directory")
|
||||
return errors.New("source is not a directory")
|
||||
}
|
||||
|
||||
_, err = os.Stat(dst)
|
||||
|
||||
@@ -33,7 +33,7 @@ type (
|
||||
|
||||
// PatchBuilder manages the building of a patch for a commit to be applied to another commit (or the working tree, or removed from the current commit). We also support building patches from things like stashes, for which there is less flexibility
|
||||
type PatchBuilder struct {
|
||||
// To is the commit sha if we're dealing with files of a commit, or a stash ref for a stash
|
||||
// To is the commit hash if we're dealing with files of a commit, or a stash ref for a stash
|
||||
To string
|
||||
From string
|
||||
reverse bool
|
||||
@@ -46,7 +46,7 @@ type PatchBuilder struct {
|
||||
fileInfoMap map[string]*fileInfo
|
||||
Log *logrus.Entry
|
||||
|
||||
// loadFileDiff loads the diff of a file, for a given to (typically a commit SHA)
|
||||
// loadFileDiff loads the diff of a file, for a given to (typically a commit hash)
|
||||
loadFileDiff loadFileDiffFunc
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils/yaml_utils"
|
||||
yaml "github.com/jesseduffield/yaml"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// AppConfig contains the base configuration fields required for lazygit.
|
||||
@@ -164,6 +164,10 @@ func loadUserConfig(configFiles []string, base *UserConfig) (*UserConfig, error)
|
||||
if err := yaml.Unmarshal(content, base); err != nil {
|
||||
return nil, fmt.Errorf("The config at `%s` couldn't be parsed, please inspect it before opening up an issue.\n%w", path, err)
|
||||
}
|
||||
|
||||
if err := base.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("The config at `%s` has a validation error.\n%w", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
return base, nil
|
||||
@@ -180,6 +184,11 @@ func migrateUserConfig(path string, content []byte) ([]byte, error) {
|
||||
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
|
||||
}
|
||||
|
||||
changedContent, err = changeNullKeybindingsToDisabled(changedContent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
|
||||
}
|
||||
|
||||
// Add more migrations here...
|
||||
|
||||
// Write config back if changed
|
||||
@@ -193,6 +202,17 @@ func migrateUserConfig(path string, content []byte) ([]byte, error) {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func changeNullKeybindingsToDisabled(changedContent []byte) ([]byte, error) {
|
||||
return yaml_utils.Walk(changedContent, func(node *yaml.Node, path string) bool {
|
||||
if strings.HasPrefix(path, "keybinding.") && node.Kind == yaml.ScalarNode && node.Tag == "!!null" {
|
||||
node.Value = "<disabled>"
|
||||
node.Tag = "!!str"
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (c *AppConfig) GetDebug() bool {
|
||||
return c.Debug
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
yaml "github.com/jesseduffield/yaml"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// NewDummyAppConfig creates a new dummy AppConfig for testing
|
||||
|
||||
@@ -145,6 +145,11 @@ type GuiConfig struct {
|
||||
// How things are filtered when typing '/'.
|
||||
// One of 'substring' (default) | 'fuzzy'
|
||||
FilterMode string `yaml:"filterMode" jsonschema:"enum=substring,enum=fuzzy"`
|
||||
// Config relating to the spinner.
|
||||
Spinner SpinnerConfig `yaml:"spinner"`
|
||||
// Status panel view.
|
||||
// One of 'dashboard' (default) | 'allBranchesLog'
|
||||
StatusPanelView string `yaml:"statusPanelView" jsonschema:"enum=dashboard,enum=allBranchesLog"`
|
||||
}
|
||||
|
||||
func (c *GuiConfig) UseFuzzySearch() bool {
|
||||
@@ -182,6 +187,13 @@ type CommitLengthConfig struct {
|
||||
Show bool `yaml:"show"`
|
||||
}
|
||||
|
||||
type SpinnerConfig struct {
|
||||
// The frames of the spinner animation.
|
||||
Frames []string `yaml:"frames"`
|
||||
// The "speed" of the spinner in milliseconds.
|
||||
Rate int `yaml:"rate" jsonschema:"minimum=1"`
|
||||
}
|
||||
|
||||
type GitConfig struct {
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
|
||||
Paging PagingConfig `yaml:"paging"`
|
||||
@@ -671,6 +683,11 @@ func GetDefaultConfig() *UserConfig {
|
||||
AnimateExplosion: true,
|
||||
PortraitMode: "auto",
|
||||
FilterMode: "substring",
|
||||
Spinner: SpinnerConfig{
|
||||
Frames: []string{"|", "/", "-", "\\"},
|
||||
Rate: 50,
|
||||
},
|
||||
StatusPanelView: "dashboard",
|
||||
},
|
||||
Git: GitConfig{
|
||||
Paging: PagingConfig{
|
||||
|
||||
22
pkg/config/user_config_validation.go
Normal file
22
pkg/config/user_config_validation.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (config *UserConfig) Validate() error {
|
||||
if err := validateEnum("gui.statusPanelView", config.Gui.StatusPanelView, []string{"dashboard", "allBranchesLog"}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateEnum(name string, value string, allowedValues []string) error {
|
||||
if slices.Contains(allowedValues, value) {
|
||||
return nil
|
||||
}
|
||||
allowedValuesStr := strings.Join(allowedValues, ", ")
|
||||
return fmt.Errorf("Unexpected value '%s' for '%s'. Allowed values: %s", value, name, allowedValuesStr)
|
||||
}
|
||||
49
pkg/config/user_config_validation_test.go
Normal file
49
pkg/config/user_config_validation_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUserConfigValidate_enums(t *testing.T) {
|
||||
type testCase struct {
|
||||
value string
|
||||
valid bool
|
||||
}
|
||||
|
||||
scenarios := []struct {
|
||||
name string
|
||||
setup func(config *UserConfig, value string)
|
||||
testCases []testCase
|
||||
}{
|
||||
{
|
||||
name: "Gui.StatusPanelView",
|
||||
setup: func(config *UserConfig, value string) {
|
||||
config.Gui.StatusPanelView = value
|
||||
},
|
||||
testCases: []testCase{
|
||||
{value: "dashboard", valid: true},
|
||||
{value: "allBranchesLog", valid: true},
|
||||
{value: "", valid: false},
|
||||
{value: "invalid_value", valid: false},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
for _, testCase := range s.testCases {
|
||||
config := GetDefaultConfig()
|
||||
s.setup(config, testCase.value)
|
||||
err := config.Validate()
|
||||
|
||||
if testCase.valid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -87,9 +87,10 @@ func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan stru
|
||||
if self.pauseBackgroundRefreshes {
|
||||
continue
|
||||
}
|
||||
self.gui.c.OnWorker(func(gocui.Task) {
|
||||
self.gui.c.OnWorker(func(gocui.Task) error {
|
||||
_ = function()
|
||||
done <- struct{}{}
|
||||
return nil
|
||||
})
|
||||
// waiting so that we don't bunch up refreshes if the refresh takes longer than the interval
|
||||
<-done
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type LocalCommitsContext struct {
|
||||
@@ -28,12 +29,12 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
||||
)
|
||||
|
||||
getDisplayStrings := func(startIdx int, endIdx int) [][]string {
|
||||
selectedCommitSha := ""
|
||||
selectedCommitHash := ""
|
||||
|
||||
if c.CurrentContext().GetKey() == LOCAL_COMMITS_CONTEXT_KEY {
|
||||
selectedCommit := viewModel.GetSelected()
|
||||
if selectedCommit != nil {
|
||||
selectedCommitSha = selectedCommit.Sha
|
||||
selectedCommitHash = selectedCommit.Hash
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,14 +48,14 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
||||
c.Model().CheckedOutBranch,
|
||||
hasRebaseUpdateRefsConfig,
|
||||
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
||||
c.Modes().CherryPicking.SelectedShaSet(),
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
c.Modes().MarkedBaseCommit.GetSha(),
|
||||
c.Modes().MarkedBaseCommit.GetHash(),
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
c.UserConfig.Gui.ShortTimeFormat,
|
||||
time.Now(),
|
||||
c.UserConfig.Git.ParseEmoji,
|
||||
selectedCommitSha,
|
||||
selectedCommitHash,
|
||||
startIdx,
|
||||
endIdx,
|
||||
shouldShowGraph(c),
|
||||
@@ -125,6 +126,29 @@ func (self *LocalCommitsContext) GetSelectedRef() types.Ref {
|
||||
return commit
|
||||
}
|
||||
|
||||
// Returns the commit hash of the selected commit, or an empty string if no
|
||||
// commit is selected
|
||||
func (self *LocalCommitsContext) GetSelectedCommitHash() string {
|
||||
commit := self.GetSelected()
|
||||
if commit == nil {
|
||||
return ""
|
||||
}
|
||||
return commit.Hash
|
||||
}
|
||||
|
||||
func (self *LocalCommitsContext) SelectCommitByHash(hash string) bool {
|
||||
if hash == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, idx, found := lo.FindIndexOf(self.GetItems(), func(c *models.Commit) bool { return c.Hash == hash }); found {
|
||||
self.SetSelection(idx)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *LocalCommitsContext) GetDiffTerminals() []string {
|
||||
itemId := self.GetSelectedItemId()
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@@ -74,9 +76,6 @@ func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem, columnAlignment
|
||||
// TODO: move into presentation package
|
||||
func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
||||
menuItems := self.FilteredListViewModel.GetItems()
|
||||
showKeys := lo.SomeBy(menuItems, func(item *types.MenuItem) bool {
|
||||
return item.Key != nil
|
||||
})
|
||||
|
||||
return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
|
||||
displayStrings := item.LabelColumns
|
||||
@@ -84,12 +83,12 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
||||
displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0])
|
||||
}
|
||||
|
||||
if !showKeys {
|
||||
return displayStrings
|
||||
keyLabel := ""
|
||||
if item.Key != nil {
|
||||
keyLabel = style.FgCyan.Sprint(keybindings.LabelFromKey(item.Key))
|
||||
}
|
||||
|
||||
keyLabel := keybindings.LabelFromKey(item.Key)
|
||||
displayStrings = utils.Prepend(displayStrings, style.FgCyan.Sprint(keyLabel))
|
||||
displayStrings = utils.Prepend(displayStrings, keyLabel)
|
||||
return displayStrings
|
||||
})
|
||||
}
|
||||
@@ -151,7 +150,7 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
|
||||
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
|
||||
if selectedItem != nil && selectedItem.DisabledReason != nil {
|
||||
if selectedItem.DisabledReason.ShowErrorInPanel {
|
||||
return self.c.ErrorMsg(selectedItem.DisabledReason.Text)
|
||||
return errors.New(selectedItem.DisabledReason.Text)
|
||||
}
|
||||
|
||||
self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text)
|
||||
|
||||
@@ -22,7 +22,7 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
|
||||
viewModel := NewFilteredListViewModel(
|
||||
func() []*models.Commit { return c.Model().FilteredReflogCommits },
|
||||
func(commit *models.Commit) []string {
|
||||
return []string{commit.ShortSha(), commit.Name}
|
||||
return []string{commit.ShortHash(), commit.Name}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -30,7 +30,7 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
|
||||
return presentation.GetReflogCommitListDisplayStrings(
|
||||
viewModel.GetItems(),
|
||||
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
||||
c.Modes().CherryPicking.SelectedShaSet(),
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
time.Now(),
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
|
||||
@@ -26,7 +26,7 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {
|
||||
|
||||
getDisplayStrings := func(_ int, _ int) [][]string {
|
||||
return presentation.GetRemoteListDisplayStrings(
|
||||
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr)
|
||||
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr, c.UserConfig)
|
||||
}
|
||||
|
||||
return &RemotesContext{
|
||||
|
||||
@@ -44,11 +44,11 @@ func NewSubCommitsContext(
|
||||
return [][]string{}
|
||||
}
|
||||
|
||||
selectedCommitSha := ""
|
||||
selectedCommitHash := ""
|
||||
if c.CurrentContext().GetKey() == SUB_COMMITS_CONTEXT_KEY {
|
||||
selectedCommit := viewModel.GetSelected()
|
||||
if selectedCommit != nil {
|
||||
selectedCommitSha = selectedCommit.Sha
|
||||
selectedCommitHash = selectedCommit.Hash
|
||||
}
|
||||
}
|
||||
branches := []*models.Branch{}
|
||||
@@ -63,14 +63,14 @@ func NewSubCommitsContext(
|
||||
viewModel.GetRef().RefName(),
|
||||
hasRebaseUpdateRefsConfig,
|
||||
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
||||
c.Modes().CherryPicking.SelectedShaSet(),
|
||||
c.Modes().CherryPicking.SelectedHashSet(),
|
||||
c.Modes().Diffing.Ref,
|
||||
"",
|
||||
c.UserConfig.Gui.TimeFormat,
|
||||
c.UserConfig.Gui.ShortTimeFormat,
|
||||
time.Now(),
|
||||
c.UserConfig.Git.ParseEmoji,
|
||||
selectedCommitSha,
|
||||
selectedCommitHash,
|
||||
startIdx,
|
||||
endIdx,
|
||||
// Don't show the graph in the left/right view; we'd like to, but
|
||||
|
||||
@@ -30,7 +30,7 @@ func NewTagsContext(
|
||||
return presentation.GetTagListDisplayStrings(
|
||||
viewModel.GetItems(),
|
||||
c.State().GetItemOperation,
|
||||
c.Modes().Diffing.Ref, c.Tr)
|
||||
c.Modes().Diffing.Ref, c.Tr, c.UserConfig)
|
||||
}
|
||||
|
||||
return &TagsContext{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
@@ -125,9 +126,9 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
|
||||
Title: self.c.Tr.Actions.CopyCommitAttributeToClipboard,
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.CommitSha,
|
||||
Label: self.c.Tr.CommitHash,
|
||||
OnPress: func() error {
|
||||
return self.copyCommitSHAToClipboard(commit)
|
||||
return self.copyCommitHashToClipboard(commit)
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -169,25 +170,25 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
|
||||
})
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitSHAToClipboard(commit *models.Commit) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitSHAToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(commit.Sha); err != nil {
|
||||
return self.c.Error(err)
|
||||
func (self *BasicCommitsController) copyCommitHashToClipboard(commit *models.Commit) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitHashToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(commit.Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(fmt.Sprintf("'%s' %s", commit.Sha, self.c.Tr.CopiedToClipboard))
|
||||
self.c.Toast(fmt.Sprintf("'%s' %s", commit.Hash, self.c.Tr.CopiedToClipboard))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitURLToClipboard(commit *models.Commit) error {
|
||||
url, err := self.c.Helpers().Host.GetCommitURL(commit.Sha)
|
||||
url, err := self.c.Helpers().Host.GetCommitURL(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitURLToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(url); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.CommitURLCopiedToClipboard)
|
||||
@@ -195,14 +196,14 @@ func (self *BasicCommitsController) copyCommitURLToClipboard(commit *models.Comm
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitDiffToClipboard(commit *models.Commit) error {
|
||||
diff, err := self.c.Git().Commit.GetCommitDiff(commit.Sha)
|
||||
diff, err := self.c.Git().Commit.GetCommitDiff(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitDiffToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(diff); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.CommitDiffCopiedToClipboard)
|
||||
@@ -210,16 +211,16 @@ func (self *BasicCommitsController) copyCommitDiffToClipboard(commit *models.Com
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyAuthorToClipboard(commit *models.Commit) error {
|
||||
author, err := self.c.Git().Commit.GetCommitAuthor(commit.Sha)
|
||||
author, err := self.c.Git().Commit.GetCommitAuthor(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
formattedAuthor := fmt.Sprintf("%s <%s>", author.Name, author.Email)
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitAuthorToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(formattedAuthor); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.CommitAuthorCopiedToClipboard)
|
||||
@@ -227,14 +228,14 @@ func (self *BasicCommitsController) copyAuthorToClipboard(commit *models.Commit)
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.Commit) error {
|
||||
message, err := self.c.Git().Commit.GetCommitMessage(commit.Sha)
|
||||
message, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitMessageToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(message); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.CommitMessageCopiedToClipboard)
|
||||
@@ -242,14 +243,14 @@ func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.Commit) error {
|
||||
message, err := self.c.Git().Commit.GetCommitSubject(commit.Sha)
|
||||
message, err := self.c.Git().Commit.GetCommitSubject(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyCommitSubjectToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(message); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.CommitSubjectCopiedToClipboard)
|
||||
@@ -257,14 +258,14 @@ func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) openInBrowser(commit *models.Commit) error {
|
||||
url, err := self.c.Helpers().Host.GetCommitURL(commit.Sha)
|
||||
url, err := self.c.Helpers().Host.GetCommitURL(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.OpenCommitInBrowser)
|
||||
if err := self.c.OS().OpenLink(url); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -275,7 +276,7 @@ func (self *BasicCommitsController) newBranch(commit *models.Commit) error {
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) createResetMenu(commit *models.Commit) error {
|
||||
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Sha)
|
||||
return self.c.Helpers().Refs.CreateGitResetMenu(commit.Hash)
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) checkout(commit *models.Commit) error {
|
||||
@@ -284,7 +285,7 @@ func (self *BasicCommitsController) checkout(commit *models.Commit) error {
|
||||
Prompt: self.c.Tr.SureCheckoutThisCommit,
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CheckoutCommit)
|
||||
return self.c.Helpers().Refs.CheckoutRef(commit.Sha, types.CheckoutRefOptions{})
|
||||
return self.c.Helpers().Refs.CheckoutRef(commit.Hash, types.CheckoutRefOptions{})
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -295,7 +296,7 @@ func (self *BasicCommitsController) copyRange(*models.Commit) error {
|
||||
|
||||
func (self *BasicCommitsController) canCopyCommits(selectedCommits []*models.Commit, startIdx int, endIdx int) *types.DisabledReason {
|
||||
for _, commit := range selectedCommits {
|
||||
if commit.Sha == "" {
|
||||
if commit.Hash == "" {
|
||||
return &types.DisabledReason{Text: self.c.Tr.CannotCherryPickNonCommit, ShowErrorInPanel: true}
|
||||
}
|
||||
|
||||
@@ -314,7 +315,7 @@ func (self *BasicCommitsController) handleOldCherryPickKey() error {
|
||||
"paste": keybindings.Label(self.c.UserConfig.Keybinding.Commits.PasteCommits),
|
||||
})
|
||||
|
||||
return self.c.ErrorMsg(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) openDiffTool(commit *models.Commit) error {
|
||||
|
||||
@@ -69,18 +69,18 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
// Originally we were allowing the user to, from the bisect menu, select whether
|
||||
// they were talking about the selected commit or the current bisect commit,
|
||||
// and that was a bit confusing (and required extra keypresses).
|
||||
selectCurrentAfter := info.GetCurrentSha() == "" || info.GetCurrentSha() == commit.Sha
|
||||
selectCurrentAfter := info.GetCurrentHash() == "" || info.GetCurrentHash() == commit.Hash
|
||||
// we need to wait to reselect if our bisect commits aren't ancestors of our 'start'
|
||||
// ref, because we'll be reloading our commits in that case.
|
||||
waitToReselect := selectCurrentAfter && !self.c.Git().Bisect.ReachableFromStart(info)
|
||||
|
||||
// If we have a current sha already, then we always want to use that one. If
|
||||
// If we have a current hash already, then we always want to use that one. If
|
||||
// not, we're still picking the initial commits before we really start, so
|
||||
// use the selected commit in that case.
|
||||
|
||||
bisecting := info.GetCurrentSha() != ""
|
||||
shaToMark := lo.Ternary(bisecting, info.GetCurrentSha(), commit.Sha)
|
||||
shortShaToMark := utils.ShortSha(shaToMark)
|
||||
bisecting := info.GetCurrentHash() != ""
|
||||
hashToMark := lo.Ternary(bisecting, info.GetCurrentHash(), commit.Hash)
|
||||
shortHashToMark := utils.ShortHash(hashToMark)
|
||||
|
||||
// For marking a commit as bad, when we're not already bisecting, we require
|
||||
// a single item selected, but once we are bisecting, it doesn't matter because
|
||||
@@ -92,11 +92,11 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
|
||||
menuItems := []*types.MenuItem{
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.NewTerm()),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortHashToMark, info.NewTerm()),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BisectMark)
|
||||
if err := self.c.Git().Bisect.Mark(shaToMark, info.NewTerm()); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Mark(hashToMark, info.NewTerm()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
@@ -105,11 +105,11 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
Key: 'b',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.OldTerm()),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortHashToMark, info.OldTerm()),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BisectMark)
|
||||
if err := self.c.Git().Bisect.Mark(shaToMark, info.OldTerm()); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Mark(hashToMark, info.OldTerm()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
@@ -118,11 +118,11 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
Key: 'g',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortShaToMark),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortHashToMark),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BisectSkip)
|
||||
if err := self.c.Git().Bisect.Skip(shaToMark); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Skip(hashToMark); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
@@ -131,13 +131,13 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
Key: 's',
|
||||
},
|
||||
}
|
||||
if info.GetCurrentSha() != "" && info.GetCurrentSha() != commit.Sha {
|
||||
if info.GetCurrentHash() != "" && info.GetCurrentHash() != commit.Hash {
|
||||
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipSelected, commit.ShortSha()),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipSelected, commit.ShortHash()),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BisectSkip)
|
||||
if err := self.c.Git().Bisect.Skip(commit.Sha); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Skip(commit.Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
@@ -165,15 +165,15 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
Title: self.c.Tr.Bisect.BisectMenuTitle,
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.NewTerm()),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortHash(), info.NewTerm()),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StartBisect)
|
||||
if err := self.c.Git().Bisect.Start(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.c.Git().Bisect.Mark(commit.Sha, info.NewTerm()); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Mark(commit.Hash, info.NewTerm()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
@@ -182,15 +182,15 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
Key: 'b',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.OldTerm()),
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortHash(), info.OldTerm()),
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StartBisect)
|
||||
if err := self.c.Git().Bisect.Start(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.c.Git().Bisect.Mark(commit.Sha, info.OldTerm()); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Bisect.Mark(commit.Hash, info.OldTerm()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
@@ -209,7 +209,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
HandleConfirm: func(newTerm string) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StartBisect)
|
||||
if err := self.c.Git().Bisect.StartWithTerms(oldTerm, newTerm); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
@@ -224,15 +224,15 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
})
|
||||
}
|
||||
|
||||
func (self *BisectController) showBisectCompleteMessage(candidateShas []string) error {
|
||||
func (self *BisectController) showBisectCompleteMessage(candidateHashes []string) error {
|
||||
prompt := self.c.Tr.Bisect.CompletePrompt
|
||||
if len(candidateShas) > 1 {
|
||||
if len(candidateHashes) > 1 {
|
||||
prompt = self.c.Tr.Bisect.CompletePromptIndeterminate
|
||||
}
|
||||
|
||||
formattedCommits, err := self.c.Git().Commit.GetCommitsOneline(candidateShas)
|
||||
formattedCommits, err := self.c.Git().Commit.GetCommitsOneline(candidateHashes)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
@@ -241,7 +241,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateShas []string)
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.ResetBisect)
|
||||
if err := self.c.Git().Bisect.Reset(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
@@ -250,33 +250,34 @@ func (self *BisectController) showBisectCompleteMessage(candidateShas []string)
|
||||
}
|
||||
|
||||
func (self *BisectController) afterMark(selectCurrent bool, waitToReselect bool) error {
|
||||
done, candidateShas, err := self.c.Git().Bisect.IsDone()
|
||||
done, candidateHashes, err := self.c.Git().Bisect.IsDone()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.afterBisectMarkRefresh(selectCurrent, waitToReselect); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if done {
|
||||
return self.showBisectCompleteMessage(candidateShas)
|
||||
return self.showBisectCompleteMessage(candidateHashes)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToReselect bool) error {
|
||||
selectFn := func() {
|
||||
selectFn := func() error {
|
||||
if selectCurrent {
|
||||
self.selectCurrentBisectCommit()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if waitToReselect {
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{}, Then: selectFn})
|
||||
} else {
|
||||
selectFn()
|
||||
_ = selectFn()
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
}
|
||||
@@ -284,10 +285,10 @@ func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToR
|
||||
|
||||
func (self *BisectController) selectCurrentBisectCommit() {
|
||||
info := self.c.Git().Bisect.GetInfo()
|
||||
if info.GetCurrentSha() != "" {
|
||||
// find index of commit with that sha, move cursor to that.
|
||||
if info.GetCurrentHash() != "" {
|
||||
// find index of commit with that hash, move cursor to that.
|
||||
for i, commit := range self.c.Model().Commits {
|
||||
if commit.Sha == info.GetCurrentSha() {
|
||||
if commit.Hash == info.GetCurrentHash() {
|
||||
self.context().SetSelection(i)
|
||||
_ = self.context().HandleFocus(types.OnFocusOpts{})
|
||||
break
|
||||
|
||||
@@ -209,7 +209,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
LabelColumns: []string{self.c.Tr.UnsetUpstream},
|
||||
OnPress: func() error {
|
||||
if err := self.c.Git().Branch.UnsetUpstream(selectedBranch.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.Refresh(types.RefreshOptions{
|
||||
Mode: types.SYNC,
|
||||
@@ -218,7 +218,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
types.COMMITS,
|
||||
},
|
||||
}); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -231,11 +231,11 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
return self.c.Helpers().Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.c.Git().Branch.SetUpstream(upstreamRemote, upstreamBranch, selectedBranch.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.Refresh(types.RefreshOptions{
|
||||
Mode: types.SYNC,
|
||||
@@ -244,7 +244,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
types.COMMITS,
|
||||
},
|
||||
}); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -279,7 +279,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
OnPress: func() error {
|
||||
err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -292,7 +292,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
OpensMenu: true,
|
||||
OnPress: func() error {
|
||||
if err := self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranch.ShortUpstreamRefName()); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -334,7 +334,7 @@ func (self *BranchesController) context() *context.BranchesContext {
|
||||
|
||||
func (self *BranchesController) press(selectedBranch *models.Branch) error {
|
||||
if selectedBranch == self.c.Helpers().Refs.GetCheckedOutRef() {
|
||||
return self.c.ErrorMsg(self.c.Tr.AlreadyCheckedOutBranch)
|
||||
return errors.New(self.c.Tr.AlreadyCheckedOutBranch)
|
||||
}
|
||||
|
||||
worktreeForRef, ok := self.worktreeForBranch(selectedBranch)
|
||||
@@ -378,7 +378,7 @@ func (self *BranchesController) promptToCheckoutWorktree(worktree *models.Worktr
|
||||
|
||||
func (self *BranchesController) handleCreatePullRequest(selectedBranch *models.Branch) error {
|
||||
if !selectedBranch.IsTrackingRemote() {
|
||||
return self.c.ErrorMsg(self.c.Tr.PullRequestNoUpstream)
|
||||
return errors.New(self.c.Tr.PullRequestNoUpstream)
|
||||
}
|
||||
return self.createPullRequest(selectedBranch.UpstreamBranch, "")
|
||||
}
|
||||
@@ -395,16 +395,16 @@ func (self *BranchesController) copyPullRequestURL() error {
|
||||
branchExistsOnRemote := self.c.Git().Remote.CheckRemoteBranchExists(branch.Name)
|
||||
|
||||
if !branchExistsOnRemote {
|
||||
return self.c.Error(errors.New(self.c.Tr.NoBranchOnRemote))
|
||||
return errors.New(self.c.Tr.NoBranchOnRemote)
|
||||
}
|
||||
|
||||
url, err := self.c.Helpers().Host.GetPullRequestURL(branch.Name, "")
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyPullRequestURL)
|
||||
if err := self.c.OS().CopyToClipboard(url); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.PullRequestURLCopiedToClipboard)
|
||||
@@ -423,7 +423,7 @@ func (self *BranchesController) forceCheckout() error {
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.ForceCheckoutBranch)
|
||||
if err := self.c.Git().Branch.Checkout(branch.Name, git_commands.CheckoutOptions{Force: true}); err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
},
|
||||
@@ -463,7 +463,7 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er
|
||||
}
|
||||
|
||||
if err := self.c.Git().Branch.New(newBranchName, branch.FullRefName()); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.context().SetSelection(0)
|
||||
@@ -524,7 +524,7 @@ func (self *BranchesController) localDelete(branch *models.Branch) error {
|
||||
return self.forceDelete(branch)
|
||||
}
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
|
||||
})
|
||||
@@ -548,7 +548,7 @@ func (self *BranchesController) forceDelete(branch *models.Branch) error {
|
||||
Prompt: message,
|
||||
HandleConfirm: func() error {
|
||||
if err := self.c.Git().Branch.LocalDelete(branch.Name, true); err != nil {
|
||||
return self.c.ErrorMsg(err.Error())
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}})
|
||||
},
|
||||
@@ -615,13 +615,13 @@ func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *type
|
||||
|
||||
func (self *BranchesController) fastForward(branch *models.Branch) error {
|
||||
if !branch.IsTrackingRemote() {
|
||||
return self.c.ErrorMsg(self.c.Tr.FwdNoUpstream)
|
||||
return errors.New(self.c.Tr.FwdNoUpstream)
|
||||
}
|
||||
if !branch.RemoteBranchStoredLocally() {
|
||||
return self.c.ErrorMsg(self.c.Tr.FwdNoLocalUpstream)
|
||||
return errors.New(self.c.Tr.FwdNoLocalUpstream)
|
||||
}
|
||||
if branch.HasCommitsToPush() {
|
||||
return self.c.ErrorMsg(self.c.Tr.FwdCommitsToPush)
|
||||
return errors.New(self.c.Tr.FwdCommitsToPush)
|
||||
}
|
||||
|
||||
action := self.c.Tr.Actions.FastForwardBranch
|
||||
@@ -688,7 +688,7 @@ func (self *BranchesController) rename(branch *models.Branch) error {
|
||||
HandleConfirm: func(newBranchName string) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RenameBranch)
|
||||
if err := self.c.Git().Branch.Rename(branch.Name, helpers.SanitizedBranchName(newBranchName)); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// need to find where the branch is now so that we can re-select it. That means we need to refetch the branches synchronously and then find our branch
|
||||
@@ -766,7 +766,7 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra
|
||||
LabelColumns: fromToLabelColumns(checkedOutBranch.Name, selectedBranch.Name),
|
||||
OnPress: func() error {
|
||||
if !checkedOutBranch.IsTrackingRemote() || !selectedBranch.IsTrackingRemote() {
|
||||
return self.c.ErrorMsg(self.c.Tr.PullRequestNoUpstream)
|
||||
return errors.New(self.c.Tr.PullRequestNoUpstream)
|
||||
}
|
||||
return self.createPullRequest(checkedOutBranch.UpstreamBranch, selectedBranch.UpstreamBranch)
|
||||
},
|
||||
@@ -783,13 +783,13 @@ func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Bra
|
||||
func (self *BranchesController) createPullRequest(from string, to string) error {
|
||||
url, err := self.c.Helpers().Host.GetPullRequestURL(from, to)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.OpenPullRequest)
|
||||
|
||||
if err := self.c.OS().OpenLink(url); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
@@ -114,7 +116,7 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
|
||||
if err == git_commands.ErrInvalidCommitIndex {
|
||||
return false, nil
|
||||
}
|
||||
return false, self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
|
||||
return false, errors.New(self.c.Tr.CommitWithoutMessageErr)
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
@@ -170,7 +171,7 @@ func (self *CommitFilesController) onClickMain(opts gocui.ViewMouseBindingOpts)
|
||||
func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CheckoutFile)
|
||||
if err := self.c.Git().WorkingTree.CheckoutFile(self.context().GetRef().RefName(), node.GetPath()); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
@@ -179,7 +180,7 @@ func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error
|
||||
func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileNode) error {
|
||||
parentContext, ok := self.c.CurrentContext().GetParentContext()
|
||||
if !ok || parentContext.GetKey() != context.LOCAL_COMMITS_CONTEXT_KEY {
|
||||
return self.c.ErrorMsg(self.c.Tr.CanOnlyDiscardFromLocalCommits)
|
||||
return errors.New(self.c.Tr.CanOnlyDiscardFromLocalCommits)
|
||||
}
|
||||
|
||||
if ok, err := self.c.Helpers().PatchBuilding.ValidateNormalWorkingTreeState(); !ok {
|
||||
@@ -208,7 +209,7 @@ func (self *CommitFilesController) discard(selectedNodes []*filetree.CommitFileN
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +295,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
|
||||
return patchOperationFunction(file.Name)
|
||||
})
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func (self *ContextLinesController) Context() types.Context {
|
||||
func (self *ContextLinesController) Increase() error {
|
||||
if self.isShowingDiff() {
|
||||
if err := self.checkCanChangeContext(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.AppState.DiffContextSize++
|
||||
@@ -80,7 +80,7 @@ func (self *ContextLinesController) Decrease() error {
|
||||
|
||||
if self.isShowingDiff() && old_size > 1 {
|
||||
if err := self.checkCanChangeContext(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.AppState.DiffContextSize = old_size - 1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
@@ -15,11 +16,11 @@ type CustomPatchOptionsMenuAction struct {
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
if !self.c.Git().Patch.PatchBuilder.Active() {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoPatchError)
|
||||
return errors.New(self.c.Tr.NoPatchError)
|
||||
}
|
||||
|
||||
if self.c.Git().Patch.PatchBuilder.IsEmpty() {
|
||||
return self.c.ErrorMsg(self.c.Tr.EmptyPatchError)
|
||||
return errors.New(self.c.Tr.EmptyPatchError)
|
||||
}
|
||||
|
||||
menuItems := []*types.MenuItem{
|
||||
@@ -67,7 +68,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
|
||||
if self.c.CurrentContext().GetKey() == self.c.Contexts().LocalCommits.GetKey() {
|
||||
selectedCommit := self.c.Contexts().LocalCommits.GetSelected()
|
||||
if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Sha {
|
||||
if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Hash {
|
||||
|
||||
var disabledReason *types.DisabledReason
|
||||
if self.c.Contexts().LocalCommits.AreMultipleItemsSelected() {
|
||||
@@ -80,7 +81,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
append(
|
||||
[]*types.MenuItem{
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Sha),
|
||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Hash),
|
||||
Tooltip: self.c.Tr.MovePatchToSelectedCommitTooltip,
|
||||
OnPress: self.handleMovePatchToSelectedCommit,
|
||||
Key: 'm',
|
||||
@@ -106,7 +107,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int {
|
||||
for index, commit := range self.c.Model().Commits {
|
||||
if commit.Sha == self.c.Git().Patch.PatchBuilder.To {
|
||||
if commit.Hash == self.c.Git().Patch.PatchBuilder.To {
|
||||
return index
|
||||
}
|
||||
}
|
||||
@@ -115,7 +116,7 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int {
|
||||
|
||||
func (self *CustomPatchOptionsMenuAction) validateNormalWorkingTreeState() (bool, error) {
|
||||
if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
|
||||
return false, self.c.ErrorMsg(self.c.Tr.CantPatchWhileRebasingError)
|
||||
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -234,7 +235,7 @@ func (self *CustomPatchOptionsMenuAction) handleApplyPatch(reverse bool) error {
|
||||
}
|
||||
self.c.LogAction(action)
|
||||
if err := self.c.Git().Patch.ApplyCustomPatch(reverse); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
}
|
||||
@@ -244,7 +245,7 @@ func (self *CustomPatchOptionsMenuAction) copyPatchToClipboard() error {
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopyPatchToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(patch); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Toast(self.c.Tr.PatchCopiedToClipboard)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
@@ -388,7 +389,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||
// if any files within have inline merge conflicts we can't stage or unstage,
|
||||
// or it'll end up with those >>>>>> lines actually staged
|
||||
if node.GetHasInlineMergeConflicts() {
|
||||
return self.c.ErrorMsg(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
|
||||
return errors.New(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +411,7 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||
}
|
||||
|
||||
if err := self.c.Git().WorkingTree.StageFiles(toPaths(selectedNodes)); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
self.c.LogAction(self.c.Tr.Actions.UnstageFile)
|
||||
@@ -428,13 +429,13 @@ func (self *FilesController) pressWithLock(selectedNodes []*filetree.FileNode) e
|
||||
|
||||
if len(untrackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageUntrackedFiles(toPaths(untrackedNodes)); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(trackedNodes) > 0 {
|
||||
if err := self.c.Git().WorkingTree.UnstageTrackedFiles(toPaths(trackedNodes)); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -496,7 +497,7 @@ func (self *FilesController) EnterFile(opts types.OnFocusOpts) error {
|
||||
return self.switchToMerge()
|
||||
}
|
||||
if file.HasMergeConflicts {
|
||||
return self.c.ErrorMsg(self.c.Tr.FileStagingRequirements)
|
||||
return errors.New(self.c.Tr.FileStagingRequirements)
|
||||
}
|
||||
|
||||
return self.c.PushContext(self.c.Contexts().Staging, opts)
|
||||
@@ -523,7 +524,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
|
||||
// if any files within have inline merge conflicts we can't stage or unstage,
|
||||
// or it'll end up with those >>>>>> lines actually staged
|
||||
if root.GetHasInlineMergeConflicts() {
|
||||
return self.c.ErrorMsg(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
|
||||
return errors.New(self.c.Tr.ErrStageDirWithInlineMergeConflicts)
|
||||
}
|
||||
|
||||
if root.GetHasUnstagedChanges() {
|
||||
@@ -534,7 +535,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
|
||||
}
|
||||
|
||||
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
self.c.LogAction(self.c.Tr.Actions.UnstageAllFiles)
|
||||
@@ -544,7 +545,7 @@ func (self *FilesController) toggleStagedAllWithLock() error {
|
||||
}
|
||||
|
||||
if err := self.c.Git().WorkingTree.UnstageAll(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,30 +607,17 @@ func (self *FilesController) ignoreOrExcludeFile(node *filetree.FileNode, trText
|
||||
|
||||
func (self *FilesController) ignore(node *filetree.FileNode) error {
|
||||
if node.GetPath() == ".gitignore" {
|
||||
return self.c.ErrorMsg(self.c.Tr.Actions.IgnoreFileErr)
|
||||
return errors.New(self.c.Tr.Actions.IgnoreFileErr)
|
||||
}
|
||||
err := self.ignoreOrExcludeFile(node, self.c.Tr.IgnoreTracked, self.c.Tr.IgnoreTrackedPrompt, self.c.Tr.Actions.IgnoreExcludeFile, self.c.Git().WorkingTree.Ignore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return self.ignoreOrExcludeFile(node, self.c.Tr.IgnoreTracked, self.c.Tr.IgnoreTrackedPrompt, self.c.Tr.Actions.IgnoreExcludeFile, self.c.Git().WorkingTree.Ignore)
|
||||
}
|
||||
|
||||
func (self *FilesController) exclude(node *filetree.FileNode) error {
|
||||
if node.GetPath() == ".git/info/exclude" {
|
||||
return self.c.ErrorMsg(self.c.Tr.Actions.ExcludeFileErr)
|
||||
}
|
||||
|
||||
if node.GetPath() == ".gitignore" {
|
||||
return self.c.ErrorMsg(self.c.Tr.Actions.ExcludeGitIgnoreErr)
|
||||
return errors.New(self.c.Tr.Actions.ExcludeGitIgnoreErr)
|
||||
}
|
||||
|
||||
err := self.ignoreOrExcludeFile(node, self.c.Tr.ExcludeTracked, self.c.Tr.ExcludeTrackedPrompt, self.c.Tr.Actions.ExcludeFile, self.c.Git().WorkingTree.Exclude)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return self.ignoreOrExcludeFile(node, self.c.Tr.ExcludeTracked, self.c.Tr.ExcludeTrackedPrompt, self.c.Tr.Actions.ExcludeFile, self.c.Git().WorkingTree.Exclude)
|
||||
}
|
||||
|
||||
func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error {
|
||||
@@ -640,7 +628,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
|
||||
LabelColumns: []string{self.c.Tr.IgnoreFile},
|
||||
OnPress: func() error {
|
||||
if err := self.ignore(node); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -650,7 +638,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
|
||||
LabelColumns: []string{self.c.Tr.ExcludeFile},
|
||||
OnPress: func() error {
|
||||
if err := self.exclude(node); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
@@ -671,7 +659,7 @@ func (self *FilesController) handleAmendCommitPress() error {
|
||||
HandleConfirm: func() error {
|
||||
return self.c.Helpers().WorkingTree.WithEnsureCommitableFiles(func() error {
|
||||
if len(self.c.Model().Commits) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoCommitToAmend)
|
||||
return errors.New(self.c.Tr.NoCommitToAmend)
|
||||
}
|
||||
|
||||
return self.c.Helpers().AmendHelper.AmendHead()
|
||||
@@ -778,7 +766,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
Label: self.c.Tr.StashAllChanges,
|
||||
OnPress: func() error {
|
||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
|
||||
return errors.New(self.c.Tr.NoFilesToStash)
|
||||
}
|
||||
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges)
|
||||
},
|
||||
@@ -788,7 +776,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
Label: self.c.Tr.StashAllChangesKeepIndex,
|
||||
OnPress: func() error {
|
||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
|
||||
return errors.New(self.c.Tr.NoFilesToStash)
|
||||
}
|
||||
// if there are no staged files it behaves the same as Stash.Save
|
||||
return self.handleStashSave(self.c.Git().Stash.StashAndKeepIndex, self.c.Tr.Actions.StashAllChangesKeepIndex)
|
||||
@@ -807,7 +795,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
OnPress: func() error {
|
||||
// there must be something in staging otherwise the current implementation mucks the stash up
|
||||
if !self.c.Helpers().WorkingTree.AnyStagedFiles() {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash)
|
||||
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
|
||||
}
|
||||
return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges)
|
||||
},
|
||||
@@ -817,7 +805,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
Label: self.c.Tr.StashUnstagedChanges,
|
||||
OnPress: func() error {
|
||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesToStash)
|
||||
return errors.New(self.c.Tr.NoFilesToStash)
|
||||
}
|
||||
if self.c.Helpers().WorkingTree.AnyStagedFiles() {
|
||||
return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges)
|
||||
@@ -838,7 +826,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
Label: self.c.Tr.CopyFileName,
|
||||
OnPress: func() error {
|
||||
if err := self.c.OS().CopyToClipboard(node.Name()); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Toast(self.c.Tr.FileNameCopiedToast)
|
||||
return nil
|
||||
@@ -850,7 +838,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
Label: self.c.Tr.CopyFilePath,
|
||||
OnPress: func() error {
|
||||
if err := self.c.OS().CopyToClipboard(node.Path); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Toast(self.c.Tr.FilePathCopiedToast)
|
||||
return nil
|
||||
@@ -866,10 +854,10 @@ func (self *FilesController) openCopyMenu() error {
|
||||
hasStaged := self.hasPathStagedChanges(node)
|
||||
diff, err := self.c.Git().Diff.GetPathDiff(path, hasStaged)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.OS().CopyToClipboard(diff); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Toast(self.c.Tr.FileDiffCopiedToast)
|
||||
return nil
|
||||
@@ -891,10 +879,10 @@ func (self *FilesController) openCopyMenu() error {
|
||||
hasStaged := self.c.Helpers().WorkingTree.AnyStagedFiles()
|
||||
diff, err := self.c.Git().Diff.GetAllDiff(hasStaged)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.OS().CopyToClipboard(diff); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Toast(self.c.Tr.AllFilesDiffCopiedToast)
|
||||
return nil
|
||||
@@ -970,7 +958,7 @@ func (self *FilesController) handleStashSave(stashFunc func(message string) erro
|
||||
self.c.LogAction(action)
|
||||
|
||||
if err := stashFunc(stashComment); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH, types.FILES}})
|
||||
},
|
||||
@@ -988,7 +976,7 @@ func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) e
|
||||
func (self *FilesController) fetch() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.FetchingStatus, func(task gocui.Task) error {
|
||||
if err := self.fetchAux(task); err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
})
|
||||
@@ -999,7 +987,7 @@ func (self *FilesController) fetchAux(task gocui.Task) (err error) {
|
||||
err = self.c.Git().Sync.Fetch(task)
|
||||
|
||||
if err != nil && strings.Contains(err.Error(), "exit status 128") {
|
||||
_ = self.c.ErrorMsg(self.c.Tr.PassUnameWrong)
|
||||
return errors.New(self.c.Tr.PassUnameWrong)
|
||||
}
|
||||
|
||||
_ = self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.COMMITS, types.REMOTES, types.TAGS}, Mode: types.ASYNC})
|
||||
@@ -1086,7 +1074,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
|
||||
|
||||
for _, node := range selectedNodes {
|
||||
if err := self.c.Git().WorkingTree.DiscardAllDirChanges(node); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1114,7 +1102,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
|
||||
|
||||
for _, node := range selectedNodes {
|
||||
if err := self.c.Git().WorkingTree.DiscardUnstagedDirChanges(node); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1140,15 +1128,15 @@ func (self *FilesController) ResetSubmodule(submodule *models.SubmoduleConfig) e
|
||||
file := self.c.Helpers().WorkingTree.FileForSubmodule(submodule)
|
||||
if file != nil {
|
||||
if err := self.c.Git().WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.c.Git().Submodule.Stash(submodule); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.Git().Submodule.Reset(submodule); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})
|
||||
|
||||
@@ -109,6 +109,8 @@ func (self *FilteringMenuAction) setFilteringAuthor(author string) error {
|
||||
}
|
||||
|
||||
func (self *FilteringMenuAction) setFiltering() error {
|
||||
self.c.Modes().Filtering.SetSelectedCommitHash(self.c.Contexts().LocalCommits.GetSelectedCommitHash())
|
||||
|
||||
repoState := self.c.State().GetRepoState()
|
||||
if repoState.GetScreenMode() == types.SCREEN_NORMAL {
|
||||
repoState.SetScreenMode(types.SCREEN_HALF)
|
||||
@@ -118,8 +120,9 @@ func (self *FilteringMenuAction) setFiltering() error {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() error {
|
||||
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||
self.c.Contexts().LocalCommits.FocusLine()
|
||||
return nil
|
||||
}})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
@@ -46,7 +47,7 @@ func (self *GitFlowController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
||||
|
||||
func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) error {
|
||||
if !self.c.Git().Flow.GitFlowEnabled() {
|
||||
return self.c.ErrorMsg("You need to install git-flow and enable it in this repo to use git-flow features")
|
||||
return errors.New("You need to install git-flow and enable it in this repo to use git-flow features")
|
||||
}
|
||||
|
||||
startHandler := func(branchType string) func() error {
|
||||
@@ -103,7 +104,7 @@ func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) er
|
||||
func (self *GitFlowController) gitFlowFinishBranch(branchName string) error {
|
||||
cmdObj, err := self.c.Git().Flow.FinishCmdObj(branchName)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.GitFlowFinish)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/status"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type AppStatusHelper struct {
|
||||
@@ -60,26 +59,20 @@ func (self appStatusHelperTask) Continue() {
|
||||
|
||||
// withWaitingStatus wraps a function and shows a waiting status while the function is still executing
|
||||
func (self *AppStatusHelper) WithWaitingStatus(message string, f func(gocui.Task) error) {
|
||||
self.c.OnWorker(func(task gocui.Task) {
|
||||
self.statusMgr().WithWaitingStatus(message, self.renderAppStatus, func(waitingStatusHandle *status.WaitingStatusHandle) {
|
||||
if err := f(appStatusHelperTask{task, waitingStatusHandle}); err != nil {
|
||||
self.c.OnUIThread(func() error {
|
||||
return self.c.Error(err)
|
||||
})
|
||||
}
|
||||
self.c.OnWorker(func(task gocui.Task) error {
|
||||
return self.statusMgr().WithWaitingStatus(message, self.renderAppStatus, func(waitingStatusHandle *status.WaitingStatusHandle) error {
|
||||
return f(appStatusHelperTask{task, waitingStatusHandle})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) {
|
||||
self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) {
|
||||
func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) error {
|
||||
return self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) error {
|
||||
stop := make(chan struct{})
|
||||
defer func() { close(stop) }()
|
||||
self.renderAppStatusSync(stop)
|
||||
|
||||
if err := f(); err != nil {
|
||||
_ = self.c.Error(err)
|
||||
}
|
||||
return f()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -88,16 +81,16 @@ func (self *AppStatusHelper) HasStatus() bool {
|
||||
}
|
||||
|
||||
func (self *AppStatusHelper) GetStatusString() string {
|
||||
appStatus, _ := self.statusMgr().GetStatusString()
|
||||
appStatus, _ := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
return appStatus
|
||||
}
|
||||
|
||||
func (self *AppStatusHelper) renderAppStatus() {
|
||||
self.c.OnWorker(func(_ gocui.Task) {
|
||||
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
appStatus, color := self.statusMgr().GetStatusString()
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
self.c.Views().AppStatus.FgColor = color
|
||||
self.c.OnUIThread(func() error {
|
||||
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
|
||||
@@ -105,9 +98,10 @@ func (self *AppStatusHelper) renderAppStatus() {
|
||||
})
|
||||
|
||||
if appStatus == "" {
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -130,7 +124,7 @@ func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
appStatus, color := self.statusMgr().GetStatusString()
|
||||
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
|
||||
self.c.Views().AppStatus.FgColor = color
|
||||
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
|
||||
// Redraw all views of the bottom line:
|
||||
|
||||
@@ -19,7 +19,7 @@ func (self *BisectHelper) Reset() error {
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.ResetBisect)
|
||||
if err := self.c.Git().Bisect.Reset(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.PostBisectCommandRefresh()
|
||||
|
||||
@@ -37,7 +37,7 @@ func (self *BranchesHelper) ConfirmDeleteRemote(remoteName string, branchName st
|
||||
return self.c.WithWaitingStatus(self.c.Tr.DeletingStatus, func(task gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.DeleteRemoteBranch)
|
||||
if err := self.c.Git().Remote.DeleteRemoteBranch(task, remoteName, branchName); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||
})
|
||||
|
||||
@@ -38,10 +38,10 @@ func (self *CherryPickHelper) CopyRange(commitsList []*models.Commit, context ty
|
||||
return err
|
||||
}
|
||||
|
||||
commitSet := self.getData().SelectedShaSet()
|
||||
commitSet := self.getData().SelectedHashSet()
|
||||
|
||||
allCommitsCopied := lo.EveryBy(commitsList[startIdx:endIdx+1], func(commit *models.Commit) bool {
|
||||
return commitSet.Includes(commit.Sha)
|
||||
return commitSet.Includes(commit.Hash)
|
||||
})
|
||||
|
||||
// if all selected commits are already copied, we'll uncopy them
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -167,7 +168,7 @@ func (self *CommitsHelper) HandleCommitConfirm() error {
|
||||
summary, description := self.getCommitSummary(), self.getCommitDescription()
|
||||
|
||||
if summary == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
|
||||
return errors.New(self.c.Tr.CommitWithoutMessageErr)
|
||||
}
|
||||
|
||||
err := self.c.Contexts().CommitMessage.OnConfirm(summary, description)
|
||||
|
||||
@@ -36,7 +36,7 @@ func (self *ConfirmationHelper) wrappedConfirmationFunction(cancel goContext.Can
|
||||
|
||||
if function != nil {
|
||||
if err := function(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ
|
||||
confirmationView.RenderTextArea()
|
||||
} else {
|
||||
self.c.ResetViewOrigin(confirmationView)
|
||||
self.c.SetViewContent(confirmationView, style.AttrBold.Sprint(opts.Prompt))
|
||||
self.c.SetViewContent(confirmationView, style.AttrBold.Sprint(underlineLinks(opts.Prompt)))
|
||||
}
|
||||
|
||||
if err := self.setKeyBindings(cancel, opts); err != nil {
|
||||
@@ -228,6 +228,32 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ
|
||||
return self.c.PushContext(self.c.Contexts().Confirmation)
|
||||
}
|
||||
|
||||
func underlineLinks(text string) string {
|
||||
result := ""
|
||||
remaining := text
|
||||
for {
|
||||
linkStart := strings.Index(remaining, "https://")
|
||||
if linkStart == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
linkEnd := strings.IndexAny(remaining[linkStart:], " \n>")
|
||||
if linkEnd == -1 {
|
||||
linkEnd = len(remaining)
|
||||
} else {
|
||||
linkEnd += linkStart
|
||||
}
|
||||
underlinedLink := style.AttrUnderline.Sprint(remaining[linkStart:linkEnd])
|
||||
if strings.HasSuffix(underlinedLink, "\x1b[0m") {
|
||||
// Replace the "all styles off" code with "underline off" code
|
||||
underlinedLink = underlinedLink[:len(underlinedLink)-2] + "24m"
|
||||
}
|
||||
result += remaining[:linkStart] + underlinedLink
|
||||
remaining = remaining[linkEnd:]
|
||||
}
|
||||
return result + remaining
|
||||
}
|
||||
|
||||
func (self *ConfirmationHelper) setKeyBindings(cancel goContext.CancelFunc, opts types.CreatePopupPanelOpts) error {
|
||||
var onConfirm func() error
|
||||
if opts.HandleConfirmPrompt != nil {
|
||||
|
||||
63
pkg/gui/controllers/helpers/confirmation_helper_test.go
Normal file
63
pkg/gui/controllers/helpers/confirmation_helper_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/xo/terminfo"
|
||||
)
|
||||
|
||||
func Test_underlineLinks(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
text string
|
||||
expectedResult string
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
text: "",
|
||||
expectedResult: "",
|
||||
},
|
||||
{
|
||||
name: "no links",
|
||||
text: "abc",
|
||||
expectedResult: "abc",
|
||||
},
|
||||
{
|
||||
name: "entire string is a link",
|
||||
text: "https://example.com",
|
||||
expectedResult: "\x1b[4mhttps://example.com\x1b[24m",
|
||||
},
|
||||
{
|
||||
name: "link preceeded and followed by text",
|
||||
text: "bla https://example.com xyz",
|
||||
expectedResult: "bla \x1b[4mhttps://example.com\x1b[24m xyz",
|
||||
},
|
||||
{
|
||||
name: "more than one link",
|
||||
text: "bla https://link1 blubb https://link2 xyz",
|
||||
expectedResult: "bla \x1b[4mhttps://link1\x1b[24m blubb \x1b[4mhttps://link2\x1b[24m xyz",
|
||||
},
|
||||
{
|
||||
name: "link in angle brackets",
|
||||
text: "See <https://example.com> for details",
|
||||
expectedResult: "See <\x1b[4mhttps://example.com\x1b[24m> for details",
|
||||
},
|
||||
{
|
||||
name: "link followed by newline",
|
||||
text: "URL: https://example.com\nNext line",
|
||||
expectedResult: "URL: \x1b[4mhttps://example.com\x1b[24m\nNext line",
|
||||
},
|
||||
}
|
||||
|
||||
oldColorLevel := color.ForceSetColorLevel(terminfo.ColorLevelMillions)
|
||||
defer color.ForceSetColorLevel(oldColorLevel)
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
result := underlineLinks(s.text)
|
||||
assert.Equal(t, s.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (self *FilesHelper) OpenFile(filename string) error {
|
||||
}
|
||||
self.c.LogAction(self.c.Tr.Actions.OpenFile)
|
||||
if err := self.c.OS().OpenFile(absPath); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -36,33 +38,33 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
|
||||
return err
|
||||
}
|
||||
if diff == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoChangedFiles)
|
||||
return errors.New(self.c.Tr.NoChangedFiles)
|
||||
}
|
||||
|
||||
deletedLineInfos, hasHunksWithOnlyAddedLines := self.parseDiff(diff)
|
||||
if len(deletedLineInfos) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoDeletedLinesInDiff)
|
||||
return errors.New(self.c.Tr.NoDeletedLinesInDiff)
|
||||
}
|
||||
|
||||
shas := self.blameDeletedLines(deletedLineInfos)
|
||||
hashes := self.blameDeletedLines(deletedLineInfos)
|
||||
|
||||
if len(shas) == 0 {
|
||||
if len(hashes) == 0 {
|
||||
// This should never happen
|
||||
return self.c.ErrorMsg(self.c.Tr.NoBaseCommitsFound)
|
||||
return errors.New(self.c.Tr.NoBaseCommitsFound)
|
||||
}
|
||||
if len(shas) > 1 {
|
||||
subjects, err := self.c.Git().Commit.GetShasAndCommitMessagesFirstLine(shas)
|
||||
if len(hashes) > 1 {
|
||||
subjects, err := self.c.Git().Commit.GetHashesAndCommitMessagesFirstLine(hashes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
message := lo.Ternary(hasStagedChanges,
|
||||
self.c.Tr.MultipleBaseCommitsFoundStaged,
|
||||
self.c.Tr.MultipleBaseCommitsFoundUnstaged)
|
||||
return self.c.ErrorMsg(message + "\n\n" + subjects)
|
||||
return fmt.Errorf("%s\n\n%s", message, subjects)
|
||||
}
|
||||
|
||||
commit, index, ok := lo.FindIndexOf(self.c.Model().Commits, func(commit *models.Commit) bool {
|
||||
return commit.Sha == shas[0]
|
||||
return commit.Hash == hashes[0]
|
||||
})
|
||||
if !ok {
|
||||
commits := self.c.Model().Commits
|
||||
@@ -70,13 +72,13 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
|
||||
// If the commit is not found, it's most likely because it's already
|
||||
// merged, and more than 300 commits away. Check if the last known
|
||||
// commit is already merged; if so, show the "already merged" error.
|
||||
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
|
||||
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
|
||||
}
|
||||
// If we get here, the current branch must have more then 300 commits. Unlikely...
|
||||
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsNotInCurrentView)
|
||||
return errors.New(self.c.Tr.BaseCommitIsNotInCurrentView)
|
||||
}
|
||||
if commit.Status == models.StatusMerged {
|
||||
return self.c.ErrorMsg(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
|
||||
return errors.New(self.c.Tr.BaseCommitIsAlreadyOnMainBranch)
|
||||
}
|
||||
|
||||
doIt := func() error {
|
||||
@@ -164,7 +166,7 @@ func (self *FixupHelper) parseDiff(diff string) ([]*deletedLineInfo, bool) {
|
||||
// returns the list of commit hashes that introduced the lines which have now been deleted
|
||||
func (self *FixupHelper) blameDeletedLines(deletedLineInfos []*deletedLineInfo) []string {
|
||||
var wg sync.WaitGroup
|
||||
shaChan := make(chan string)
|
||||
hashChan := make(chan string)
|
||||
|
||||
for _, info := range deletedLineInfos {
|
||||
wg.Add(1)
|
||||
@@ -178,19 +180,19 @@ func (self *FixupHelper) blameDeletedLines(deletedLineInfos []*deletedLineInfo)
|
||||
}
|
||||
blameLines := strings.Split(strings.TrimSuffix(blameOutput, "\n"), "\n")
|
||||
for _, line := range blameLines {
|
||||
shaChan <- strings.Split(line, " ")[0]
|
||||
hashChan <- strings.Split(line, " ")[0]
|
||||
}
|
||||
}(info)
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(shaChan)
|
||||
close(hashChan)
|
||||
}()
|
||||
|
||||
result := set.New[string]()
|
||||
for sha := range shaChan {
|
||||
result.Add(sha)
|
||||
for hash := range hashChan {
|
||||
result.Add(hash)
|
||||
}
|
||||
|
||||
return result.ToSlice()
|
||||
|
||||
@@ -45,10 +45,8 @@ func (self *GpgHelper) runAndStream(cmdObj oscommands.ICmdObj, waitingStatus str
|
||||
return self.c.WithWaitingStatus(waitingStatus, func(gocui.Task) error {
|
||||
if err := cmdObj.StreamOutput().Run(); err != nil {
|
||||
_ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
return self.c.Error(
|
||||
fmt.Errorf(
|
||||
self.c.Tr.GitCommandFailed, self.c.UserConfig.Keybinding.Universal.ExtrasMenu,
|
||||
),
|
||||
return fmt.Errorf(
|
||||
self.c.Tr.GitCommandFailed, self.c.UserConfig.Keybinding.Universal.ExtrasMenu,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
type IHostHelper interface {
|
||||
GetPullRequestURL(from string, to string) (string, error)
|
||||
GetCommitURL(commitSha string) (string, error)
|
||||
GetCommitURL(commitHash string) (string, error)
|
||||
}
|
||||
|
||||
type HostHelper struct {
|
||||
@@ -31,12 +31,12 @@ func (self *HostHelper) GetPullRequestURL(from string, to string) (string, error
|
||||
return mgr.GetPullRequestURL(from, to)
|
||||
}
|
||||
|
||||
func (self *HostHelper) GetCommitURL(commitSha string) (string, error) {
|
||||
func (self *HostHelper) GetCommitURL(commitHash string) (string, error) {
|
||||
mgr, err := self.getHostingServiceMgr()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return mgr.GetCommitURL(commitSha)
|
||||
return mgr.GetCommitURL(commitHash)
|
||||
}
|
||||
|
||||
// getting this on every request rather than storing it in state in case our remoteURL changes
|
||||
|
||||
@@ -68,17 +68,11 @@ func (self *InlineStatusHelper) WithInlineStatus(opts InlineStatusOpts, f func(g
|
||||
view := context.GetView()
|
||||
visible := view.Visible && self.windowHelper.TopViewInWindow(context.GetWindowName(), false) == view
|
||||
if visible && context.IsItemVisible(opts.Item) {
|
||||
self.c.OnWorker(func(task gocui.Task) {
|
||||
self.c.OnWorker(func(task gocui.Task) error {
|
||||
self.start(opts)
|
||||
defer self.stop(opts)
|
||||
|
||||
err := f(inlineStatusHelperTask{task, self, opts})
|
||||
if err != nil {
|
||||
self.c.OnUIThread(func() error {
|
||||
return self.c.Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
self.stop(opts)
|
||||
return f(inlineStatusHelperTask{task, self, opts})
|
||||
})
|
||||
} else {
|
||||
message := presentation.ItemOperationToString(opts.Operation, self.c.Tr)
|
||||
@@ -105,7 +99,7 @@ func (self *InlineStatusHelper) start(opts InlineStatusOpts) {
|
||||
self.contextsWithInlineStatus[opts.ContextKey] = info
|
||||
|
||||
go utils.Safe(func() {
|
||||
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
|
||||
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
|
||||
defer ticker.Stop()
|
||||
outer:
|
||||
for {
|
||||
@@ -131,12 +125,28 @@ func (self *InlineStatusHelper) stop(opts InlineStatusOpts) {
|
||||
info.stop <- struct{}{}
|
||||
delete(self.contextsWithInlineStatus, opts.ContextKey)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self.mutex.Unlock()
|
||||
|
||||
self.c.State().ClearItemOperation(opts.Item)
|
||||
|
||||
// When recording a demo we need to re-render the context again here to
|
||||
// remove the inline status. In normal usage we don't want to do this
|
||||
// because in the case of pushing a branch this would first reveal the ↑3↓7
|
||||
// status from before the push for a brief moment, to be replaced by a green
|
||||
// checkmark a moment later when the async refresh is done. This looks
|
||||
// jarring, so normally we rely on the async refresh to redraw with the
|
||||
// status removed. (In some rare cases, where there's no refresh at all, we
|
||||
// need to redraw manually in the controller; see TagsController.push() for
|
||||
// an example.)
|
||||
//
|
||||
// In demos, however, we turn all async refreshes into sync ones, because
|
||||
// this looks better in demos. In this case the refresh happens while the
|
||||
// status is still set, so we need to render again after removing it.
|
||||
if self.c.InDemo() {
|
||||
self.renderContext(opts.ContextKey)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *InlineStatusHelper) renderContext(contextKey types.ContextKey) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -78,7 +79,7 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error {
|
||||
status := self.c.Git().Status.WorkingTreeState()
|
||||
|
||||
if status != enums.REBASE_MODE_MERGING && status != enums.REBASE_MODE_REBASING {
|
||||
return self.c.ErrorMsg(self.c.Tr.NotMergingOrRebasing)
|
||||
return errors.New(self.c.Tr.NotMergingOrRebasing)
|
||||
}
|
||||
|
||||
self.c.LogAction(fmt.Sprintf("Merge/Rebase: %s", command))
|
||||
@@ -169,9 +170,9 @@ func (self *MergeAndRebaseHelper) CheckForConflicts(result error) error {
|
||||
|
||||
if isMergeConflictErr(result.Error()) {
|
||||
return self.PromptForConflictHandling()
|
||||
} else {
|
||||
return self.c.ErrorMsg(result.Error())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *MergeAndRebaseHelper) PromptForConflictHandling() error {
|
||||
@@ -241,7 +242,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(task gocui.Task) error {
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetSha()
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetHash()
|
||||
var err error
|
||||
if baseCommit != "" {
|
||||
err = self.c.Git().Rebase.RebaseBranchFromBaseCommit(ref, baseCommit)
|
||||
@@ -262,7 +263,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
Tooltip: self.c.Tr.InteractiveRebaseTooltip,
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetSha()
|
||||
baseCommit := self.c.Modes().MarkedBaseCommit.GetHash()
|
||||
var err error
|
||||
if baseCommit != "" {
|
||||
err = self.c.Git().Rebase.EditRebaseFromBaseCommit(ref, baseCommit)
|
||||
@@ -281,7 +282,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
}
|
||||
|
||||
title := utils.ResolvePlaceholderString(
|
||||
lo.Ternary(self.c.Modes().MarkedBaseCommit.GetSha() != "",
|
||||
lo.Ternary(self.c.Modes().MarkedBaseCommit.GetHash() != "",
|
||||
self.c.Tr.RebasingFromBaseCommitTitle,
|
||||
self.c.Tr.RebasingTitle),
|
||||
map[string]string{
|
||||
@@ -298,11 +299,11 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
|
||||
func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) error {
|
||||
if self.c.Git().Branch.IsHeadDetached() {
|
||||
return self.c.ErrorMsg("Cannot merge branch in detached head state. You might have checked out a commit directly or a remote branch, in which case you should checkout the local branch you want to be on")
|
||||
return errors.New("Cannot merge branch in detached head state. You might have checked out a commit directly or a remote branch, in which case you should checkout the local branch you want to be on")
|
||||
}
|
||||
checkedOutBranchName := self.refsHelper.GetCheckedOutRef().Name
|
||||
if checkedOutBranchName == refName {
|
||||
return self.c.ErrorMsg(self.c.Tr.CantMergeBranchIntoItself)
|
||||
return errors.New(self.c.Tr.CantMergeBranchIntoItself)
|
||||
}
|
||||
prompt := utils.ResolvePlaceholderString(
|
||||
self.c.Tr.ConfirmMerge,
|
||||
|
||||
@@ -129,7 +129,7 @@ func (self *MergeConflictsHelper) RefreshMergeState() error {
|
||||
|
||||
hasConflicts, err := self.SetConflictsAndRender(self.c.Contexts().MergeConflicts.GetState().GetPath())
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !hasConflicts {
|
||||
|
||||
@@ -163,12 +163,26 @@ func (self *ModeHelper) ExitFilterMode() error {
|
||||
}
|
||||
|
||||
func (self *ModeHelper) ClearFiltering() error {
|
||||
selectedCommitHash := self.c.Contexts().LocalCommits.GetSelectedCommitHash()
|
||||
self.c.Modes().Filtering.Reset()
|
||||
if self.c.State().GetRepoState().GetScreenMode() == types.SCREEN_HALF {
|
||||
self.c.State().GetRepoState().SetScreenMode(types.SCREEN_NORMAL)
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}})
|
||||
return self.c.Refresh(types.RefreshOptions{
|
||||
Scope: []types.RefreshableView{types.COMMITS},
|
||||
Then: func() error {
|
||||
// Find the commit that was last selected in filtering mode, and select it again after refreshing
|
||||
if !self.c.Contexts().LocalCommits.SelectCommitByHash(selectedCommitHash) {
|
||||
// If we couldn't find it (either because no commit was selected
|
||||
// in filtering mode, or because the commit is outside the
|
||||
// initial 300 range), go back to the commit that was selected
|
||||
// before we entered filtering
|
||||
self.c.Contexts().LocalCommits.SelectCommitByHash(self.c.Modes().Filtering.GetSelectedCommitHash())
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *ModeHelper) SetSuppressRebasingMode(value bool) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@@ -24,7 +26,7 @@ func NewPatchBuildingHelper(
|
||||
|
||||
func (self *PatchBuildingHelper) ValidateNormalWorkingTreeState() (bool, error) {
|
||||
if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
|
||||
return false, self.c.ErrorMsg(self.c.Tr.CantPatchWhileRebasingError)
|
||||
return false, errors.New(self.c.Tr.CantPatchWhileRebasingError)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
||||
)
|
||||
}
|
||||
|
||||
f := func() {
|
||||
f := func() error {
|
||||
var scopeSet *set.Set[types.RefreshableView]
|
||||
if len(options.Scope) == 0 {
|
||||
// not refreshing staging/patch-building unless explicitly requested because we only need
|
||||
@@ -104,8 +104,9 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
||||
// everything happens fast and it's better to have everything update
|
||||
// in the one frame
|
||||
if !self.c.InDemo() && options.Mode == types.ASYNC {
|
||||
self.c.OnWorker(func(t gocui.Task) {
|
||||
self.c.OnWorker(func(t gocui.Task) error {
|
||||
f()
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
wg.Add(1)
|
||||
@@ -187,20 +188,22 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
||||
wg.Wait()
|
||||
|
||||
if options.Then != nil {
|
||||
options.Then()
|
||||
if err := options.Then(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if options.Mode == types.BLOCK_UI {
|
||||
self.c.OnUIThread(func() error {
|
||||
f()
|
||||
return nil
|
||||
return f()
|
||||
})
|
||||
} else {
|
||||
f()
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
return f()
|
||||
}
|
||||
|
||||
func getScopeNames(scopes []types.RefreshableView) []string {
|
||||
@@ -246,10 +249,11 @@ func getModeName(mode types.RefreshMode) string {
|
||||
func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() {
|
||||
switch self.c.State().GetRepoState().GetStartupStage() {
|
||||
case types.INITIAL:
|
||||
self.c.OnWorker(func(_ gocui.Task) {
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
_ = self.refreshReflogCommits()
|
||||
self.refreshBranches(false, true)
|
||||
self.c.State().GetRepoState().SetStartupStage(types.COMPLETE)
|
||||
return nil
|
||||
})
|
||||
|
||||
case types.COMPLETE:
|
||||
@@ -267,7 +271,7 @@ func (self *RefreshHelper) refreshCommitsAndCommitFiles() {
|
||||
_ = self.refreshCommitsWithLimit()
|
||||
ctx, ok := self.c.Contexts().CommitFiles.GetParentContext()
|
||||
if ok && ctx.GetKey() == context.LOCAL_COMMITS_CONTEXT_KEY {
|
||||
// This makes sense when we've e.g. just amended a commit, meaning we get a new commit SHA at the same position.
|
||||
// This makes sense when we've e.g. just amended a commit, meaning we get a new commit hash at the same position.
|
||||
// However if we've just added a brand new commit, it pushes the list down by one and so we would end up
|
||||
// showing the contents of a different commit than the one we initially entered.
|
||||
// Ideally we would know when to refresh the commit files context and when not to,
|
||||
@@ -290,16 +294,16 @@ func (self *RefreshHelper) determineCheckedOutBranchName() string {
|
||||
return strings.TrimPrefix(rebasedBranch, "refs/heads/")
|
||||
}
|
||||
|
||||
if bisectInfo := self.c.Git().Bisect.GetInfo(); bisectInfo.Bisecting() && bisectInfo.GetStartSha() != "" {
|
||||
if bisectInfo := self.c.Git().Bisect.GetInfo(); bisectInfo.Bisecting() && bisectInfo.GetStartHash() != "" {
|
||||
// Likewise, when we're bisecting we're on a detached head as well. In
|
||||
// this case we read the branch name from the ".git/BISECT_START" file.
|
||||
return bisectInfo.GetStartSha()
|
||||
return bisectInfo.GetStartHash()
|
||||
}
|
||||
|
||||
// In all other cases, get the branch name by asking git what branch is
|
||||
// checked out. Note that if we're on a detached head (for reasons other
|
||||
// than rebasing or bisecting, i.e. it was explicitly checked out), then
|
||||
// this will return its sha.
|
||||
// this will return its hash.
|
||||
if branchName, err := self.c.Git().Branch.CurrentBranchName(); err == nil {
|
||||
return branchName
|
||||
}
|
||||
@@ -381,7 +385,7 @@ func (self *RefreshHelper) refreshCommitFilesContext() error {
|
||||
|
||||
files, err := self.c.Git().Loaders.CommitFileLoader.GetFilesInDiff(from, to, reverse)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Model().CommitFiles = files
|
||||
self.c.Contexts().CommitFiles.CommitFileTreeViewModel.SetTree()
|
||||
@@ -406,7 +410,7 @@ func (self *RefreshHelper) refreshRebaseCommits() error {
|
||||
func (self *RefreshHelper) refreshTags() error {
|
||||
tags, err := self.c.Git().Loaders.TagLoader.GetTags()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Model().Tags = tags
|
||||
@@ -448,7 +452,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
|
||||
|
||||
branches, err := self.c.Git().Loaders.BranchLoader.Load(reflogCommits)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
self.c.Log.Error(err)
|
||||
}
|
||||
|
||||
self.c.Model().Branches = branches
|
||||
@@ -543,7 +547,7 @@ func (self *RefreshHelper) refreshStateFiles() error {
|
||||
if len(pathsToStage) > 0 {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageResolvedFiles)
|
||||
if err := self.c.Git().WorkingTree.StageFiles(pathsToStage); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,7 +607,7 @@ func (self *RefreshHelper) refreshReflogCommits() error {
|
||||
commits, onlyObtainedNewReflogCommits, err := self.c.Git().Loaders.ReflogCommitLoader.
|
||||
GetReflogCommits(lastReflogCommit, filterPath, filterAuthor)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if onlyObtainedNewReflogCommits {
|
||||
@@ -634,7 +638,7 @@ func (self *RefreshHelper) refreshRemotes() error {
|
||||
|
||||
remotes, err := self.c.Git().Loaders.RemoteLoader.GetRemotes()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Model().Remotes = remotes
|
||||
@@ -706,7 +710,7 @@ func (self *RefreshHelper) refreshStatus() {
|
||||
|
||||
repoName := self.c.Git().RepoPaths.RepoName()
|
||||
|
||||
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr)
|
||||
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr, self.c.UserConfig)
|
||||
|
||||
self.c.SetViewContent(self.c.Views().Status, status)
|
||||
}
|
||||
@@ -721,10 +725,10 @@ func (self *RefreshHelper) refForLog() string {
|
||||
|
||||
// need to see if our bisect's current commit is reachable from our 'new' ref.
|
||||
if bisectInfo.Bisecting() && !self.c.Git().Bisect.ReachableFromStart(bisectInfo) {
|
||||
return bisectInfo.GetNewSha()
|
||||
return bisectInfo.GetNewHash()
|
||||
}
|
||||
|
||||
return bisectInfo.GetStartSha()
|
||||
return bisectInfo.GetStartHash()
|
||||
}
|
||||
|
||||
func (self *RefreshHelper) refreshView(context types.Context) error {
|
||||
|
||||
@@ -69,10 +69,10 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
|
||||
Prompt: self.c.Tr.AutoStashPrompt,
|
||||
HandleConfirm: func() error {
|
||||
if err := self.c.Git().Stash.Push(self.c.Tr.StashPrefix + ref); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.c.Git().Branch.Checkout(ref, cmdOptions); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
onSuccess()
|
||||
@@ -80,16 +80,14 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions
|
||||
if err := self.c.Refresh(refreshOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(refreshOptions)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if err := self.c.Error(err); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
onSuccess()
|
||||
|
||||
@@ -142,7 +140,7 @@ func (self *RefsHelper) CheckoutRemoteBranch(fullBranchName string, localBranchN
|
||||
// "git checkout -b", but we want to benefit from all the
|
||||
// nice features of the CheckoutRef function.
|
||||
if err := self.c.Git().Branch.CreateWithUpstream(localBranchName, fullBranchName); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
// Do a sync refresh to make sure the new branch is visible,
|
||||
// so that we see an inline status when checking it out
|
||||
@@ -176,7 +174,7 @@ func (self *RefsHelper) GetCheckedOutRef() *models.Branch {
|
||||
|
||||
func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string) error {
|
||||
if err := self.c.Git().Commit.ResetToCommit(ref, strength, envVars); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.c.Contexts().LocalCommits.SetSelection(0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -62,8 +63,8 @@ func (self *ReposHelper) getCurrentBranch(path string) string {
|
||||
// is a branch
|
||||
branchDisplay = strings.TrimPrefix(content, refsPrefix)
|
||||
} else {
|
||||
// detached HEAD state, displaying short SHA
|
||||
branchDisplay = utils.ShortSha(content)
|
||||
// detached HEAD state, displaying short hash
|
||||
branchDisplay = utils.ShortHash(content)
|
||||
}
|
||||
return branchDisplay, nil
|
||||
}
|
||||
@@ -156,7 +157,7 @@ func (self *ReposHelper) DispatchSwitchTo(path string, errMsg string, contextKey
|
||||
|
||||
if err := os.Chdir(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return self.c.ErrorMsg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -39,7 +40,7 @@ func (self *SnakeHelper) renderSnakeGame(cells [][]snake.CellType, alive bool) {
|
||||
view := self.c.Views().Snake
|
||||
|
||||
if !alive {
|
||||
_ = self.c.ErrorMsg(self.c.Tr.YouDied)
|
||||
self.c.OnUIThread(func() error { return errors.New(self.c.Tr.YouDied) })
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error {
|
||||
if description != "" {
|
||||
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
|
||||
if err := self.c.Git().Tag.CreateAnnotated(tagName, ref, description, force); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag)
|
||||
if err := self.c.Git().Tag.CreateLightweight(tagName, ref, force); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/updates"
|
||||
@@ -41,10 +43,10 @@ func (self *UpdateHelper) CheckForUpdateInForeground() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.CheckingForUpdates, func(gocui.Task) error {
|
||||
self.updater.CheckForNewUpdate(func(newVersion string, err error) error {
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if newVersion == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.FailedToRetrieveLatestVersionErr)
|
||||
return errors.New(self.c.Tr.FailedToRetrieveLatestVersionErr)
|
||||
}
|
||||
return self.showUpdatePrompt(newVersion)
|
||||
}, true)
|
||||
@@ -71,7 +73,7 @@ func (self *UpdateHelper) onUpdateFinish(err error) error {
|
||||
"errMessage": err.Error(),
|
||||
},
|
||||
)
|
||||
return self.c.ErrorMsg(errMessage)
|
||||
return errors.New(errMessage)
|
||||
}
|
||||
return self.c.Alert(self.c.Tr.UpdateCompletedTitle, self.c.Tr.UpdateCompleted)
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
@@ -137,7 +138,7 @@ func (self *WorkingTreeHelper) HandleCommitEditorPress() error {
|
||||
func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
|
||||
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
|
||||
if skipHookPrefix == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||
return errors.New(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||
}
|
||||
|
||||
return self.HandleCommitPressWithMessage(skipHookPrefix)
|
||||
@@ -153,7 +154,7 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||
prefixReplace := commitPrefixConfig.Replace
|
||||
rgx, err := regexp.Compile(prefixPattern)
|
||||
if err != nil {
|
||||
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.CommitPrefixPatternError, err.Error()))
|
||||
return fmt.Errorf("%s: %s", self.c.Tr.CommitPrefixPatternError, err.Error())
|
||||
}
|
||||
prefix := rgx.ReplaceAllString(self.refHelper.GetCheckedOutRef().Name, prefixReplace)
|
||||
message = prefix
|
||||
@@ -165,11 +166,11 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||
|
||||
func (self *WorkingTreeHelper) WithEnsureCommitableFiles(handler func() error) error {
|
||||
if err := self.prepareFilesForCommit(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(self.c.Model().Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
return errors.New(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.AnyStagedFiles() {
|
||||
@@ -186,10 +187,10 @@ func (self *WorkingTreeHelper) promptToStageAllAndRetry(retry func() error) erro
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
|
||||
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if err := self.syncRefresh(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return retry()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
@@ -139,7 +140,7 @@ func (self *WorktreeHelper) NewWorktreeCheckout(base string, canCheckoutBase boo
|
||||
Title: self.c.Tr.NewBranchName,
|
||||
HandleConfirm: func(branchName string) error {
|
||||
if branchName == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.BranchNameCannotBeBlank)
|
||||
return errors.New(self.c.Tr.BranchNameCannotBeBlank)
|
||||
}
|
||||
|
||||
opts.Branch = branchName
|
||||
@@ -154,7 +155,7 @@ func (self *WorktreeHelper) NewWorktreeCheckout(base string, canCheckoutBase boo
|
||||
|
||||
func (self *WorktreeHelper) Switch(worktree *models.Worktree, contextKey types.ContextKey) error {
|
||||
if worktree.IsCurrent {
|
||||
return self.c.ErrorMsg(self.c.Tr.AlreadyInWorktree)
|
||||
return errors.New(self.c.Tr.AlreadyInWorktree)
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.SwitchToWorktree)
|
||||
@@ -186,13 +187,13 @@ func (self *WorktreeHelper) Remove(worktree *models.Worktree, force bool) error
|
||||
if err := self.c.Git().Worktree.Delete(worktree.Path, force); err != nil {
|
||||
errMessage := err.Error()
|
||||
if !strings.Contains(errMessage, "--force") {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !force {
|
||||
return self.Remove(worktree, true)
|
||||
}
|
||||
return self.c.ErrorMsg(errMessage)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
|
||||
})
|
||||
@@ -206,7 +207,7 @@ func (self *WorktreeHelper) Detach(worktree *models.Worktree) error {
|
||||
|
||||
err := self.c.Git().Worktree.Detach(worktree.Path)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.WORKTREES, types.BRANCHES, types.FILES}})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package controllers
|
||||
|
||||
import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
// Embed this into your list controller to get some convenience methods for
|
||||
// ensuring a single item is selected, etc.
|
||||
@@ -106,7 +110,7 @@ func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() erro
|
||||
var zeroValue T
|
||||
commit := self.getSelectedItem()
|
||||
if commit == zeroValue {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||
return errors.New(self.c.Tr.NoItemSelected)
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
@@ -117,7 +121,7 @@ func (self *ListControllerTrait[T]) withItems(callback func([]T) error) func() e
|
||||
return func() error {
|
||||
items, _, _ := self.getSelectedItems()
|
||||
if len(items) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||
return errors.New(self.c.Tr.NoItemSelected)
|
||||
}
|
||||
|
||||
return callback(items)
|
||||
@@ -129,7 +133,7 @@ func (self *ListControllerTrait[T]) withItemsRange(callback func([]T, int, int)
|
||||
return func() error {
|
||||
items, startIdx, endIdx := self.getSelectedItems()
|
||||
if len(items) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||
return errors.New(self.c.Tr.NoItemSelected)
|
||||
}
|
||||
|
||||
return callback(items, startIdx, endIdx)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stefanhaller/git-todo-parser/todo"
|
||||
)
|
||||
|
||||
// after selecting the 200th commit, we'll load in all the rest
|
||||
@@ -285,7 +285,7 @@ func (self *LocalCommitsController) GetOnRenderToMain() func() error {
|
||||
"ref": strings.TrimPrefix(commit.Name, "refs/heads/"),
|
||||
}))
|
||||
} else {
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Sha, self.c.Modes().Filtering.GetPath())
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath())
|
||||
task = types.NewRunPtyTask(cmdObj.GetCmd())
|
||||
}
|
||||
|
||||
@@ -350,9 +350,9 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
||||
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Sha)
|
||||
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
@@ -399,7 +399,7 @@ func (self *LocalCommitsController) switchFromCommitMessagePanelToEditor(filepat
|
||||
func (self *LocalCommitsController) handleReword(summary string, description string) error {
|
||||
err := self.c.Git().Rebase.RewordCommit(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), summary, description)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.c.Helpers().Commits.OnCommitSuccess()
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
@@ -416,7 +416,7 @@ func (self *LocalCommitsController) doRewordEditor() error {
|
||||
self.c.Model().Commits, self.context().GetSelectedLineIdx(),
|
||||
)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if subProcess != nil {
|
||||
return self.c.RunSubprocessAndRefresh(subProcess)
|
||||
@@ -457,9 +457,9 @@ func (self *LocalCommitsController) drop(selectedCommits []*models.Commit, start
|
||||
}
|
||||
|
||||
if selectedIdx > rangeStartIdx {
|
||||
selectedIdx = utils.Max(selectedIdx-len(updateRefTodos), rangeStartIdx)
|
||||
selectedIdx = max(selectedIdx-len(updateRefTodos), rangeStartIdx)
|
||||
} else {
|
||||
rangeStartIdx = utils.Max(rangeStartIdx-len(updateRefTodos), selectedIdx)
|
||||
rangeStartIdx = max(rangeStartIdx-len(updateRefTodos), selectedIdx)
|
||||
}
|
||||
|
||||
self.context().SetSelectionRangeAndMode(selectedIdx, rangeStartIdx, rangeSelectMode)
|
||||
@@ -495,7 +495,7 @@ func (self *LocalCommitsController) edit(selectedCommits []*models.Commit) error
|
||||
func (self *LocalCommitsController) quickStartInteractiveRebase() error {
|
||||
commitToEdit, err := self.findCommitForQuickStartInteractiveRebase()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.startInteractiveRebaseWithEdit([]*models.Commit{commitToEdit})
|
||||
@@ -508,23 +508,23 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
|
||||
self.c.LogAction(self.c.Tr.Actions.EditCommit)
|
||||
selectedIdx, rangeStartIdx, rangeSelectMode := self.context().GetSelectionRangeAndMode()
|
||||
commits := self.c.Model().Commits
|
||||
selectedSha := commits[selectedIdx].Sha
|
||||
rangeStartSha := commits[rangeStartIdx].Sha
|
||||
err := self.c.Git().Rebase.EditRebase(commitsToEdit[len(commitsToEdit)-1].Sha)
|
||||
selectedHash := commits[selectedIdx].Hash
|
||||
rangeStartHash := commits[rangeStartIdx].Hash
|
||||
err := self.c.Git().Rebase.EditRebase(commitsToEdit[len(commitsToEdit)-1].Hash)
|
||||
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebaseWithRefreshOptions(
|
||||
err,
|
||||
types.RefreshOptions{Mode: types.BLOCK_UI, Then: func() {
|
||||
types.RefreshOptions{Mode: types.BLOCK_UI, Then: func() error {
|
||||
todos := make([]*models.Commit, 0, len(commitsToEdit)-1)
|
||||
for _, c := range commitsToEdit[:len(commitsToEdit)-1] {
|
||||
// Merge commits can't be set to "edit", so just skip them
|
||||
if !c.IsMerge() {
|
||||
todos = append(todos, &models.Commit{Sha: c.Sha, Action: todo.Pick})
|
||||
todos = append(todos, &models.Commit{Hash: c.Hash, Action: todo.Pick})
|
||||
}
|
||||
}
|
||||
if len(todos) > 0 {
|
||||
err := self.updateTodos(todo.Edit, todos)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,14 +532,15 @@ func (self *LocalCommitsController) startInteractiveRebaseWithEdit(
|
||||
// new lines can be added for update-ref commands in the TODO file, due to
|
||||
// stacked branches. So the selected commits may be in different positions in the list.
|
||||
_, newSelectedIdx, ok1 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
|
||||
return c.Sha == selectedSha
|
||||
return c.Hash == selectedHash
|
||||
})
|
||||
_, newRangeStartIdx, ok2 := lo.FindIndexOf(self.c.Model().Commits, func(c *models.Commit) bool {
|
||||
return c.Sha == rangeStartSha
|
||||
return c.Hash == rangeStartHash
|
||||
})
|
||||
if ok1 && ok2 {
|
||||
self.context().SetSelectionRangeAndMode(newSelectedIdx, newRangeStartIdx, rangeSelectMode)
|
||||
}
|
||||
return nil
|
||||
}})
|
||||
})
|
||||
}
|
||||
@@ -587,7 +588,7 @@ func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand, s
|
||||
// begin a rebase. It then updates the todo file with that action
|
||||
func (self *LocalCommitsController) updateTodos(action todo.TodoCommand, selectedCommits []*models.Commit) error {
|
||||
if err := self.c.Git().Rebase.EditRebaseTodo(selectedCommits, action); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{
|
||||
@@ -620,7 +621,7 @@ func (self *LocalCommitsController) isRebasing() bool {
|
||||
func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, startIdx int, endIdx int) error {
|
||||
if self.isRebasing() {
|
||||
if err := self.c.Git().Rebase.MoveTodosDown(selectedCommits); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.context().MoveSelection(1)
|
||||
|
||||
@@ -643,7 +644,7 @@ func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, s
|
||||
func (self *LocalCommitsController) moveUp(selectedCommits []*models.Commit, startIdx int, endIdx int) error {
|
||||
if self.isRebasing() {
|
||||
if err := self.c.Git().Rebase.MoveTodosUp(selectedCommits); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
self.context().MoveSelection(-1)
|
||||
|
||||
@@ -733,7 +734,7 @@ func (self *LocalCommitsController) resetAuthor() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.ResetCommitAuthor)
|
||||
if err := self.c.Git().Rebase.ResetCommitAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx()); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
@@ -748,7 +749,7 @@ func (self *LocalCommitsController) setAuthor() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.SetCommitAuthor)
|
||||
if err := self.c.Git().Rebase.SetCommitAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx(), value); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
@@ -765,7 +766,7 @@ func (self *LocalCommitsController) addCoAuthor() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.AddCommitCoAuthor)
|
||||
if err := self.c.Git().Rebase.AddCommitCoAuthor(self.c.Model().Commits, self.context().GetSelectedLineIdx(), value); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||
})
|
||||
@@ -782,12 +783,12 @@ func (self *LocalCommitsController) revert(commit *models.Commit) error {
|
||||
Prompt: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.ConfirmRevertCommit,
|
||||
map[string]string{
|
||||
"selectedCommit": commit.ShortSha(),
|
||||
"selectedCommit": commit.ShortHash(),
|
||||
}),
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RevertCommit)
|
||||
return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error {
|
||||
if err := self.c.Git().Commit.Revert(commit.Sha); err != nil {
|
||||
if err := self.c.Git().Commit.Revert(commit.Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
return self.afterRevertCommit()
|
||||
@@ -799,20 +800,20 @@ func (self *LocalCommitsController) revert(commit *models.Commit) error {
|
||||
|
||||
func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.Commit) error {
|
||||
menuItems := make([]*types.MenuItem, len(commit.Parents))
|
||||
for i, parentSha := range commit.Parents {
|
||||
for i, parentHash := range commit.Parents {
|
||||
i := i
|
||||
message, err := self.c.Git().Commit.GetCommitMessageFirstLine(parentSha)
|
||||
message, err := self.c.Git().Commit.GetCommitMessageFirstLine(parentHash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
menuItems[i] = &types.MenuItem{
|
||||
Label: fmt.Sprintf("%s: %s", utils.SafeTruncate(parentSha, 8), message),
|
||||
Label: fmt.Sprintf("%s: %s", utils.SafeTruncate(parentHash, 8), message),
|
||||
OnPress: func() error {
|
||||
parentNumber := i + 1
|
||||
self.c.LogAction(self.c.Tr.Actions.RevertCommit)
|
||||
return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error {
|
||||
if err := self.c.Git().Commit.RevertMerge(commit.Sha, parentNumber); err != nil {
|
||||
if err := self.c.Git().Commit.RevertMerge(commit.Hash, parentNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
return self.afterRevertCommit()
|
||||
@@ -850,8 +851,8 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
|
||||
return self.c.Helpers().WorkingTree.WithEnsureCommitableFiles(func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CreateFixupCommit)
|
||||
return self.c.WithWaitingStatusSync(self.c.Tr.CreatingFixupCommitStatus, func() error {
|
||||
if err := self.c.Git().Commit.CreateFixupCommit(commit.Sha); err != nil {
|
||||
return self.c.Error(err)
|
||||
if err := self.c.Git().Commit.CreateFixupCommit(commit.Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.context().MoveSelectedLine(1)
|
||||
@@ -884,9 +885,9 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) createAmendCommit(commit *models.Commit, includeFileChanges bool) error {
|
||||
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Sha)
|
||||
commitMessage, err := self.c.Git().Commit.GetCommitMessage(commit.Hash)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
|
||||
@@ -903,7 +904,7 @@ func (self *LocalCommitsController) createAmendCommit(commit *models.Commit, inc
|
||||
self.c.LogAction(self.c.Tr.Actions.CreateFixupCommit)
|
||||
return self.c.WithWaitingStatusSync(self.c.Tr.CreatingFixupCommitStatus, func() error {
|
||||
if err := self.c.Git().Commit.CreateAmendCommit(originalSubject, summary, description, includeFileChanges); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
self.context().MoveSelectedLine(1)
|
||||
@@ -944,7 +945,7 @@ func (self *LocalCommitsController) squashAllFixupsAboveSelectedCommit(commit *m
|
||||
func (self *LocalCommitsController) squashAllFixupsInCurrentBranch() error {
|
||||
commit, rebaseStartIdx, err := self.findCommitForSquashFixupsInCurrentBranch()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.squashFixupsImpl(commit, rebaseStartIdx)
|
||||
@@ -1024,7 +1025,7 @@ func isFixupCommit(subject string) (string, bool) {
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) createTag(commit *models.Commit) error {
|
||||
return self.c.Helpers().Tags.OpenCreateTagPrompt(commit.Sha, func() {})
|
||||
return self.c.Helpers().Tags.OpenCreateTagPrompt(commit.Hash, func() {})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) openSearch() error {
|
||||
@@ -1153,10 +1154,8 @@ func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
context := self.context()
|
||||
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
|
||||
context.SetLimitCommits(false)
|
||||
self.c.OnWorker(func(_ gocui.Task) {
|
||||
if err := self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}}); err != nil {
|
||||
_ = self.c.Error(err)
|
||||
}
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1181,11 +1180,11 @@ func (self *LocalCommitsController) canPaste() *types.DisabledReason {
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) error {
|
||||
if commit.Sha == self.c.Modes().MarkedBaseCommit.GetSha() {
|
||||
if commit.Hash == self.c.Modes().MarkedBaseCommit.GetHash() {
|
||||
// Reset when invoking it again on the marked commit
|
||||
self.c.Modes().MarkedBaseCommit.SetSha("")
|
||||
self.c.Modes().MarkedBaseCommit.SetHash("")
|
||||
} else {
|
||||
self.c.Modes().MarkedBaseCommit.SetSha(commit.Sha)
|
||||
self.c.Modes().MarkedBaseCommit.SetHash(commit.Hash)
|
||||
}
|
||||
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ func (self *PatchExplorerController) CopySelectedToClipboard() error {
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.CopySelectedTextToClipboard)
|
||||
if err := self.c.OS().CopyToClipboard(selected); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -45,7 +45,7 @@ func (self *ReflogCommitsController) GetOnRenderToMain() func() error {
|
||||
if commit == nil {
|
||||
task = types.NewRenderStringTask("No reflog history")
|
||||
} else {
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Sha, self.c.Modes().Filtering.GetPath())
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath())
|
||||
|
||||
task = types.NewRunPtyTask(cmdObj.GetCmd())
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.Remot
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.SetBranchUpstream)
|
||||
if err := self.c.Git().Branch.SetUpstream(selectedBranch.RemoteName, selectedBranch.Name, checkedOutBranch.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||
|
||||
@@ -179,7 +179,7 @@ func (self *RemotesController) remove(remote *models.Remote) error {
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RemoveRemote)
|
||||
if err := self.c.Git().Remote.RemoveRemote(remote.Name); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||
@@ -202,7 +202,7 @@ func (self *RemotesController) edit(remote *models.Remote) error {
|
||||
if updatedRemoteName != remote.Name {
|
||||
self.c.LogAction(self.c.Tr.Actions.UpdateRemote)
|
||||
if err := self.c.Git().Remote.RenameRemote(remote.Name, updatedRemoteName); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ func (self *RemotesController) edit(remote *models.Remote) error {
|
||||
HandleConfirm: func(updatedRemoteUrl string) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.UpdateRemote)
|
||||
if err := self.c.Git().Remote.UpdateRemoteUrl(updatedRemoteName, updatedRemoteUrl); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||
},
|
||||
@@ -238,7 +238,7 @@ func (self *RemotesController) fetch(remote *models.Remote) error {
|
||||
return self.c.WithInlineStatus(remote, types.ItemOperationFetching, context.REMOTES_CONTEXT_KEY, func(task gocui.Task) error {
|
||||
err := self.c.Git().Sync.FetchRemote(task, remote.Name)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{
|
||||
|
||||
@@ -3,7 +3,6 @@ package controllers
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
// To be called after pressing up-arrow; checks whether the cursor entered the
|
||||
@@ -39,7 +38,7 @@ func calculateLinesToScrollUp(viewPortStart int, viewPortHeight int, scrollOffMa
|
||||
// a very large value to keep the cursor always in the middle of the screen.
|
||||
// Use +.5 so that if the height is even, the top margin is one line higher
|
||||
// than the bottom margin.
|
||||
scrollOffMargin = utils.Min(scrollOffMargin, int((float64(viewPortHeight)+.5)/2))
|
||||
scrollOffMargin = min(scrollOffMargin, int((float64(viewPortHeight)+.5)/2))
|
||||
|
||||
// Scroll only if the "before" position was visible (this could be false if
|
||||
// the scroll wheel was used to scroll the selected line out of view) ...
|
||||
@@ -59,7 +58,7 @@ func calculateLinesToScrollDown(viewPortStart int, viewPortHeight int, scrollOff
|
||||
// a very large value to keep the cursor always in the middle of the screen.
|
||||
// Use -.5 so that if the height is even, the bottom margin is one line lower
|
||||
// than the top margin.
|
||||
scrollOffMargin = utils.Min(scrollOffMargin, int((float64(viewPortHeight)-.5)/2))
|
||||
scrollOffMargin = min(scrollOffMargin, int((float64(viewPortHeight)-.5)/2))
|
||||
|
||||
// Scroll only if the "before" position was visible (this could be false if
|
||||
// the scroll wheel was used to scroll the selected line out of view) ...
|
||||
|
||||
@@ -244,7 +244,7 @@ func (self *StagingController) applySelection(reverse bool) error {
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if state.SelectingRange() {
|
||||
@@ -317,7 +317,7 @@ func (self *StagingController) editHunk() error {
|
||||
Cached: true,
|
||||
},
|
||||
); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -109,7 +109,7 @@ func (self *StashController) handleStashApply(stashEntry *models.StashEntry) err
|
||||
err := self.c.Git().Stash.Apply(stashEntry.Index)
|
||||
_ = self.postStashRefresh()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (self *StashController) handleStashPop(stashEntry *models.StashEntry) error
|
||||
err := self.c.Git().Stash.Pop(stashEntry.Index)
|
||||
_ = self.postStashRefresh()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (self *StashController) handleStashDrop(stashEntry *models.StashEntry) erro
|
||||
err := self.c.Git().Stash.Drop(stashEntry.Index)
|
||||
_ = self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}})
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -79,50 +79,19 @@ func (self *StatusController) GetMouseKeybindings(opts types.KeybindingsOpts) []
|
||||
}
|
||||
|
||||
func (self *StatusController) onClickMain(opts gocui.ViewMouseBindingOpts) error {
|
||||
view := self.c.Views().Main
|
||||
|
||||
cx, cy := view.Cursor()
|
||||
url, err := view.Word(cx, cy)
|
||||
if err == nil && strings.HasPrefix(url, "https://") {
|
||||
// Ignore errors (opening the link via the OS can fail if the
|
||||
// `os.openLink` config key references a command that doesn't exist, or
|
||||
// that errors when called.)
|
||||
_ = self.c.OS().OpenLink(url)
|
||||
}
|
||||
|
||||
return nil
|
||||
return self.c.HandleGenericClick(self.c.Views().Main)
|
||||
}
|
||||
|
||||
func (self *StatusController) GetOnRenderToMain() func() error {
|
||||
versionStr := "master"
|
||||
version, err := types.ParseVersionNumber(self.c.GetConfig().GetVersion())
|
||||
if err == nil {
|
||||
// Don't just take the version string as is, but format it again. This
|
||||
// way it will be correct even if a distribution omits the "v", or the
|
||||
// ".0" at the end.
|
||||
versionStr = fmt.Sprintf("v%d.%d.%d", version.Major, version.Minor, version.Patch)
|
||||
}
|
||||
config := self.c.UserConfig.Gui
|
||||
|
||||
return func() error {
|
||||
dashboardString := strings.Join(
|
||||
[]string{
|
||||
lazygitTitle(),
|
||||
"Copyright 2022 Jesse Duffield",
|
||||
fmt.Sprintf("Keybindings: %s", style.AttrUnderline.Sprint(fmt.Sprintf(constants.Links.Docs.Keybindings, versionStr))),
|
||||
fmt.Sprintf("Config Options: %s", style.AttrUnderline.Sprint(fmt.Sprintf(constants.Links.Docs.Config, versionStr))),
|
||||
fmt.Sprintf("Tutorial: %s", style.AttrUnderline.Sprint(constants.Links.Docs.Tutorial)),
|
||||
fmt.Sprintf("Raise an Issue: %s", style.AttrUnderline.Sprint(constants.Links.Issues)),
|
||||
fmt.Sprintf("Release Notes: %s", style.AttrUnderline.Sprint(constants.Links.Releases)),
|
||||
style.FgMagenta.Sprintf("Become a sponsor: %s", style.AttrUnderline.Sprint(constants.Links.Donate)), // caffeine ain't free
|
||||
}, "\n\n") + "\n"
|
||||
|
||||
return self.c.RenderToMainViews(types.RefreshMainOpts{
|
||||
Pair: self.c.MainViewPairs().Normal,
|
||||
Main: &types.ViewUpdateOpts{
|
||||
Title: self.c.Tr.StatusTitle,
|
||||
Task: types.NewRenderStringTask(dashboardString),
|
||||
},
|
||||
})
|
||||
switch config.StatusPanelView {
|
||||
case "dashboard":
|
||||
return self.showDashboard
|
||||
case "allBranchesLog":
|
||||
return self.showAllBranchLogs
|
||||
default:
|
||||
return self.showDashboard
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +116,7 @@ func (self *StatusController) onClick() error {
|
||||
}
|
||||
|
||||
cx, _ := self.c.Views().Status.Cursor()
|
||||
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now())
|
||||
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig)
|
||||
repoName := self.c.Git().RepoPaths.RepoName()
|
||||
workingTreeState := self.c.Git().Status.WorkingTreeState()
|
||||
switch workingTreeState {
|
||||
@@ -235,6 +204,37 @@ func (self *StatusController) showAllBranchLogs() error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *StatusController) showDashboard() error {
|
||||
versionStr := "master"
|
||||
version, err := types.ParseVersionNumber(self.c.GetConfig().GetVersion())
|
||||
if err == nil {
|
||||
// Don't just take the version string as is, but format it again. This
|
||||
// way it will be correct even if a distribution omits the "v", or the
|
||||
// ".0" at the end.
|
||||
versionStr = fmt.Sprintf("v%d.%d.%d", version.Major, version.Minor, version.Patch)
|
||||
}
|
||||
|
||||
dashboardString := strings.Join(
|
||||
[]string{
|
||||
lazygitTitle(),
|
||||
fmt.Sprintf("Copyright %d Jesse Duffield", time.Now().Year()),
|
||||
fmt.Sprintf("Keybindings: %s", style.AttrUnderline.Sprint(fmt.Sprintf(constants.Links.Docs.Keybindings, versionStr))),
|
||||
fmt.Sprintf("Config Options: %s", style.AttrUnderline.Sprint(fmt.Sprintf(constants.Links.Docs.Config, versionStr))),
|
||||
fmt.Sprintf("Tutorial: %s", style.AttrUnderline.Sprint(constants.Links.Docs.Tutorial)),
|
||||
fmt.Sprintf("Raise an Issue: %s", style.AttrUnderline.Sprint(constants.Links.Issues)),
|
||||
fmt.Sprintf("Release Notes: %s", style.AttrUnderline.Sprint(constants.Links.Releases)),
|
||||
style.FgMagenta.Sprintf("Become a sponsor: %s", style.AttrUnderline.Sprint(constants.Links.Donate)), // caffeine ain't free
|
||||
}, "\n\n") + "\n"
|
||||
|
||||
return self.c.RenderToMainViews(types.RefreshMainOpts{
|
||||
Pair: self.c.MainViewPairs().Normal,
|
||||
Main: &types.ViewUpdateOpts{
|
||||
Title: self.c.Tr.StatusTitle,
|
||||
Task: types.NewRenderStringTask(dashboardString),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *StatusController) handleCheckForUpdate() error {
|
||||
return self.c.Helpers().Update.CheckForUpdateInForeground()
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (self *SubCommitsController) GetOnRenderToMain() func() error {
|
||||
if commit == nil {
|
||||
task = types.NewRenderStringTask("No commits")
|
||||
} else {
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Sha, self.c.Modes().Filtering.GetPath())
|
||||
cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath())
|
||||
|
||||
task = types.NewRunPtyTask(cmdObj.GetCmd())
|
||||
}
|
||||
@@ -68,10 +68,8 @@ func (self *SubCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
context := self.context()
|
||||
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
|
||||
context.SetLimitCommits(false)
|
||||
self.c.OnWorker(func(_ gocui.Task) {
|
||||
if err := self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUB_COMMITS}}); err != nil {
|
||||
_ = self.c.Error(err)
|
||||
}
|
||||
self.c.OnWorker(func(_ gocui.Task) error {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUB_COMMITS}})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ func (self *SubmodulesController) add() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.AddSubmodule)
|
||||
err := self.c.Git().Submodule.Add(submoduleName, submodulePath, submoduleUrl)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -185,7 +185,7 @@ func (self *SubmodulesController) editURL(submodule *models.SubmoduleConfig) err
|
||||
self.c.LogAction(self.c.Tr.Actions.UpdateSubmoduleUrl)
|
||||
err := self.c.Git().Submodule.UpdateUrl(submodule, newUrl)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -199,7 +199,7 @@ func (self *SubmodulesController) init(submodule *models.SubmoduleConfig) error
|
||||
self.c.LogAction(self.c.Tr.Actions.InitialiseSubmodule)
|
||||
err := self.c.Git().Submodule.Init(submodule.Path)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -217,7 +217,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BulkInitialiseSubmodules)
|
||||
err := self.c.Git().Submodule.BulkInitCmdObj().Run()
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -231,7 +231,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RunningCommand, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BulkUpdateSubmodules)
|
||||
if err := self.c.Git().Submodule.BulkUpdateCmdObj().Run(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -245,7 +245,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.RunningCommand, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.BulkDeinitialiseSubmodules)
|
||||
if err := self.c.Git().Submodule.BulkDeinitCmdObj().Run(); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -262,7 +262,7 @@ func (self *SubmodulesController) update(submodule *models.SubmoduleConfig) erro
|
||||
self.c.LogAction(self.c.Tr.Actions.UpdateSubmodule)
|
||||
err := self.c.Git().Submodule.Update(submodule.Path)
|
||||
if err != nil {
|
||||
_ = self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES}})
|
||||
@@ -276,7 +276,7 @@ func (self *SubmodulesController) remove(submodule *models.SubmoduleConfig) erro
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RemoveSubmodule)
|
||||
if err := self.c.Git().Submodule.Delete(submodule); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.SUBMODULES, types.FILES}})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -101,7 +102,7 @@ func (self *SyncController) push(currentBranch *models.Branch) error {
|
||||
return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
|
||||
upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
|
||||
if err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.pushAux(currentBranch, pushOpts{
|
||||
@@ -121,7 +122,7 @@ func (self *SyncController) pull(currentBranch *models.Branch) error {
|
||||
if !currentBranch.IsTrackingRemote() {
|
||||
return self.c.Helpers().Upstream.PromptForUpstreamWithInitialContent(currentBranch, func(upstream string) error {
|
||||
if err := self.setCurrentBranchUpstream(upstream); err != nil {
|
||||
return self.c.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return self.PullAux(currentBranch, PullFilesOptions{Action: action})
|
||||
@@ -197,7 +198,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
|
||||
})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Updates were rejected") {
|
||||
return self.c.ErrorMsg(self.c.Tr.UpdatesRejected)
|
||||
return errors.New(self.c.Tr.UpdatesRejected)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -208,7 +209,7 @@ func (self *SyncController) pushAux(currentBranch *models.Branch, opts pushOpts)
|
||||
func (self *SyncController) requestToForcePush(currentBranch *models.Branch, opts pushOpts) error {
|
||||
forcePushDisabled := self.c.UserConfig.Git.DisableForcePushing
|
||||
if forcePushDisabled {
|
||||
return self.c.ErrorMsg(self.c.Tr.ForcePushDisabled)
|
||||
return errors.New(self.c.Tr.ForcePushDisabled)
|
||||
}
|
||||
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user