summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/uffizzi-build.yml89
-rw-r--r--.github/workflows/uffizzi-preview.yml84
-rw-r--r--README.md13
-rw-r--r--docs/Config.md7
-rw-r--r--pkg/commands/git_commands/branch.go22
-rw-r--r--pkg/commands/git_commands/branch_test.go22
-rw-r--r--pkg/commands/git_commands/commit.go7
-rw-r--r--pkg/commands/git_commands/commit_loader.go19
-rw-r--r--pkg/commands/git_commands/commit_loader_test.go25
-rw-r--r--pkg/commands/git_commands/commit_test.go73
-rw-r--r--pkg/commands/patch/patch_parser.go8
-rw-r--r--pkg/config/user_config.go76
-rw-r--r--pkg/gui/controllers/local_commits_controller.go52
-rw-r--r--pkg/i18n/chinese.go3
-rw-r--r--pkg/i18n/dutch.go3
-rw-r--r--pkg/i18n/english.go6
-rw-r--r--pkg/i18n/japanese.go3
-rw-r--r--pkg/i18n/korean.go3
-rw-r--r--pkg/i18n/polish.go2
-rw-r--r--pkg/integration/tests/branch/detached_head.go40
-rw-r--r--pkg/integration/tests/tests.go1
-rw-r--r--pkg/utils/template.go9
-rw-r--r--pkg/utils/template_test.go7
-rw-r--r--uffizzi/DockerfileTtyd17
-rw-r--r--uffizzi/docker-compose.uffizzi.yml20
25 files changed, 453 insertions, 158 deletions
diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml
new file mode 100644
index 000000000..58c7e5866
--- /dev/null
+++ b/.github/workflows/uffizzi-build.yml
@@ -0,0 +1,89 @@
+name: Build PR Image
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, closed]
+
+jobs:
+ build-application:
+ name: Build and Push `lazygit`
+ runs-on: ubuntu-latest
+ if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
+ outputs:
+ tags: ${{ steps.meta.outputs.tags }}
+ steps:
+ - name: Checkout git repo
+ uses: actions/checkout@v3
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+ - name: Generate UUID image name
+ id: uuid
+ run: echo "UUID_APP_TAG=$(uuidgen)" >> $GITHUB_ENV
+ - name: Docker metadata
+ id: meta
+ uses: docker/metadata-action@v3
+ with:
+ images: registry.uffizzi.com/${{ env.UUID_APP_TAG }}
+ tags: type=raw,value=60d
+ - name: Build and Push Image to registry.uffizzi.com ephemeral registry
+ uses: docker/build-push-action@v2
+ with:
+ push: true
+ context: ./
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ file: ./uffizzi/DockerfileTtyd
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+
+ render-compose-file:
+ name: Render Docker Compose File
+ # Pass output of this workflow to another triggered by `workflow_run` event.
+ runs-on: ubuntu-latest
+ needs:
+ - build-application
+ outputs:
+ compose-file-cache-key: ${{ steps.hash.outputs.hash }}
+ steps:
+ - name: Checkout git repo
+ uses: actions/checkout@v3
+ - name: Render Compose File
+ run: |
+ APP_IMAGE=$(echo ${{ needs.build-application.outputs.tags }})
+ export APP_IMAGE
+ # Render simple template from environment variables.
+ envsubst < ./uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml
+ cat docker-compose.rendered.yml
+ - name: Upload Rendered Compose File as Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: preview-spec
+ path: docker-compose.rendered.yml
+ retention-days: 2
+ - name: Serialize PR Event to File
+ run: |
+ cat << EOF > event.json
+ ${{ toJSON(github.event) }}
+
+ EOF
+ - name: Upload PR Event as Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: preview-spec
+ path: event.json
+ retention-days: 2
+
+ delete-preview:
+ name: Call for Preview Deletion
+ runs-on: ubuntu-latest
+ if: ${{ github.event.action == 'closed' }}
+ steps:
+ # If this PR is closing, we will not render a compose file nor pass it to the next workflow.
+ - name: Serialize PR Event to File
+ run: echo '${{ toJSON(github.event) }}' > event.json
+ - name: Upload PR Event as Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: preview-spec
+ path: event.json
+ retention-days: 2
diff --git a/.github/workflows/uffizzi-preview.yml b/.github/workflows/uffizzi-preview.yml
new file mode 100644
index 000000000..ce8a9c46f
--- /dev/null
+++ b/.github/workflows/uffizzi-preview.yml
@@ -0,0 +1,84 @@
+name: Deploy Uffizzi Preview
+
+on:
+ workflow_run:
+ workflows:
+ - "Build PR Image"
+ types:
+ - completed
+
+
+jobs:
+ cache-compose-file:
+ name: Cache Compose File
+ runs-on: ubuntu-latest
+ outputs:
+ compose-file-cache-key: ${{ env.COMPOSE_FILE_HASH }}
+ pr-number: ${{ env.PR_NUMBER }}
+ steps:
+ - name: 'Download artifacts'
+ # Fetch output (zip archive) from the workflow run that triggered this workflow.
+ uses: actions/github-script@v6
+ with:
+ script: |
+ let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.payload.workflow_run.id,
+ });
+ let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
+ return artifact.name == "preview-spec"
+ })[0];
+ let download = await github.rest.actions.downloadArtifact({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: matchArtifact.id,
+ archive_format: 'zip',
+ });
+ let fs = require('fs');
+ fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
+ - name: 'Unzip artifact'
+ run: unzip preview-spec.zip
+ - name: Read Event into ENV
+ run: |
+ echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
+ cat event.json >> $GITHUB_ENV
+ echo 'EOF' >> $GITHUB_ENV
+ - name: Hash Rendered Compose File
+ id: hash
+ # If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
+ if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
+ run: echo "COMPOSE_FILE_HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
+ - name: Cache Rendered Compose File
+ if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
+ uses: actions/cache@v3
+ with:
+ path: docker-compose.rendered.yml
+ key: ${{ env.COMPOSE_FILE_HASH }}
+
+ - name: Read PR Number From Event Object
+ id: pr
+ run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
+
+ - name: DEBUG - Print Job Outputs
+ if: ${{ runner.debug }}
+ run: |
+ echo "PR number: ${{ env.PR_NUMBER }}"
+ echo "Compose file hash: ${{ env.COMPOSE_FILE_HASH }}"
+ cat event.json
+ deploy-uffizzi-preview:
+ name: Use Remote Workflow to Preview on Uffizzi
+ needs:
+ - cache-compose-file
+ uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2.6.1
+ with:
+ # If this workflow was triggered by a PR close event, cache-key will be an empty string
+ # and this reusable workflow will delete the preview deployment.
+ compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
+ compose-file-cache-path: docker-compose.rendered.yml
+ server: https://app.uffizzi.com
+ pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
+ permissions:
+ contents: read
+ pull-requests: write
+ id-token: write \ No newline at end of file
diff --git a/README.md b/README.md
index 2dbfdbaed..cdb06fbad 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ A simple terminal UI for git commands, written in Go with the [gocui](https://gi
</p>
<p align="center">
-<!-- sponsors --><a href="https://github.com/atecce"><img src="https://github.com/atecce.png" width="60px" alt="" /></a><a href="https://github.com/intabulas"><img src="https://github.com/intabulas.png" width="60px" alt="" /></a><a href="https://github.com/peppy"><img src="https://github.com/peppy.png" width="60px" alt="" /></a><a href="https://github.com/piot"><img src="https://github.com/piot.png" width="60px" alt="" /></a><a href="https://github.com/blacky14"><img src="https://github.com/blacky14.png" width="60px" alt="" /></a><a href="https://github.com/rgwood"><img src="https://github.com/rgwood.png" width="60px" alt="" /></a><a href="https://github.com/oliverguenther"><img src="https://github.com/oliverguenther.png" width="60px" alt="" /></a><a href="https://github.com/pawanjay176"><img src="https://github.com/pawanjay176.png" width="60px" alt="" /></a><a href="https://github.com/bdach"><img src="https://github.com/bdach.png" width="60px" alt="" /></a><a href="https://github.com/naoey"><img src="https://github.com/naoey.png" width="60px" alt="" /></a><a href="https://github.com/jryom"><img src="https://github.com/jryom.png" width="60px" alt="" /></a><a href="https://github.com/carstengehling"><img src="https://github.com/carstengehling.png" width="60px" alt="" /></a><a href="https://github.com/ceuk"><img src="https://github.com/ceuk.png" width="60px" alt="" /></a><a href="https://github.com/akospwc"><img src="https://github.com/akospwc.png" width="60px" alt="" /></a><a href="https://github.com/Xetera"><img src="https://github.com/Xetera.png" width="60px" alt="" /></a><a href="https://github.com/HoldenLucas"><img src="https://github.com/HoldenLucas.png" width="60px" alt="" /></a><a href="https://github.com/barbados-clemens"><img src="https://github.com/barbados-clemens.png" width="60px" alt="" /></a><a href="https://github.com/nartc"><img src="https://github.com/nartc.png" width="60px" alt="" /></a><a href="https://github.com/"><img src="https://github.com/.png" width="60px" alt="" /></a><a href="https://github.com/matejcik"><img src="https://github.com/matejcik.png" width="60px" alt="" /></a><a href="https://github.com/lucatume"><img src="https://github.com/lucatume.png" width="60px" alt="" /></a><a href="https://github.com/dbabiak"><img src="https://github.com/dbabiak.png" width="60px" alt="" /></a><a href="https://github.com/davidlattimore"><img src="https://github.com/davidlattimore.png" width="60px" alt="" /></a><a href="https://github.com/zach-fuller"><img src="https://github.com/zach-fuller.png" width="60px" alt="" /></a><a href="https://github.com/escrafford"><img src="https://github.com/escrafford.png" width="60px" alt="" /></a><a href="https://github.com/davdroman"><img src="https://github.com/davdroman.png" width="60px" alt="" /></a><a href="https://github.com/KowalskiPiotr98"><img src="https://github.com/KowalskiPiotr98.png" width="60px" alt="" /></a><a href="https://github.com/IvanZuy"><img src="https://github.com/IvanZuy.png" width="60px" alt="" /></a><a href="https://github.com/nicholascloud"><img src="https://github.com/nicholascloud.png" width="60px" alt="" /></a><a href="https://github.com/topher200"><img src="https://github.com/topher200.png" width="60px" alt="" /></a><a href="https://github.com/PhotonQuantum"><img src="https://github.com/PhotonQuantum.png" width="60px" alt="" /></a><a href="https://github.com/GitSquared"><img src="https://github.com/GitSquared.png" width="60px" alt="" /></a><a href="https://github.com/ava1ar"><img src="https://github.com/ava1ar.png" width="60px" alt="" /></a><a href="https://github.com/alqh"><img src="https://github.com/alqh.png" width="60px" alt="" /></a><a href="https://github.com/pedropombeiro"><img src="https://github.com/pedropombeiro.png" width="60px" alt="" /></a><a href="https://github.com/minidfx"><img src="https://github.com/minidfx.png" width="60px" alt="" /></a><a href="https://github.com/JoeKlemmer"><img src="https://github.com/JoeKlemmer.png" width="60px" alt="" /></a><a href="https://github.com/MikaelElkiaer"><img src="https://github.com/MikaelElkiaer.png" width="60px" alt="" /></a><a href="https://github.com/smoogipoo"><img src="https://github.com/smoogipoo.png" width="60px" alt="" /></a><a href="https://github.com/ColonelBucket8"><img src="https://github.com/ColonelBucket8.png" width="60px" alt="" /></a><a href="https://github.com/mutewinter"><img src="https://github.com/mutewinter.png" width="60px" alt="" /></a><a href="https://github.com/tobi"><img src="https://github.com/tobi.png" width="60px" alt="" /></a><a href="https://github.com/benmacleod"><img src="https://github.com/benmacleod.png" width="60px" alt="" /></a><a href="https://github.com/benbfortis"><img src="https://github.com/benbfortis.png" width="60px" alt="" /></a><a href="https://github.com/jakewarren"><img src="https://github.com/jakewarren.png" width="60px" alt="" /></a><a href="https://github.com/huettern"><img src="https://github.com/huettern.png" width="60px" alt="" /></a><a href="https://github.com/tgpholly"><img src="https://github.com/tgpholly.png" width="60px" alt="" /></a><a href="https://github.com/Fuzznimp"><img src="https://github.com/Fuzznimp.png" width="60px" alt="" /></a><a href="https://github.com/crab-apple"><img src="https://github.com/crab-apple.png" width="60px" alt="" /></a><a href="https://github.com/Tommylans"><img src="https://github.com/Tommylans.png" width="60px" alt="" /></a><a href="https://github.com/jacktrusler"><img src="https://github.com/jacktrusler.png" width="60px" alt="" /></a><a href="https://github.com/pablosproject"><img src="https://github.com/pablosproject.png" width="60px" alt="" /></a><a href="https://github.com/jisantuc"><img src="https://github.com/jisantuc.png" width="60px" alt="" /></a><a href="https://github.com/kahgeh"><img src="https://github.com/kahgeh.png" width="60px" alt="" /></a><a href="https://github.com/broneks"><img src="https://github.com/broneks.png" width="60px" alt="" /></a><a href="https://github.com/zabil"><img src="https://github.com/zabil.png" width="60px" alt="" /></a><a href="https://github.com/naoric"><img src="https://github.com/naoric.png" width="60px" alt="" /></a><a href="https://github.com/GianniBYoung"><img src="https://github.com/GianniBYoung.png" width="60px" alt="" /></a><a href="https://github.com/kannapoix"><img src="https://github.com/kannapoix.png" width="60px" alt="" /></a><a href="https://github.com/jliendo"><img src="https://github.com/jliendo.png" width="60px" alt="" /></a><a href="https://github.com/bitprophet"><img src="https://github.com/bitprophet.png" width="60px" alt="" /></a><!-- sponsors -->
+<!-- sponsors --><a href="https://github.com/atecce"><img src="https://github.com/atecce.png" width="60px" alt="" /></a><a href="https://github.com/intabulas"><img src="https://github.com/intabulas.png" width="60px" alt="" /></a><a href="https://github.com/peppy"><img src="https://github.com/peppy.png" width="60px" alt="" /></a><a href="https://github.com/piot"><img src="https://github.com/piot.png" width="60px" alt="" /></a><a href="https://github.com/blacky14"><img src="https://github.com/blacky14.png" width="60px" alt="" /></a><a href="https://github.com/rgwood"><img src="https://github.com/rgwood.png" width="60px" alt="" /></a><a href="https://github.com/oliverguenther"><img src="https://github.com/oliverguenther.png" width="60px" alt="" /></a><a href="https://github.com/pawanjay176"><img src="https://github.com/pawanjay176.png" width="60px" alt="" /></a><a href="https://github.com/bdach"><img src="https://github.com/bdach.png" width="60px" alt="" /></a><a href="https://github.com/naoey"><img src="https://github.com/naoey.png" width="60px" alt="" /></a><a href="https://github.com/jryom"><img src="https://github.com/jryom.png" width="60px" alt="" /></a><a href="https://github.com/carstengehling"><img src="https://github.com/carstengehling.png" width="60px" alt="" /></a><a href="https://github.com/ceuk"><img src="https://github.com/ceuk.png" width="60px" alt="" /></a><a href="https://github.com/akospwc"><img src="https://github.com/akospwc.png" width="60px" alt="" /></a><a href="https://github.com/Xetera"><img src="https://github.com/Xetera.png" width="60px" alt="" /></a><a href="https://github.com/HoldenLucas"><img src="https://github.com/HoldenLucas.png" width="60px" alt="" /></a><a href="https://github.com/barbados-clemens"><img src="https://github.com/barbados-clemens.png" width="60px" alt="" /></a><a href="https://github.com/nartc"><img src="https://github.com/nartc.png" width="60px" alt="" /></a><a href="https://github.com/"><img src="https://github.com/.png" width="60px" alt="" /></a><a href="https://github.com/matejcik"><img src="https://github.com/matejcik.png" width="60px" alt="" /></a><a href="https://github.com/lucatume"><img src="https://github.com/lucatume.png" width="60px" alt="" /></a><a href="https://github.com/dbabiak"><img src="https://github.com/dbabiak.png" width="60px" alt="" /></a><a href="https://github.com/davidlattimore"><img src="https://github.com/davidlattimore.png" width="60px" alt="" /></a><a href="https://github.com/zach-fuller"><img src="https://github.com/zach-fuller.png" width="60px" alt="" /></a><a href="https://github.com/escrafford"><img src="https://github.com/escrafford.png" width="60px" alt="" /></a><a href="https://github.com/davdroman"><img src="https://github.com/davdroman.png" width="60px" alt="" /></a><a href="https://github.com/KowalskiPiotr98"><img src="https://github.com/KowalskiPiotr98.png" width="60px" alt="" /></a><a href="https://github.com/IvanZuy"><img src="https://github.com/IvanZuy.png" width="60px" alt="" /></a><a href="https://github.com/nicholascloud"><img src="https://github.com/nicholascloud.png" width="60px" alt="" /></a><a href="https://github.com/topher200"><img src="https://github.com/topher200.png" width="60px" alt="" /></a><a href="https://github.com/PhotonQuantum"><img src="https://github.com/PhotonQuantum.png" width="60px" alt="" /></a><a href="https://github.com/GitSquared"><img src="https://github.com/GitSquared.png" width="60px" alt="" /></a><a href="https://github.com/ava1ar"><img src="https://github.com/ava1ar.png" width="60px" alt="" /></a><a href="https://github.com/alqh"><img src="https://github.com/alqh.png" width="60px" alt="" /></a><a href="https://github.com/pedropombeiro"><img src="https://github.com/pedropombeiro.png" width="60px" alt="" /></a><a href="https://github.com/minidfx"><img src="https://github.com/minidfx.png" width="60px" alt="" /></a><a href="https://github.com/JoeKlemmer"><img src="https://github.com/JoeKlemmer.png" width="60px" alt="" /></a><a href="https://github.com/MikaelElkiaer"><img src="https://github.com/MikaelElkiaer.png" width="60px" alt="" /></a><a href="https://github.com/smoogipoo"><img src="https://github.com/smoogipoo.png" width="60px" alt="" /></a><a href="https://github.com/ColonelBucket8"><img src="https://github.com/ColonelBucket8.png" width="60px" alt="" /></a><a href="https://github.com/mutewinter"><img src="https://github.com/mutewinter.png" width="60px" alt="" /></a><a href="https://github.com/tobi"><img src="https://github.com/tobi.png" width="60px" alt="" /></a><a href="https://github.com/benmacleod"><img src="https://github.com/benmacleod.png" width="60px" alt="" /></a><a href="https://github.com/benbfortis"><img src="https://github.com/benbfortis.png" width="60px" alt="" /></a><a href="https://github.com/jakewarren"><img src="https://github.com/jakewarren.png" width="60px" alt="" /></a><a href="https://github.com/huettern"><img src="https://github.com/huettern.png" width="60px" alt="" /></a><a href="https://github.com/tgpholly"><img src="https://github.com/tgpholly.png" width="60px" alt="" /></a><a href="https://github.com/Fuzznimp"><img src="https://github.com/Fuzznimp.png" width="60px" alt="" /></a><a href="https://github.com/crab-apple"><img src="https://github.com/crab-apple.png" width="60px" alt="" /></a><a href="https://github.com/Tommylans"><img src="https://github.com/Tommylans.png" width="60px" alt="" /></a><a href="https://github.com/jacktrusler"><img src="https://github.com/jacktrusler.png" width="60px" alt="" /></a><a href="https://github.com/pablosproject"><img src="https://github.com/pablosproject.png" width="60px" alt="" /></a><a href="https://github.com/jisantuc"><img src="https://github.com/jisantuc.png" width="60px" alt="" /></a><a href="https://github.com/zabil"><img src="https://github.com/zabil.png" width="60px" alt="" /></a><a href="https://github.com/kannapoix"><img src="https://github.com/kannapoix.png" width="60px" alt="" /></a><a href="https://github.com/jliendo"><img src="https://github.com/jliendo.png" width="60px" alt="" /></a><a href="https://github.com/bitprophet"><img src="https://github.com/bitprophet.png" width="60px" alt="" /></a><a href="https://github.com/kohane27"><img src="https://github.com/kohane27.png" width="60px" alt="" /></a><a href="https://github.com/cschmatzler"><img src="https://github.com/cschmatzler.png" width="60px" alt="" /></a><a href="https://github.com/viktorburian"><img src="https://github.com/viktorburian.png" width="60px" alt="" /></a><a href="https://github.com/the-shank"><img src="https://github.com/the-shank.png" width="60px" alt="" /></a><a href="https://github.com/tayleighr"><img src="https://github.com/tayleighr.png" width="60px" alt="" /></a><!-- sponsors -->
</p>
## Elevator Pitch
@@ -150,15 +150,10 @@ sudo eopkg install lazygit
### Ubuntu
```sh
-LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v*([^"]+)".*/\1/')
-```
-
-```sh
+LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz"
-```
-
-```sh
-sudo tar xf lazygit.tar.gz -C /usr/local/bin lazygit
+tar xf lazygit.tar.gz lazygit
+sudo install lazygit /usr/local/bin
```
Verify the correct installation of lazygit:
diff --git a/docs/Config.md b/docs/Config.md
index 4bcac2064..6a9be62e9 100644
--- a/docs/Config.md
+++ b/docs/Config.md
@@ -62,20 +62,21 @@ gui:
showIcons: false
commandLogSize: 8
splitDiff: 'auto' # one of 'auto' | 'always'
+ skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
git:
paging:
colorArg: always
useConfig: false
commit:
signOff: false
- verbose: false
+ verbose: default # one of 'default' | 'always' | 'never'
merging:
# only applicable to unix users
manualCommit: false
# extra args passed to `git merge`, e.g. --no-ff
args: ''
log:
- # one of date-order, author-date-order, topo-order.
+ # one of date-order, author-date-order, topo-order or default.
# topo-order makes it easier to read the git log graph, but commits may not
# appear chronologically. See https://git-scm.com/docs/git-log#_commit_ordering
order: 'topo-order'
@@ -190,6 +191,8 @@ keybinding:
viewResetOptions: 'D'
fetch: 'f'
toggleTreeView: '`'
+ openMergeTool: 'M'
+ openStatusFilter: '<c-b>'
branches:
createPullRequest: 'o'
viewPullRequestOptions: 'O'
diff --git a/pkg/commands/git_commands/branch.go b/pkg/commands/git_commands/branch.go
index 117427778..a71e365ea 100644
--- a/pkg/commands/git_commands/branch.go
+++ b/pkg/commands/git_commands/branch.go
@@ -2,19 +2,12 @@ package git_commands
import (
"fmt"
- "regexp"
"strings"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
-// this takes something like:
-// * (HEAD detached at 264fc6f5)
-// remotes
-// and returns '264fc6f5' as the second match
-const CurrentBranchNameRegex = `(?m)^\*.*?([^ ]*?)\)?$`
-
type BranchCommands struct {
*GitCommon
}
@@ -41,19 +34,18 @@ func (self *BranchCommands) CurrentBranchInfo() (BranchInfo, error) {
DetachedHead: false,
}, nil
}
- output, err := self.cmd.New("git branch --contains").DontLog().RunWithOutput()
+ output, err := self.cmd.New(`git branch --points-at=HEAD --format="%(HEAD)%00%(objectname)%00%(refname)"`).DontLog().RunWithOutput()
if err != nil {
return BranchInfo{}, err
}
for _, line := range utils.SplitLines(output) {
- re := regexp.MustCompile(CurrentBranchNameRegex)
- match := re.FindStringSubmatch(line)
- if len(match) > 0 {
- branchName = match[1]
- displayBranchName := match[0][2:]
+ split := strings.Split(strings.TrimRight(line, "\r\n"), "\x00")
+ if len(split) == 3 && split[0] == "*" {
+ sha := split[1]
+ displayName := split[2]
return BranchInfo{
- RefName: branchName,
- DisplayName: displayBranchName,
+ RefName: sha,
+ DisplayName: displayName,
DetachedHead: true,
}, nil
}
diff --git a/pkg/commands/git_commands/branch_test.go b/pkg/commands/git_commands/branch_test.go
index 94456c0f8..2fdf7d9c2 100644
--- a/pkg/commands/git_commands/branch_test.go
+++ b/pkg/commands/git_commands/branch_test.go
@@ -181,26 +181,30 @@ func TestBranchCurrentBranchInfo(t *testing.T) {
},
},
{
- "falls back to git `git branch --contains` if symbolic-ref fails",
+ "falls back to git `git branch --points-at=HEAD` if symbolic-ref fails",
oscommands.NewFakeRunner(t).
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
- Expect(`git branch --contains`, "* (HEAD detached at 8982166a)", nil),
+ Expect(`git branch --points-at=HEAD --format="%(HEAD)%00%(objectname)%00%(refname)"`, "*\x006f71c57a8d4bd6c11399c3f55f42c815527a73a4\x00(HEAD detached at 6f71c57a)\n", nil),
func(info BranchInfo, err error) {
assert.NoError(t, err)
- assert.EqualValues(t, "8982166a", info.RefName)
- assert.EqualValues(t, "(HEAD detached at 8982166a)", info.DisplayName)
+ assert.EqualValues(t, "6f71c57a8d4bd6c11399c3f55f42c815527a73a4", info.RefName)
+ assert.EqualValues(t, "(HEAD detached at 6f71c57a)", info.DisplayName)
assert.True(t, info.DetachedHead)
},
},
{
- "handles a detached head",
+ "handles a detached head (LANG=zh_CN.UTF-8)",
oscommands.NewFakeRunner(t).
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
- Expect(`git branch --contains`, "* (HEAD detached at 123abcd)", nil),
+ Expect(
+ `git branch --points-at=HEAD --format="%(HEAD)%00%(objectname)%00%(refname)"`,
+ "*\x00679b0456f3db7c505b398def84e7d023e5b55a8d\x00(头指针在 679b0456 分离)\n"+
+ " \x00679b0456f3db7c505b398def84e7d023e5b55a8d\x00refs/heads/master\n",
+ nil),
func(info BranchInfo, err error) {
assert.NoError(t, err)
- assert.EqualValues(t, "123abcd", info.RefName)
- assert.EqualValues(t, "(HEAD detached at 123abcd)", info.DisplayName)
+ assert.EqualValues(t, "679b0456f3db7c505b398def84e7d023e5b55a8d", info.RefName)
+ assert.EqualValues(t, "(头指针在 679b0456 分离)", info.DisplayName)
assert.True(t, info.DetachedHead)
},
},
@@ -208,7 +212,7 @@ func TestBranchCurrentBranchInfo(t *testing.T) {
"bubbles up error if there is one",
oscommands.NewFakeRunner(t).
Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")).
- Expect(`git branch --contains`, "", errors.New("error")),
+ Expect(`git branch --points-at=HEAD --format="%(HEAD)%00%(objectname)%00%(refname)"`, "", errors.New("error")),
func(info BranchInfo, err error) {
assert.Error(t, err)
assert.EqualValues(t, "", info.RefName)
diff --git a/pkg/commands/git_commands/commit.go b/pkg/commands/git_commands/commit.go
index be06cb245..b5293a2ff 100644
--- a/pkg/commands/git_commands/commit.go
+++ b/pkg/commands/git_commands/commit.go
@@ -74,9 +74,12 @@ func (self *CommitCommands) signoffFlag() string {
}
func (self *CommitCommands) verboseFlag() string {
- if self.UserConfig.Git.Commit.Verbose {
+ switch self.config.UserConfig.Git.Commit.Verbose {
+ case "always":
return " --verbose"
- } else {
+ case "never":
+ return " --no-verbose"
+ default:
return ""
}
}
diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go
index f89f62c48..00e2f80ad 100644
--- a/pkg/commands/git_commands/commit_loader.go
+++ b/pkg/commands/git_commands/commit_loader.go
@@ -426,7 +426,10 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
config := self.UserConfig.Git.Log
- orderFlag := "--" + config.Order
+ orderFlag := ""
+ if config.Order != "default" {
+ orderFlag = " --" + config.Order
+ }
allFlag := ""
if opts.All {
allFlag = " --all"
@@ -434,7 +437,7 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
return self.cmd.New(
fmt.Sprintf(
- "git -c log.showSignature=false log %s %s %s --oneline %s%s --abbrev=%d%s",
+ "git -c log.showSignature=false log %s%s%s --oneline %s%s --abbrev=%d%s",
self.cmd.Quote(opts.RefName),
orderFlag,
allFlag,
@@ -446,14 +449,4 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
).DontLog()
}
-var prettyFormat = fmt.Sprintf(
- "--pretty=format:\"%%H%s%%at%s%%aN%s%%ae%s%%d%s%%p%s%%s\"",
- NULL_CODE,
- NULL_CODE,
- NULL_CODE,
- NULL_CODE,
- NULL_CODE,
- NULL_CODE,
-)
-
-const NULL_CODE = "%x00"
+const prettyFormat = `--pretty=format:"%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s"`
diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go
index ab6d5a105..aa20ae802 100644
--- a/pkg/commands/git_commands/commit_loader_test.go
+++ b/pkg/commands/git_commands/commit_loader_test.go
@@ -27,6 +27,7 @@ func TestGetCommits(t *testing.T) {
runner *oscommands.FakeCmdObjRunner
expectedCommits []*models.Commit
expectedError error
+ logOrder string
rebaseMode enums.RebaseMode
currentBranchName string
opts GetCommitsOptions
@@ -35,18 +36,20 @@ func TestGetCommits(t *testing.T) {
scenarios := []scenario{
{
testName: "should return no commits if there are none",
+ logOrder: "topo-order",
rebaseMode: enums.REBASE_MODE_NONE,
currentBranchName: "master",
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
runner: oscommands.NewFakeRunner(t).
Expect(`git merge-base "HEAD" "HEAD"@{u}`, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
- Expect(`git -c log.showSignature=false log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s" --abbrev=40`, "", nil),
+ Expect(`git -c log.showSignature=false log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s" --abbrev=40`, "", nil),
expectedCommits: []*models.Commit{},
expectedError: nil,
},
{
testName: "should return commits if they are present",
+ logOrder: "topo-order",
rebaseMode: enums.REBASE_MODE_NONE,
currentBranchName: "master",
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
@@ -54,7 +57,7 @@ func TestGetCommits(t *testing.T) {
// here it's seeing which commits are yet to be pushed
Expect(`git merge-base "HEAD" "HEAD"@{u}`, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
// here it's actually getting all the commits in a formatted form, one per line
- Expect(`git -c log.showSignature=false log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s" --abbrev=40`, commitsOutput, nil).
+ Expect(`git -c log.showSignature=false log "HEAD" --topo-order --oneline --pretty=format:"%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s" --abbrev=40`, commitsOutput, nil).
// here it's seeing where our branch diverged from the