Compare commits

..
894 Commits
Author SHA1 Message Date
Jesse Duffield 80d6bbef86 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-09-23 14:13:14 +10:00
Jesse Duffield 3d751c03fe add donation link to status panel 2018-09-23 14:13:10 +10:00
Jesse Duffield 4e0d0f7d75 Update README.md 2018-09-23 13:09:54 +10:00
Jesse Duffield b8b3eee961 Merge pull request #300 from jesseduffield/hotfix/273-cursor-scrolling
Fix slow scrolling
2018-09-22 13:59:49 +10:00
Jesse Duffield 7947668e18 Merge branch 'hotfix/273-cursor-scrolling' of https://github.com/jesseduffield/lazygit into hotfix/273-cursor-scrolling 2018-09-22 13:50:01 +10:00
Jesse Duffield 619c28ce56 use lineheight rather than buffer length 2018-09-22 13:49:58 +10:00
Jesse Duffield 53aef7846a Merge branch 'master' into hotfix/273-cursor-scrolling 2018-09-22 13:47:38 +10:00
Jesse Duffield 227067fdd1 use lineheight rather than buffer length 2018-09-22 13:44:48 +10:00
Jesse Duffield 3df4a9484f Merge pull request #295 from jesseduffield/hotfix/commit-message-panel-focus
Fix issues with commit message panel losing focus
2018-09-22 13:42:27 +10:00
Jesse Duffield 2229a6e133 Merge branch 'master' into hotfix/commit-message-panel-focus 2018-09-21 16:43:37 +10:00
Jesse Duffield 3101c50582 Merge pull request #297 from jesseduffield/hotfix/remove-files
add removeAll to git
2018-09-21 09:25:55 +10:00
Jesse Duffield 70ee4faf15 add removeAll to git 2018-09-21 09:23:00 +10:00
Jesse Duffield b9708c9f88 fix issues with commit message panel losing focus 2018-09-19 20:36:40 +10:00
Jesse Duffield 7b90d2496b Merge pull request #294 from jesseduffield/feature/recent-repos
Recent Repos Menu
2018-09-19 20:22:36 +10:00
Jesse Duffield 0367399cf3 bump deps to use forked termbox which doesn't crash as easily 2018-09-19 20:16:22 +10:00
Jesse Duffield 3072c93e13 Merge pull request #280 from jesseduffield/hotfix/cursor-positioning
Fix cursor positioning bugs
2018-09-19 19:55:14 +10:00
Jesse Duffield 4ea446205c Merge branch 'hotfix/cursor-positioning' into feature/recent-repos 2018-09-19 19:32:11 +10:00
Jesse Duffield 5a76b57952 one more spec to increase coverage 2018-09-19 19:31:29 +10:00
Jesse Duffield 6de291ff44 Merge branch 'hotfix/cursor-positioning' into feature/recent-repos 2018-09-19 19:23:42 +10:00
Jesse Duffield 64f0eeb42e fix specs 2018-09-19 19:23:31 +10:00
Jesse Duffield baa9eff318 Merge branch 'hotfix/cursor-positioning' into feature/recent-repos 2018-09-19 19:17:05 +10:00
Jesse Duffield fcaf4e339c fix specs 2018-09-19 19:16:55 +10:00
Jesse Duffield e91fb21233 add recent repos menu option 2018-09-19 19:15:29 +10:00
Jesse Duffield 99a6439641 Merge branch 'master' into hotfix/cursor-positioning 2018-09-19 18:42:25 +10:00
Jesse Duffield 768b9453f8 Merge branch 'hotfix/cursor-positioning' into feature/recent-repos 2018-09-19 18:40:41 +10:00
Jesse Duffield e95b2e5f0b update specs 2018-09-19 18:31:54 +10:00
Jesse Duffield 950cfeff6f add specs for menu utils 2018-09-19 18:19:26 +10:00
Jesse Duffield fce895ed0d Merge pull request #287 from antham/add-tests-part-6
Add tests part 6
2018-09-18 21:47:46 +10:00
Jesse Duffield b384fcf6af generalise popup menu panel 2018-09-18 21:07:25 +10:00
Anthony HAMON 60cf549a32 commands/git : reverse the logic 2018-09-18 09:23:41 +02:00
Anthony HAMON 6f0b32f95e commands/git : add GetCommits tests refactor
* switch GetCommitsToPush scope to private
* return a map instead of slice for look up
* remove useless includesString function
2018-09-17 21:19:17 +02:00
Jesse Duffield f89bc10af1 appease golangci 2018-09-17 21:32:19 +10:00
Jesse Duffield a66ac8092e minor refactor 2018-09-17 21:27:53 +10:00
Jesse Duffield bd04ecff69 Merge branch 'master' into hotfix/cursor-positioning 2018-09-17 21:03:29 +10:00
Jesse Duffield c00c834b35 standardise rendering of lists in panels 2018-09-17 21:02:30 +10:00
Anthony HAMON 9d9d775f50 circle : remove new line 2018-09-16 22:49:17 +02:00
Anthony HAMON 38036e0d20 circle : kill old cache 2018-09-16 22:41:41 +02:00
Anthony HAMON 9713a15167 commands/git : add test to GetBranchGraph, refactor 2018-09-16 22:12:03 +02:00
Anthony HAMON b641d6bd96 commands/git : add test to Checkout, refactor 2018-09-16 22:08:23 +02:00
Anthony HAMON 67a42f49b4 commands/git : add test to RemoveFile, refactor 2018-09-16 22:03:56 +02:00
Anthony HAMON bbc88071e9 gui : remove unreachable code 2018-09-16 20:46:25 +02:00
Jesse Duffield ca2eec60fe Merge pull request #285 from antham/add-tests-part-5
Add tests to pkg/commands/git - Part 5
2018-09-16 22:03:10 +10:00
Anthony HAMON c1b7a21631 commands/git : move tests 2018-09-16 11:11:09 +02:00
Anthony HAMON 91832f2c5e commands/git : add tests, refactor a bit 2018-09-16 11:11:09 +02:00
Jesse Duffield fa08c6c2a2 Merge pull request #284 from mingrammer/main-error
main: display an error message instead of panic when setup fails
2018-09-14 09:38:21 +10:00
mingrammer 3cf84a5af1 main: display an error message instead of panic when setup fails 2018-09-14 00:23:11 +09:00
Jesse Duffield eb4b5cd43b Merge pull request #282 from antham/add-tests-part-4
Add tests to pkg/commands/git - Part 4
2018-09-13 09:34:28 +10:00
Anthony HAMON c92510ceba commands/git : add tests on SquashFixupCommit and refactor 2018-09-12 22:45:52 +02:00
Anthony HAMON 65a24d70c3 commands/git : add tests on SquashPreviousTwoCommits 2018-09-12 20:43:03 +02:00
Jesse Duffield 3b765e5417 add test for min method 2018-09-12 19:39:36 +10:00
Jesse Duffield 57f6a552d2 Merge branch 'hotfix/cursor-positioning' of https://github.com/jesseduffield/lazygit into hotfix/cursor-positioning 2018-09-12 18:49:14 +10:00
Jesse Duffield 35cae80de9 more efficient building of branch displaystrings 2018-09-12 18:49:09 +10:00
Jesse Duffield b4b4cd83dd Merge branch 'master' into hotfix/cursor-positioning 2018-09-12 18:47:57 +10:00
Jesse Duffield 31c33dfdcb remove redundant comments 2018-09-12 18:47:37 +10:00
Jesse Duffield 79940b7ba9 Merge pull request #279 from jesseduffield/hotfix/file-ordering
Restore old file merging algorithm
2018-09-12 18:26:29 +10:00
Jesse Duffield 2ce8ac5850 restore old file sorting algorithm 2018-09-12 18:24:03 +10:00
Jesse Duffield f8b484f638 don't use newlines at the end of panel buffers 2018-09-12 18:23:25 +10:00
Jesse Duffield 73e2c1005a Merge pull request #277 from antham/add-tests-part-3
Add tests to pkg/commands/git - Part 3
2018-09-12 17:35:09 +10:00
Anthony HAMON 97e0a6dc45 commands/git : remove extra space 2018-09-12 07:51:14 +02:00
Anthony HAMON 9bad0337fe commands/git : swap global/local get config 2018-09-12 07:50:49 +02:00
Anthony HAMON f03544f392 commands/git : fix test 2018-09-11 22:20:59 +02:00
Anthony HAMON 0aba49af2b commands/git : fix typo 2018-09-11 21:56:17 +02:00
Anthony HAMON ccbc5e569c commands/git : add test to Push func, refactor 2018-09-11 21:56:17 +02:00
Anthony HAMON 415aad600c commands/git : add test to Commit func, refactor 2018-09-11 21:56:17 +02:00
Anthony HAMON d23577168f commands/git : remove dependency on gocui 2018-09-11 21:56:17 +02:00
Anthony HAMON 5c204b2813 commands/git: rewrite UsingGpg, add tests 2018-09-11 21:56:17 +02:00
Jesse Duffield 7d86278507 Merge pull request #274 from sascha-andres/master
fix: escape quote character on Linux
2018-09-11 09:07:36 +10:00
Sascha Andres 985196f5aa docs: add comments for new test code 2018-09-10 17:36:59 +02:00
Jesse Duffield 52b132fe01 better handling of cursor and origin positionings 2018-09-10 20:17:39 +10:00
Sascha Andres 9ec5a04cf5 merge: remote-tracking branch 'upstream/master' 2018-09-10 10:33:20 +02:00
Sascha AndresandJesse Duffield bb9698810d refactor: move fallback to platform struct
Co-authored-by: Jesse Duffield <jessedduffield@gmail.com>
2018-09-10 10:31:15 +02:00
Jesse Duffield 7f4371ad71 Merge pull request #275 from mjarkk/master
Translated untranslated dutch phrases
2018-09-10 18:15:15 +10:00
Sascha Andres 74144e3892 fix: remove call to fmt.Println 2018-09-10 10:10:10 +02:00
mjarkk 07f87eb7cf Added missing dutch translations 2018-09-10 08:08:53 +02:00
Mark Kopenga 5600da9ee7 Merge pull request #11 from jesseduffield/master
updated to latest master
2018-09-10 07:28:11 +02:00
Sascha Andres ba0cc20e22 feat: add test cases 2018-09-10 06:51:19 +02:00
Sascha AndresandDawid Dziurla 717913e64c fix: escape quote character on Linux
Co-authored-by: Dawid Dziurla <dawidd0811@gmail.com>

Closes #269
2018-09-10 06:36:15 +02:00
Jesse Duffield 5a0431bb62 Merge pull request #272 from antham/master
Add missing go.sum file
2018-09-10 10:58:22 +10:00
Jesse Duffield 1e357e2362 Merge branch 'master' into master 2018-09-10 10:02:06 +10:00
Jesse Duffield c3b62a555c Merge pull request #265 from antham/add-tests-part-2
Add tests to pkg/commands/git - Part 2
2018-09-10 10:01:55 +10:00
Jesse Duffield 557461c016 Merge branch 'master' into add-tests-part-2 2018-09-10 09:47:14 +10:00
Jesse Duffield c2e670104e Merge branch 'master' into master 2018-09-10 09:46:01 +10:00
Jesse Duffield bea9971f9c Merge pull request #271 from glvr182/feature/ignore-hidden-files
Change the gitignore a bit to cover more
2018-09-10 09:45:29 +10:00
Jesse Duffield a8fdf1a646 Merge branch 'master' into feature/ignore-hidden-files 2018-09-10 09:45:18 +10:00
Jesse Duffield f8ab4f4073 Merge pull request #234 from dawidd6/feature/help
WIP: Add menu panel (cheatsheet)
2018-09-10 09:43:28 +10:00
Anthony HAMON 24f15742d0 commands/git : rename variable 2018-09-09 20:08:46 +02:00
Glenn Vriesman 700f8c7e79 REPO: Added TODO entries to the gitignore for jesse 2018-09-09 13:37:38 +02:00
Anthony HAMON 28e8d6e472 add go.sum 2018-09-09 11:13:18 +02:00
Anthony HAMON 6076a75643 commands/git : fix function call 2018-09-09 10:52:34 +02:00
Anthony HAMON b46e4b4976 commands/git : add several tests, do some cleanup 2018-09-09 10:52:34 +02:00
Anthony HAMON 99eca7b000 commands/git : replace make function 2018-09-09 10:52:34 +02:00
Anthony HAMON a0faaf6893 commands/git : remove includes function 2018-09-09 10:52:34 +02:00
Anthony HAMON 56ad07ebab commands/git : rename functions 2018-09-09 10:52:34 +02:00
Anthony HAMON 1ecd74c357 commands/git : add tests for GetCommitsToPush 2018-09-09 10:52:34 +02:00
Anthony HAMON ceab9706cb commands/git : add tests for UpstreamDifferentCount 2018-09-09 10:52:34 +02:00
Anthony HAMON 1cc7e9c02a rewrite to use subtests 2018-09-09 10:52:34 +02:00
Dawid Dziurla 63e400647a shorter english string 2018-09-09 10:47:13 +02:00
Dawid Dziurla 6f7de83bce Merge branch 'master' into feature/help
conflicts resolved
2018-09-09 10:41:01 +02:00
Jesse Duffield 5af03b6820 Merge pull request #264 from antham/master
Add go.mod to support modules landed in go1.11
2018-09-09 11:35:48 +10:00
Glenn Vriesman a8866b158b REPO: Added and modified some ignore statements 2018-09-08 14:25:33 +02:00
antham 0d7a697e86 add go.mod 2018-09-07 21:35:04 +02:00
Dawid Dziurla e80371fc6f satisfy golangci 2018-09-07 14:41:01 +02:00
Dawid Dziurla 9cef98f779 ladies and gentlemen...
this is fmt number x+1
2018-09-07 14:23:08 +02:00
Dawid Dziurla ba6dedfb22 rewrite some of menu panel logic
panel keybindings are now on top and
global keybindings are below separated with empty newline
2018-09-07 14:19:16 +02:00
Jesse Duffield ca715c5b23 support switching to recent repo 2018-09-07 09:41:15 +10:00
Jesse Duffield ba7e6add86 Merge pull request #267 from glvr182/feature/add-effgo-link
Added entry to the contributing guide
2018-09-07 09:30:29 +10:00
Glenn Vriesman a820189450 Added entry to the contributing guide 2018-09-06 17:31:19 +02:00
Jesse Duffield ce95e6771a Merge pull request #263 from dawidd6/feature/confirm_quit
Add confirmOnQuit config option
2018-09-06 09:33:06 +10:00
Dawid Dziurla e9268d1828 add confirmOnQuit config option 2018-09-05 19:56:11 +02:00
Dawid Dziurla db2e2160a9 change menu keybinding from ? to x 2018-09-05 15:55:24 +02:00
Dawid Dziurla 08395ae76c workaround to include menu keybinding in cheatsheet 2018-09-05 15:45:20 +02:00
Dawid Dziurla 4188786749 update pl translation 2018-09-05 15:20:34 +02:00
Jesse Duffield cf41338a9f Merge pull request #262 from jesseduffield/feature/50/jesse
Add commit counter using subtitle
2018-09-05 23:09:20 +10:00
Jesse Duffield a2d40cfbf1 allow users to configure whether the commit length is shown 2018-09-05 23:02:13 +10:00
Dawid Dziurla 34d1648bd3 fmt strikes again 2018-09-05 13:23:06 +02:00
Dawid Dziurla 906f8e252e include global keybindings in menu 2018-09-05 13:16:40 +02:00
Jesse Duffield 986774e5c7 add commit count via gocui subtitle 2018-09-05 20:43:45 +10:00
Dawid Dziurla 98763e98cb initial commit message counter 2018-09-05 11:26:54 +02:00
Jesse Duffield f777c60ea4 Merge pull request #260 from jesseduffield/hotfix/258-commit-message-newlines
Fix popup panel resizing
2018-09-05 19:15:39 +10:00
Dawid Dziurla 557009e660 help -> menu 2018-09-05 11:12:11 +02:00
Jesse Duffield af876d2be2 Merge branch 'master' into hotfix/258-commit-message-newlines 2018-09-05 19:11:30 +10:00
Jesse Duffield 422b263df4 fix popup panel resizing 2018-09-05 19:10:46 +10:00
Jesse Duffield 4fc290b101 Update README.md 2018-09-05 18:44:24 +10:00
Jesse Duffield c1bf1e52b0 Merge pull request #257 from antham/master
Increase circleci compile speed
2018-09-05 17:12:29 +10:00
Anthony HAMON 4d745fa525 update cache path in circleci 2018-09-05 08:55:15 +02:00
Jesse Duffield f0e19690f5 Merge pull request #254 from jesseduffield/feature/dockerfile-for-alpine
Dockerfile for testing on alpine linux
2018-09-05 14:20:51 +10:00
Jesse Duffield 580c1cbc89 Merge branch 'master' into feature/dockerfile-for-alpine 2018-09-05 11:03:17 +10:00
Dawid Dziurla e21f739f4f add renderGlobalOptions
render only global options for all panels
2018-09-04 16:07:31 +02:00
Dawid Dziurla 97ad4a1643 delete options 2018-09-04 15:40:29 +02:00
Dawid Dziurla cbafadd48e move keys slice to guiState struct 2018-09-04 15:29:43 +02:00
Dawid Dziurla 7b84c162f4 set help panel fgcolor to white 2018-09-04 15:25:54 +02:00
Dawid Dziurla f29c81fb5c add getMaxKeyLength 2018-09-04 15:25:02 +02:00
Jesse Duffield 59003c8bbf Merge pull request #253 from jesseduffield/hotfix/238-xdg-open-2
Update xdg-open command
2018-09-04 22:21:03 +10:00
Jesse Duffield 6c1d133315 dockerfile for testing on alpine linux 2018-09-04 22:19:08 +10:00
Jesse Duffield 33ea093d88 Merge branch 'master' into hotfix/238-xdg-open-2 2018-09-04 20:37:35 +10:00
Jesse Duffield a81f8b84e3 Merge pull request #245 from antham/master
Rewrite SetupGit in GitCommand
2018-09-04 19:29:21 +10:00
Jesse Duffield 3f68fe42cb update xdg-open command 2018-09-04 19:18:18 +10:00
Anthony HAMON 172cd7c687 fix tests locally 2018-09-04 08:32:43 +02:00
Anthony HAMON df3e7abd68 use RunCommand 2018-09-04 08:32:40 +02:00
Anthony HAMON 8c67578063 replace fmt with errors 2018-09-04 06:21:58 +02:00
Anthony HAMON 06846ef3ae rename NewApp to Setup 2018-09-04 06:21:58 +02:00
Anthony HAMON 43ad9a81c2 merge setup in function that create a new git command 2018-09-04 06:21:58 +02:00
Anthony HAMON 9f7775df26 pkg/git : remove unused Map function 2018-09-04 06:21:58 +02:00
Anthony HAMON c1984528c8 pkg/git : add tests for SetupGit 2018-09-04 06:21:58 +02:00
Anthony HAMON 624d63d2fa pkg/git : remove panic in SetupGit method 2018-09-04 06:21:58 +02:00
Dawid Dziurla 67d99a24ea get selected branch from correct panel 2018-09-03 18:45:52 +02:00
Dawid Dziurla bf8514f5e2 helperize spaces 2018-09-03 18:44:56 +02:00
Dawid Dziurla 93e88ea8fe add missing translated polish strings 2018-09-03 18:34:04 +02:00
Dawid Dziurla a2073528f4 add missing untranslated dutch strings
@mjarkk
2018-09-03 18:33:38 +02:00
Dawid Dziurla 230a5afa4c remove capitalization of keybindings descriptions 2018-09-03 18:16:54 +02:00
Dawid Dziurla c49e4dc287 get item position from correct panel 2018-09-03 18:07:38 +02:00
Dawid Dziurla 59f50010b6 apply fmt again 2018-09-03 18:01:07 +02:00
Dawid Dziurla b5827b7d80 merge conflict effect fix 2018-09-03 17:57:03 +02:00
Dawid Dziurla 36874be45b apply very important fmt 2018-09-03 17:54:06 +02:00
Dawid Dziurla 83b7c60246 add untranslated dutch strings
@mjarkk
2018-09-03 17:54:06 +02:00
Dawid Dziurla 323016aa01 polish translation 2018-09-03 17:54:06 +02:00
Dawid Dziurla b403b6e46d better english string 2018-09-03 17:54:06 +02:00
Dawid Dziurla 359636c1aa add generate_cheatsheet script
script is generating markdown document with small cheatsheet
in selected language
2018-09-03 17:54:06 +02:00
Dawid Dziurla 1fa55875e2 remove testing content 2018-09-03 17:54:06 +02:00
Dawid Dziurla 5177e458ef use Fprint instead of renderString
renderString is wrapping content
because of that lines are being select wrong
2018-09-03 17:54:06 +02:00
Dawid Dziurla 314c8c279a apply fmt on keybindings 2018-09-03 17:54:06 +02:00
Dawid Dziurla 20073d0293 don't panic
"panic: runtime error: index out of range"

when executing stash pop 'g' from help menu
2018-09-03 17:54:06 +02:00
Dawid Dziurla 90a4cada82 add missing descriptions 2018-09-03 17:54:06 +02:00
Dawid Dziurla e376de6d1a explicitly delete 'help' view 2018-09-03 17:54:06 +02:00
Dawid Dziurla 265d7e121a use Key if it's a rune, otherwise KeyReadable 2018-09-03 17:54:06 +02:00
Dawid Dziurla 7ec5b6cc30 indent keybindings 2018-09-03 17:54:06 +02:00
Dawid Dziurla 9ceaf5b9a9 move descriptions to i18n 2018-09-03 17:52:05 +02:00
Dawid Dziurla cc3fa4b79d make '?' key visible on every panel 2018-09-03 17:52:05 +02:00
Dawid Dziurla 653d590157 help panel size from getConfirmationPanelDimensions 2018-09-03 17:52:05 +02:00
Dawid Dziurla 8a01d11202 more error checks 2018-09-03 17:52:05 +02:00
Dawid Dziurla 28a9594ef7 update help panel
- delete scrolling ability
- lines are now selectable
- implemented handler execution when space is pressed
- add example descriptions for status panel keybindings
2018-09-03 17:52:05 +02:00
Dawid Dziurla 77623db1d0 apply fmt 2018-09-03 17:52:05 +02:00
Dawid Dziurla 6a99d36ae1 change key from 'H' to '?' 2018-09-03 17:52:05 +02:00
Dawid Dziurla 2416f585ce initial help panel 2018-09-03 17:52:05 +02:00
Dawid Dziurla 741e28d01a move bindings to getKeybindings() 2018-09-03 17:52:05 +02:00
Jesse Duffield 19a8029795 Merge pull request #250 from dawidd6/fix/tests
Fix testing with localized rmdir + don't test scripts directory
2018-09-03 22:04:16 +10:00
Jesse Duffield 796f17eef4 Merge branch 'master' into fix/tests 2018-09-03 21:20:17 +10:00
Jesse Duffield 8fbb3aea4f Merge pull request #242 from d-dorazio/rename-commits-in-user-editor
add keybinding to open user editor when renaming last commit
2018-09-03 20:11:13 +10:00
Jesse Duffield 6fc4cb1b96 Merge branch 'master' into rename-commits-in-user-editor 2018-09-03 19:53:16 +10:00
Jesse Duffield 3c1935fee4 Merge pull request #249 from jesseduffield/hotfix/238-xdg-open
238: opening with xdg-open
2018-09-03 19:48:42 +10:00
Jesse Duffield dfb87d34dc Merge branch 'master' into hotfix/238-xdg-open 2018-09-03 19:42:06 +10:00
Jesse Duffield 4ab1a1f72b Merge branch 'master' into hotfix/238-xdg-open 2018-09-03 19:33:37 +10:00
Jesse Duffield a9cd277070 add test for ResolvePlaceholderString 2018-09-03 19:31:27 +10:00
Dawid Dziurla 5c1463313d respect localized output of rmdir 2018-09-01 17:22:49 +02:00
Dawid Dziurla 0355fc3008 don't run tests on scripts/ directory 2018-09-01 17:22:23 +02:00
Daniele D'Orazio 39f065207e add simple test for PrepareCommitAmendSubProcess 2018-09-01 12:29:43 +02:00
Daniele D'Orazio 9e6a4a529a add keybinding to open user editor when renaming last commit 2018-09-01 12:14:42 +02:00
Jesse Duffield 87de803a6c update default config header 2018-09-01 14:38:30 +10:00
Jesse Duffield 3cafa2bb12 update config to reflect platform specific defaults 2018-09-01 14:35:46 +10:00
Jesse Duffield d31520261f introduce platform specific defaults 2018-09-01 14:33:01 +10:00
Jesse Duffield ad880e2d56 wrap windows start command in shell 2018-09-01 13:28:10 +10:00
Jesse Duffield 865809e625 better error handling for commands 2018-09-01 13:27:58 +10:00
Jesse Duffield 04d5a473d7 use start instead of cygstart to open files on windows 2018-09-01 12:53:51 +10:00
Jesse Duffield f127ae62bb update config 2018-09-01 12:18:16 +10:00
Jesse Duffield 3f14b764d5 update tests 2018-09-01 12:13:41 +10:00
Jesse Duffield ae0d88f855 WIP using runDirectCommand with xdg-open 2018-09-01 11:38:32 +10:00
Jesse Duffield b65fa852f1 Merge pull request #248 from jesseduffield/hotfix/better-backwards-compatibility-error
Better error for nonbackwards compatible changes
2018-09-01 11:26:58 +10:00
Jesse Duffield 42500817e0 better error for nonbackwards compatible changes 2018-09-01 10:36:55 +10:00
Jesse Duffield d8aba3aeee Merge pull request #241 from antham/master
Fix linting issues
2018-08-29 23:05:14 +10:00
antham 1b8836e92d fix fmt issue 2018-08-29 13:46:51 +02:00
Anthony HAMON 54326907c3 fix linting issues 2018-08-29 13:46:51 +02:00
Anthony HAMON cda7b374e2 fix linting issues 2018-08-29 13:46:51 +02:00
Anthony HAMON e889a40caf fix golint issue 2018-08-29 13:46:51 +02:00
Jesse Duffield 3f26ddc06f Merge pull request #225 from antham/master
Add tests to pkg/commands/git - Part 1
2018-08-29 20:25:39 +10:00
Anthony HAMON dac7c90483 add cache based on Gopkg.lock checksum 2018-08-29 12:03:32 +02:00
Anthony HAMON 66e5dacf5e fix git tests 2018-08-29 12:03:32 +02:00
Anthony HAMON e3ed899b20 refactor MergeStatusFiles 2018-08-29 12:03:32 +02:00
Anthony HAMON d6b4d4b063 add tests for MergesStatusFiles 2018-08-29 12:03:32 +02:00
Anthony HAMON 45fa257128 add test for StashSave and refactor StashSave method 2018-08-29 12:03:32 +02:00
Anthony HAMON 99840d8fc4 add test for StashDo and refactor StashDo method 2018-08-29 12:03:32 +02:00
Anthony HAMON 85012dbc8f add tests for GetStatusFiles 2018-08-29 12:03:32 +02:00
Anthony HAMON 13f9073552 add test for GetStashEntryDiff 2018-08-29 12:03:32 +02:00
Anthony HAMON 49b507d2ff replace make 2018-08-29 12:03:32 +02:00
Anthony HAMON 8247fd69c9 add test for GetStashEntries 2018-08-29 12:03:32 +02:00
Anthony HAMON 983d0bd586 replace make 2018-08-29 12:03:32 +02:00
Anthony HAMON ca9ce22693 use assert in tests, rename testing method 2018-08-29 12:03:32 +02:00
Jesse Duffield cff1dee6dc more lenient version comparison 2018-08-29 09:37:47 +10:00
Jesse Duffield 2181a91fea Merge pull request #231 from jesseduffield/feature/24-support-unicode-characters
Support unicode characters
2018-08-28 20:09:27 +10:00
Jesse Duffield 8c2b8cfb51 support unicode characters 2018-08-28 20:08:35 +10:00
Jesse Duffield 145cba34a0 Merge pull request #228 from jesseduffield/hotfix/226-dont-panic-when-catting
226: dont panic when catting directories
2018-08-28 19:19:03 +10:00
Jesse Duffield 7e1e97d050 dont panic when catting directories 2018-08-28 19:12:35 +10:00
Jesse Duffield 320ccdb22a when panicking due to malformed gitconfig, show a more useful error 2018-08-28 18:01:53 +10:00
Jesse Duffield db1d5328f2 Merge pull request #213 from jesseduffield/feature/add-all
Add 'a' keybinding to toggle staged/unstaged for all files
2018-08-27 21:01:52 +10:00
Jesse Duffield da2d3f253f better translation 2018-08-27 20:58:17 +10:00
Jesse Duffield b4323c029f Merge branch 'master' into feature/add-all 2018-08-27 20:57:50 +10:00
Jesse Duffield 203ad29349 use logrus entry rather than logger 2018-08-27 20:51:21 +10:00
Jesse Duffield 04735d0601 update call to update user config function 2018-08-27 20:49:47 +10:00
Jesse Duffield bbe603ff5b separate english translation structs 2018-08-27 20:46:06 +10:00
Jesse Duffield 23a9f41d9d Merge branch 'feature/anonymous-reporting' 2018-08-27 20:35:55 +10:00
Jesse Duffield 1901901d24 Merge pull request #189 from jesseduffield/feature/auto-updates
Auto updates
2018-08-27 20:33:02 +10:00
Jesse Duffield f861175f83 move update quit confirmation function into updates file 2018-08-27 20:26:49 +10:00
Jesse Duffield 25c60b1854 localize update errors 2018-08-27 20:23:47 +10:00
Jesse Duffield 38557f131d record last update check as soon as you begin checking 2018-08-27 20:16:26 +10:00
Jesse Duffield 96eef7838e better auto update logic 2018-08-27 20:08:10 +10:00
Jesse Duffield 2bf536265a disable updating on windows for now 2018-08-27 19:37:01 +10:00
Jesse Duffield 43f612feb1 Merge branch 'master' into feature/auto-updates 2018-08-27 19:20:07 +10:00
Jesse Duffield a1c6adab59 Merge branch 'master' into feature/anonymous-reporting 2018-08-27 18:50:24 +10:00
Jesse Duffield e72d090c5c Merge pull request #221 from antham/fix-master
Fix format issue
2018-08-27 18:05:18 +10:00
Anthony HAMON a2a9e0c478 fix format issue 2018-08-27 10:01:05 +02:00
Jesse Duffield d3953a1440 Merge pull request #206 from antham/add-pkg-commands-test
Add test to pkg/commands, refactor some methods
2018-08-27 17:58:02 +10:00
Jesse Duffield a251cffb9a Merge pull request #220 from dawidd6/flag/config
Add config flag
2018-08-27 17:56:19 +10:00
Dawid Dziurla b7f6bcb3ca add config flag 2018-08-26 17:31:28 +02:00
Anthony HAMON 55c6af258d increase parallel build 2018-08-26 11:30:03 +02:00
Jesse Duffield 540edc0c35 anonymous reporting data 2018-08-26 16:53:31 +10:00
Jesse Duffield 12261ceb05 update config docs for auto updates 2018-08-26 13:03:37 +10:00
Anthony HAMON f6ab11e4ee run gofmt 2018-08-26 02:20:01 +02:00
Anthony HAMON 2d9f7009fa add gofmt to circle 2018-08-26 02:17:46 +02:00
Anthony HAMON 4b19b4108e add circleci cache 2018-08-26 01:58:20 +02:00
Anthony HAMON a23753dc18 exclude darwin arm from building 2018-08-26 01:58:20 +02:00
antham caf99d2d64 exclude openbsd cause of go-git bugs on this platform 2018-08-26 01:58:20 +02:00
antham 2273f4c0a5 add compile step in circleci 2018-08-26 01:58:20 +02:00
Anthony HAMON 23fe0290ad add openFile to gui struct 2018-08-26 01:58:20 +02:00
Anthony HAMON ed2dcd9e46 add tests 2018-08-26 01:58:20 +02:00
Anthony HAMON 75e08993ea extract dependencies 2018-08-26 01:58:20 +02:00
Anthony HAMON 0b07cd19f7 switch GetOpenCommand scope to private 2018-08-26 01:58:20 +02:00
Anthony HAMON 38f11f1f4a move dummy functions, rename functions 2018-08-26 01:58:19 +02:00
Anthony HAMON f91e2b12db add tests to pkg/commands 2018-08-26 01:58:19 +02:00
Anthony HAMON 364c1ac5e7 remove useless returned variable 2018-08-26 01:58:19 +02:00
Anthony HAMON 883fcf1083 remove useless returned variable 2018-08-26 01:58:19 +02:00
Anthony HAMON a891bc90b7 simplify method 2018-08-26 01:58:19 +02:00
Anthony HAMON 7a74bc504b avoid useless allocation 2018-08-26 01:58:19 +02:00
Anthony HAMON 32f4d09e89 move platform specific code to dedicated platform files 2018-08-26 01:58:19 +02:00
Anthony HAMON a5adfaee8a remove useless returned variable 2018-08-26 01:58:19 +02:00
Jesse Duffield 57decdd11d check error from setViewOnBottom 2018-08-25 17:38:03 +10:00
Jesse Duffield 87dc2bcad9 bump dependencies 2018-08-25 17:36:16 +10:00
Jesse Duffield 21f6e9ba87 auto-updates 2018-08-25 17:32:34 +10:00
Jesse Duffield f24c95aede Merge branch 'master' into feature/auto-updates 2018-08-25 11:02:46 +10:00
Jesse Duffield 93ab892bdd Merge pull request #214 from jesseduffield/hotfix/global-rune-keybindings
Ignore global rune keybindings when in editable view
2018-08-25 09:14:05 +10:00
Jesse Duffield ee7f88e123 ignore global rune keybindings when in editable view 2018-08-25 09:13:29 +10:00
Jesse Duffield 60422912c8 add 'a' keybinding to toggle staged/unstaged for all files 2018-08-25 08:59:51 +10:00
Jesse Duffield 6c389df57d Merge pull request #200 from remyabel/feature/esc-quits
Esc will quit when not in popup, fixes #197
2018-08-24 09:16:56 +10:00
Jesse Duffield 22de5e7b23 Merge pull request #210 from dawidd6/sirupsen/imports
Sirupsen -> sirupsen
2018-08-24 07:58:47 +10:00
Dawid Dziurla bcbeec1a56 Sirupsen -> sirupsen 2018-08-23 14:22:03 +02:00
Jesse Duffield 5628eae502 WIP 2018-08-23 18:43:16 +10:00
Jesse Duffield 2cdd439286 Merge pull request #204 from remyabel/hotfix/fix-dutch-errors
Fix typos causing tests to fail
2018-08-23 10:19:31 +10:00
Tommy Nguyen 110ff38c0d Remove accidentally checked in code 2018-08-22 11:34:16 -04:00
Tommy Nguyen 2680b2f4fe Merge branch 'hotfix/fix-dutch-errors' of github.com:remyabel/lazygit into hotfix/fix-dutch-errors 2018-08-22 11:28:09 -04:00
Tommy Nguyen 3e8ef0d12d Remove space before punctuation 2018-08-22 11:27:45 -04:00
remyabel bee4d98f52 Remove space before punctuation 2018-08-21 21:27:20 -04:00
Jesse Duffield 584d6b241c Merge pull request #198 from antham/fix-various-errors
Fix various errors reported by goreportcard
2018-08-22 09:28:19 +10:00
Anthony HAMON 37681627ab remove useless check 2018-08-21 20:54:48 +02:00
Anthony HAMON 810155ef2f fix documentation and reference issues 2018-08-21 20:54:46 +02:00
Tommy Nguyen 924a9bb2c9 Fix typos causing tests to fail 2018-08-21 10:55:33 -04:00
Jesse Duffield 4d635cd1cd Merge pull request #151 from alcohol/force-delete-branch
add option to force delete given branch
2018-08-21 23:45:27 +10:00
Jesse Duffield 3d49ab6666 Merge pull request #202 from dawidd6/test
Fix testPath for debian packaging
2018-08-21 23:33:25 +10:00
Tommy Nguyen eff931a138 Update gocui fork 2018-08-21 09:00:16 -04:00
Tommy Nguyen cd4063c763 s/escape/quit 2018-08-21 08:54:51 -04:00
Tommy Nguyen 646c205227 s/quit/escape, don't use special handling for views 2018-08-21 07:50:37 -04:00
Tommy Nguyen dc911906b3 Esc will quit when not in popup, fixes #197 2018-08-21 06:36:20 -04:00
Rob Bast 182e475116 correct variable assignment 2018-08-21 12:09:13 +02:00
Rob Bast 5f6b61d28c adjust translation(s) for forced branch deletion 2018-08-21 12:06:42 +02:00
Rob Bast 810540edfa add return 2018-08-21 11:32:17 +02:00
Jesse Duffield 042c83387e make bom.sh executable for easier testing 2018-08-21 17:41:18 +10:00
Jesse Duffield c6a8899060 Merge pull request #160 from remyabel/157_remove_bom
#157: clean BOM, allowing CSV files to display correctly
2018-08-21 17:39:55 +10:00
Jesse Duffield da4c12bf9e Merge pull request #193 from antham/add-tests
Add tests to i18n package
2018-08-21 17:34:13 +10:00
Jesse Duffield d6ee413587 Update Config.md 2018-08-21 13:42:17 +10:00
Jesse Duffield 9b63887867 add colored borders example image 2018-08-21 13:27:27 +10:00
Jesse Duffield d35eaa062b remove org-global context in circle ci config 2018-08-21 12:57:19 +10:00
Jesse Duffield 0c27776a83 Merge pull request #179 from antham/master
Update circleci config, add badges
2018-08-21 12:49:22 +10:00
Anthony HAMON 4972a4c218 rewrite addBundles 2018-08-20 21:18:50 +02:00
Anthony HAMON e4070ccb4f rewrite language detection, rewrite tests 2018-08-20 21:12:42 +02:00
Dawid Dziurla 483b4d939d fix testPath for debian packaging 2018-08-20 15:21:05 +02:00
Tommy Nguyen 45fea83771 Convert \r\n to \n; don't depend on unix2dos 2018-08-20 09:16:35 -04:00
Jesse Duffield 2aa89ade0d Merge pull request #195 from jesseduffield/hotfix/194-support-empty-version
194: Support empty version string
2018-08-20 20:54:23 +10:00
Jesse Duffield 37029f7db3 support empty version string 2018-08-20 20:52:32 +10:00
Jesse Duffield 954dfb12e4 Merge branch 'master' into feature/auto-updates 2018-08-20 19:53:53 +10:00
Jesse Duffield 8364509d1f Merge pull request #188 from jesseduffield/feature/force-push
Force push confirmation panel
2018-08-20 19:52:41 +10:00
Jesse Duffield d938a437a2 WIP auto updates 2018-08-20 19:52:20 +10:00
Anthony HAMON 3c0fb9b324 add tests to i18n package 2018-08-20 09:02:57 +02:00
Rob Bast 8e3df6b981 add option to force delete given branch 2018-08-20 08:37:16 +02:00
Tommy Nguyen 5dd049eb82 Convert test to use new library 2018-08-19 23:39:57 -04:00
Tommy Nguyen f1a4a7e1ff synchronize deps 2018-08-19 23:34:58 -04:00
Tommy Nguyen 108815c790 Add missing brace 2018-08-19 23:31:26 -04:00
remyabel 5c65066cbb Merge branch 'master' into 157_remove_bom 2018-08-19 23:29:47 -04:00
Jesse Duffield 64cf8f5b10 update dependencies 2018-08-20 13:25:33 +10:00
Jesse Duffield 5fcbe4ff8a Merge pull request #191 from jesseduffield/hotfix/174-language-not-found
174: Use fallback language if language not detected on startup
2018-08-20 13:23:26 +10:00
Jesse Duffield fa8248bd70 use fallback language if language not detected on startup 2018-08-20 13:20:59 +10:00
Jesse Duffield 65c5a6014b Merge pull request #185 from antham/add-tests
Add test to utils package
2018-08-20 09:24:54 +10:00
Anthony HAMON fc126a1718 remove test 2018-08-19 21:39:23 +02:00
Anthony HAMON bb86a3ff7c update github template 2018-08-19 20:21:19 +02:00
Anthony HAMON bbf7a9d790 add various badges
* golangci (https://golangci.com)
* circleci (https://circleci.com/)
* codecov.io (https://codecov.io)
* godoc
* tag release
2018-08-19 20:21:19 +02:00
Anthony HAMON fbfa48f0fc update circleci
* define release worflow when a tag is created
* add dep install
* run tests with coverage
* add goreleaser
2018-08-19 20:21:14 +02:00
Tommy Nguyen e8b12a086c Fix ineffectual assignment 2018-08-19 08:52:08 -04:00
Tommy Nguyen 766197de9d NormalizeLinefeeds removes rather than converts Window/Mac style lf's 2018-08-19 08:48:03 -04:00
Jesse Duffield 1e44001910 Merge branch 'master' into feature/auto-updates 2018-08-19 21:36:40 +10:00
Jesse Duffield 317926c808 fix golangci lint 2018-08-19 21:34:24 +10:00
Jesse Duffield 4d2346f80a popup force push confirmation panel if the local branch has diverged from the upstream branch 2018-08-19 21:28:13 +10:00
Tommy Nguyen d2bdac29aa Merge branch 'master' into 157_remove_bom 2018-08-19 07:22:48 -04:00
Tommy Nguyen cea736e6e9 Factor out into NormalizeLinefeeds; add tests 2018-08-19 07:20:50 -04:00
Jesse Duffield e6712832b5 Merge pull request #187 from jesseduffield/hotfix/177-fix-gitignore
177: Fix ignore feature
2018-08-19 20:42:51 +10:00
Jesse Duffield aa4d739577 fix ignore feature 2018-08-19 20:41:04 +10:00
Jesse Duffield 51558f51ab Merge pull request #186 from jesseduffield/hotfix/169-more-filenames-with-spaces
Handle filenames with spaces better
2018-08-19 20:19:53 +10:00
Jesse Duffield 35884f81e9 handle filenames with spaces better 2018-08-19 20:13:29 +10:00
Jesse Duffield 2008607108 remove VERSION file 2018-08-19 20:04:57 +10:00
Jesse Duffield 21be9fb3b1 bump version to v0.1.72 2018-08-19 19:48:31 +10:00
Jesse Duffield 80fac559c2 revert changes to ldflags 2018-08-19 19:48:21 +10:00
Jesse Duffield e6a6301144 bump version to v0.1.71 2018-08-19 19:47:04 +10:00
Jesse Duffield c5d4024d58 compare error message rather than error itself on no-commits error 2018-08-19 18:51:42 +10:00
Anthony HAMON f91b4067f4 add test to utils package 2018-08-19 10:37:03 +02:00
Tommy Nguyen b46d174f70 view_helpers.go: don't ignore return value 2018-08-19 02:21:33 -04:00
Tommy Nguyen cdc6d45fa4 view_helpers.go: replace \r with \r\n 2018-08-19 02:19:19 -04:00
Jesse Duffield 81b07daa01 Merge branch 'hotfix/167-ambiguous-name-in-diff' 2018-08-19 15:06:06 +10:00
Jesse Duffield 93266cc2a4 support forked branches when getting project root 2018-08-19 15:05:36 +10:00
Jesse Duffield 60fc24eada Merge pull request #172 from jesseduffield/hotfix/167-ambiguous-name-in-diff
167: Support File names that match Branch names
2018-08-19 14:53:14 +10:00
Jesse Duffield 6978785ccf add user email and config to test repo generators 2018-08-19 14:52:08 +10:00
Jesse Duffield cd9eada0c6 add test for variety of potential git diff situations 2018-08-19 14:48:39 +10:00
Jesse Duffield 7b3679d546 Merge pull request #181 from glvr182/feature/ignore-unused
Cleaned the gitignore and added the linux binary
2018-08-19 13:26:35 +10:00
Jesse Duffield c8e63894b4 Merge pull request #182 from glvr182/feature/docs-images
Feature/docs images
2018-08-19 13:25:23 +10:00
Jesse Duffield af93d04479 Merge pull request #183 from mjarkk/master
Removed logrus logger import from i18n
2018-08-19 13:23:29 +10:00
Mark Kopenga 29f2bdbba3 removed logrus logger import 2018-08-18 14:03:20 +02:00
Mark Kopenga c90e865e34 Merge pull request #10 from jesseduffield/master
Updated to latest master
2018-08-18 14:00:41 +02:00
Jesse Duffield b104dccab2 Merge pull request #163 from dawidd6/translation/pl
Add Polish translation
2018-08-18 21:08:56 +10:00
Glenn Vriesman 2dbd5be24e Removed duplicates 2018-08-18 13:04:44 +02:00
Glenn Vriesman 0a4cf6a544 Docs: Fixed typo 2018-08-18 12:56:15 +02:00
Glenn Vriesman 5f5e275a0e Docs: Made commit-diffs example a local file 2018-08-18 12:55:13 +02:00
Glenn Vriesman 7b85d146af Docs: Made resolving merge conflicts a local file 2018-08-18 12:53:26 +02:00
Glenn Vriesman fd01cdb137 Docs: Made the example gif a local file 2018-08-18 12:51:15 +02:00
Glenn Vriesman 9e8dc37308 Docs: Moved slack image to docs/resources 2018-08-18 12:46:50 +02:00
Jesse Duffield 08666889f4 improve remove file logic 2018-08-18 20:14:44 +10:00
Jesse Duffield 13ac1d151a WIP updater package 2018-08-18 19:54:44 +10:00
Glenn Vriesman c091401571 Cleaned the gitignore and added the linux binary 2018-08-18 11:49:37 +02:00
Jesse Duffield 0174375562 Merge pull request #180 from jesseduffield/hotfix/174-nil-pointer-reference-on-startup
Hotfix for issue 174: avoid nil pointer reference on startup
2018-08-18 19:45:28 +10:00
Jesse Duffield 1f756d3d0a avoid nil pointer reference on startup 2018-08-18 19:43:58 +10:00
Jesse Duffield 6473e5ca3c use runtime package to get GOOS and GOARCH 2018-08-18 17:28:03 +10:00
Jesse Duffield 896dda3adf bump version to v0.1.70 2018-08-18 17:17:22 +10:00
Jesse Duffield b9ef1a4d67 leave bump commits out of release notes 2018-08-18 17:17:05 +10:00
Jesse Duffield 671c693459 bump version to v0.1.67 2018-08-18 17:12:44 +10:00
Jesse Duffield 41171304b2 add platform/os details to goreleaser ldflags 2018-08-18 17:10:27 +10:00
Jesse Duffield f025b289f0 enforce white text color in prompt panels 2018-08-18 16:23:19 +10:00
Tommy Nguyen 018b43163c synchronize deps 2018-08-18 02:20:10 -04:00
remyabel 9a923eb300 Merge branch 'master' into 157_remove_bom 2018-08-18 02:11:13 -04:00
Jesse Duffield 3f5c1a4243 bump version to v0.1.66 2018-08-18 16:00:30 +10:00
Jesse Duffield db7e623c0c bump version to v0.1.65 2018-08-18 16:00:12 +10:00
Jesse Duffield ad8f02b986 add 386 architecture to releases 2018-08-18 16:00:00 +10:00
Jesse Duffield 29431ddc8e create dashboard 2018-08-18 15:30:56 +10:00
Jesse Duffield a1a828a781 support opening and editing config file 2018-08-18 14:54:05 +10:00
Jesse Duffield 6b150a4be0 bump dependencies 2018-08-18 14:20:19 +10:00
Jesse Duffield 284c534251 user configurable border colors 2018-08-18 13:53:58 +10:00
Jesse Duffield 10fdb5a609 support writing back to user config 2018-08-18 13:22:05 +10:00
Jesse Duffield 4dc6d40b5a merge master 2018-08-18 12:08:21 +10:00
Jesse Duffield 99d40c2f8e run codecov report after other commands on circle ci 2018-08-18 11:17:31 +10:00
Mark Kopenga 0f145093fe Here i a fix for the error go complain on your pull 2018-08-17 20:43:51 +02:00
Jesse Duffield bd91b9e1e9 add test repo for all the kinds of files that show up when diffing 2018-08-17 22:46:10 +10:00
Dawid Dziurla bf5f3bb972 pl translation 3 2018-08-17 14:27:13 +02:00
Jesse Duffield 03a7e32694 support filenames that match branchnames 2018-08-17 22:25:53 +10:00
Dawid Dziurla b0e08491ac pl translation 2 2018-08-17 14:11:48 +02:00
Jesse Duffield aaa8558de8 Merge pull request #159 from remyabel/158_escape_backticks
#158: escapes backticks, which is a problem in shells like Bash
2018-08-17 21:11:20 +10:00
Mark Kopenga 633553bcf8 Merge pull request #7 from jesseduffield/master
Update to latest master
2018-08-17 10:33:10 +02:00
Jesse Duffield 933aae7da1 bump version to v0.1.64 2018-08-17 11:15:41 +10:00
Jesse Duffield 3b1689727a bump version to v0.1.63 2018-08-17 11:15:19 +10:00
Jesse Duffield c08e6d9999 bump version to v0.1.62 2018-08-17 11:14:54 +10:00
Jesse Duffield dcd3bb6bbd use platform independent command to remove a file or directory 2018-08-17 11:13:21 +10:00
Jesse Duffield bd15f9d27a Merge pull request #164 from dawidd6/ubuntu/release-ppa
Add info about release PPA
2018-08-17 09:05:31 +10:00
Tommy Nguyen 52033b32f7 Use strings.Replace instead of regexp 2018-08-16 17:04:39 -04:00
Mark Kopenga 5c738fa493 Removed duplicates 2018-08-16 20:59:32 +02:00
Mark Kopenga 9a0f29ff5b Merge pull request #5 from jesseduffield/master
Updated to latest master
2018-08-16 20:08:14 +02:00
Dawid Dziurla 36eed80228 add info about release PPA 2018-08-16 19:26:43 +02:00
Dawid Dziurla 2d80a83d27 pl translation 1 2018-08-16 18:56:16 +02:00
Jesse Duffield f4e701611b Merge pull request #162 from ponsfrilus/patch-3
Typo path → patch
2018-08-16 23:40:37 +10:00
Nicolas Borboën ff15d86ced Typo path → patch 2018-08-16 14:15:55 +02:00
Jesse Duffield 8b57b21d79 add circle ci config 2018-08-16 22:07:02 +10:00
remyabel 64d8a55dbd Merge branch 'master' into 157_remove_bom 2018-08-16 07:59:31 -04:00
Jesse Duffield 563efc41c7 bump dependencies for i18n 2018-08-16 21:48:09 +10:00
Jesse Duffield 090537a1f1 Merge pull request #137 from mjarkk/master
Added a view basic translation functions and translation file
2018-08-16 21:46:42 +10:00
Mark Kopenga fcf616bd62 Fixed it 2018-08-16 13:35:04 +02:00
Tommy Nguyen 74d81ae080 [rebase] Fix errors; update dependencies
Argument must be []byte not string

Don't commit bomtest.txt
2018-08-16 07:17:47 -04:00
Tommy Nguyen a7755ab184 reformat 2018-08-16 07:00:13 -04:00
Mark Kopenga faf218f465 Fixed comments from jesseduffield on issue #137 2018-08-16 11:31:50 +02:00
Mark Kopenga 90746502df Fixed comments from jesseduffield on issue #137 2018-08-16 11:31:03 +02:00
Jesse Duffield df7d1df4cb bump dependencies 2018-08-16 19:20:59 +10:00
Jesse Duffield 5819e04c53 use shibukawa/configdir package to follow xdg spec config directory structure 2018-08-16 19:17:38 +10:00
Jesse Duffield fd3ce21576 use yaml for config file rather than json 2018-08-16 18:43:46 +10:00
Tommy Nguyen 3a31b84d1a add BOM test generator 2018-08-16 02:00:34 -04:00
Tommy Nguyen f09515867d #157: clean BOM, allowing CSV files to display correctly 2018-08-16 01:53:53 -04:00
Mark Kopenga 88e1a815fe Fixed comment on issue #137 from @jesseduffield 2018-08-16 07:16:32 +02:00
Tommy Nguyen db94dde114 fix formatting 2018-08-15 23:58:44 -04:00
Tommy Nguyen ee4660af97 #158: escapes backticks, which is a problem in shells like Bash 2018-08-15 23:55:55 -04:00
Jesse Duffield 59ab38fff6 Update README.md 2018-08-16 10:37:23 +10:00
Jesse Duffield adc906bb87 add slack image file 2018-08-16 10:32:52 +10:00
Mark Kopenga 9abbfe5a43 Fully translated pkg/gui/confirmation_panel.go 2018-08-15 15:12:55 +02:00
Mark Kopenga 9112278ab7 Merge pull request #4 from jesseduffield/master
Update to latest master
2018-08-15 15:03:27 +02:00
Mark Kopenga d00c46a712 Added all english translations to a file and fixed some typos 2018-08-15 14:57:20 +02:00
Jesse Duffield 29ed971558 add user configuration in json file 2018-08-15 22:06:37 +10:00
Jesse Duffield 8d99b400fd factor out code for new popup panels 2018-08-15 21:49:38 +10:00
Jesse Duffield 7c33c02930 dont panic if unable to close confirmation prompt 2018-08-15 21:43:31 +10:00
Mark Kopenga 50b41bfccc Translated pkg/gui/view_helpers.go 2018-08-15 11:49:43 +02:00
Mark Kopenga 295093a432 Translated pkg/gui/stash_panel.go 2018-08-15 11:12:46 +02:00
Mark Kopenga 10c53162ca Merge pull request #3 from jesseduffield/master
Updated to latest master
2018-08-15 10:54:43 +02:00
Mark Kopenga 7e926cf41d Added translation for pkg/gui/ confirmation_panel.go gui.go merge_panel.go 2018-08-15 10:53:05 +02:00
Mark Kopenga d12cc5a74e Fully translated pkg/gui/commits_panel.go 2018-08-15 10:30:29 +02:00
Mark Kopenga 8418fa17a5 Fully translated pkg/gui/commit_message_panel.go 2018-08-15 09:15:31 +02:00
Jesse Duffield 905e6c16ba add credential helper to config of test repo 2018-08-15 15:15:21 +10:00
Jesse Duffield db140842f3 bump version to v0.1.61 2018-08-15 09:56:15 +10:00
Jesse Duffield 7002ee5d9b bump version to v0.1.60 2018-08-15 09:52:23 +10:00
Jesse Duffield 0687c07f50 more robust reading of reflog to get branch name 2018-08-15 09:45:24 +10:00
Jesse Duffield 922f4ed5a4 try rev-parse of git symbolic-ref returns nothing 2018-08-15 09:42:02 +10:00
Mark Kopenga 3dba246029 Added translations for files_panel.go and fixed some typos 2018-08-14 22:29:17 +02:00
Mark Kopenga be3f5846e4 Added more translations 2018-08-14 21:06:50 +02:00
Mark Kopenga 38a1a00cf1 Fixed comment from myself on issue: 137 2018-08-14 16:38:25 +02:00
Mark Kopenga 9c97b75aad Merge remote-tracking branch 'origin/master' 2018-08-14 16:14:11 +02:00
Mark Kopenga 883f436b0f can't go any further because of an error 2018-08-14 16:12:21 +02:00
Jesse Duffield d923796cff Merge branch 'master' of https://github.com/mjarkk/lazygit 2018-08-14 23:48:18 +10:00
Jesse Duffield ba2b6fbf1f pull errors out of package scope and store sentinel errors on the gui struct 2018-08-14 23:47:14 +10:00
Mark Kopenga 73a1682540 fixed package naming and added tr object to file_panel.go 2018-08-14 15:26:25 +02:00
Mark Kopenga 8e22d569a0 Merge pull request #2 from jesseduffield/master
Updated to latest master
2018-08-14 15:10:59 +02:00
Jesse Duffield 4d0702fba5 Merge branch 'master' of https://github.com/mjarkk/lazygit 2018-08-14 22:12:11 +10:00
Jesse Duffield 5cbacb0c67 make local i18n package confirm to project structure 2018-08-14 22:12:07 +10:00
Mark Kopenga 0568b32f0b Added more translations 2018-08-14 13:31:23 +02:00
Mark Kopenga 6e518142b4 added some commands 2018-08-14 12:56:11 +02:00
Mark Kopenga 0c39347224 Added auto detection for the system language 2018-08-14 12:52:26 +02:00
Mark Kopenga dd7e93ac8d Added all the missing translations from dutch.go 2018-08-14 11:35:39 +02:00
Mark Kopenga f792f74f0f Merge remote-tracking branch 'origin/master' 2018-08-14 11:28:11 +02:00
Mark Kopenga 5ad97add08 Added the translation to some words again 2018-08-14 11:27:46 +02:00
Jesse Duffield 652237d48f bump version to v0.1.59 2018-08-14 19:23:05 +10:00
Jesse Duffield 6a3f8eefa5 send version number through app 2018-08-14 19:22:38 +10:00
Mark Kopenga 17dcfbcc6f Merge pull request #1 from jesseduffield/master
Update to latest master
2018-08-14 11:06:34 +02:00
Mark Kopenga dfafb98871 tried to update to latest master 2018-08-14 11:05:26 +02:00
Jesse Duffield 8cc8c4c228 bump version to v0.1.58 2018-08-14 18:49:15 +10:00
Jesse Duffield 574b34930c support files with spaces in name 2018-08-14 18:48:08 +10:00
Jesse Duffield 77080f44a4 bump version to v0.1.57 2018-08-14 18:38:04 +10:00
Jesse Duffield 97daa5eeb2 bump version to v0.1.56 2018-08-14 18:36:51 +10:00
Jesse Duffield c476dfc1cb fix open command 2018-08-14 18:35:47 +10:00
Jesse Duffield bde6182c94 better git squash logic 2018-08-14 18:30:06 +10:00
Jesse Duffield efb049cd24 better error handling for stashing files 2018-08-14 18:29:25 +10:00
Jesse Duffield 88af0fb1b6 add gpg repo generator 2018-08-14 18:12:09 +10:00
Jesse Duffield 5f30f07ea5 Merge branch 'master' into feature/quoted-messages 2018-08-14 18:10:44 +10:00
Jesse Duffield c02f474bf3 update dependencies 2018-08-14 18:05:18 +10:00
Jesse Duffield b32173b0c7 output to development.log in append mode 2018-08-14 18:02:27 +10:00
Jesse Duffield 1c750fdb40 fix reflog command 2018-08-14 18:02:14 +10:00
Jesse Duffield 9ecd7908aa refactor commands to depend less on the shell 2018-08-14 17:47:33 +10:00
Jesse Duffield ad3d332e05 Merge pull request #143 from jesseduffield/feature/clean_up
Platform should only be present once
2018-08-14 12:33:47 +10:00
Andrei Miulescu 842ceec9b0 Platform should only be present once 2018-08-14 12:24:32 +10:00
Jesse Duffield 95c7df4c61 use platform-specific message quoting 2018-08-14 11:16:52 +10:00
Jesse Duffield c0a1f90604 Merge pull request #132 from jesseduffield/feature/project_restructure
Project Restructure Episode 1
2018-08-14 09:02:38 +10:00
Jesse Duffield 15528dc341 Merge branch 'master' into feature/project_restructure 2018-08-14 08:44:39 +10:00
Jesse Duffield 7ecbd7fbb3 update pre-commit hook 2018-08-14 08:42:08 +10:00
Jesse Duffield 45f640941c update dependencies 2018-08-14 08:34:31 +10:00
Jesse Duffield 047892962a centralise subprocess code to gui.go 2018-08-14 08:33:40 +10:00
Jesse Duffield d4f4b46a1f check both local and global config for gpgsign 2018-08-14 08:33:27 +10:00
Jesse Duffield f549ad0f37 use git command with message in subprocess if using gpgsign 2018-08-14 07:27:59 +10:00
Mark Kopenga f2dfcb6e12 Added more messages and text issue: #137 2018-08-13 22:00:44 +02:00
Mark Kopenga 65eb3780a0 fixed typo 2018-08-13 20:48:49 +02:00
Mark Kopenga d9959eb998 fixed @jesseduffield comment #137 2018-08-13 20:46:53 +02:00
Jesse Duffield ebfed34145 add PR #135 keybindings to this branch 2018-08-13 23:46:08 +10:00
Jesse Duffield 450f269f02 Merge pull request #135 from jon-grangien/feature/ctrl-keybindings
Add C-u and C-d keybindings for scrolling up and down diff
2018-08-13 23:43:54 +10:00
Jesse Duffield 95d2b02664 update gitignore 2018-08-13 23:36:06 +10:00
Jesse Duffield 59e5545f38 discard log output when not in debug mode 2018-08-13 23:35:01 +10:00
mjarkk 62fc831407 Added a view basic translation functions + tranlation file 2018-08-13 15:33:45 +02:00
Jesse Duffield fb0004481b correct cursor before returning item position 2018-08-13 21:42:56 +10:00
Jesse Duffield 3bd0246e4d add test repo contents to gitignore 2018-08-13 21:42:31 +10:00
Jesse Duffield 12de0345e4 minor cleanup 2018-08-13 21:35:54 +10:00
Jesse Duffield 9e725ae24e got this bad boy compiling again 2018-08-13 21:16:21 +10:00
Jesse Duffield 97cff65612 progress on refactor 2018-08-13 20:26:02 +10:00
codingInSpace a32fc34a49 Add C-u and C-d keybindings for scrolling up and down diff 2018-08-13 04:09:32 -04:00
Jesse Duffield f9c39ad64b add newline to version output 2018-08-13 17:20:03 +10:00
Jesse Duffield 1571e6b962 add newline to version output 2018-08-13 12:27:26 +10:00
Jesse Duffield 84b27d402d Update issue templates 2018-08-12 23:46:38 +10:00
Jesse Duffield e6beb5d50b no more go-git for committing (reflecting the change in master) 2018-08-12 23:29:58 +10:00
Jesse Duffield 1354885db0 bump version to v0.1.55 2018-08-12 23:20:10 +10:00
Jesse Duffield 360bfa4642 bump version to v0.1.54 2018-08-12 23:17:47 +10:00
Jesse Duffield bb0e580a27 bump version to v0.1.53 2018-08-12 23:17:25 +10:00
Jesse Duffield 1eb0061357 bump dependencies 2018-08-12 23:16:58 +10:00
Jesse Duffield 4cd2d70659 revert to using cli git command rather than go-git for committing 2018-08-12 23:14:37 +10:00
Jesse Duffield 35d695fd0c update gitignore to reflect new test repo directory structure 2018-08-12 23:00:51 +10:00
Andrei Miulescu e8eb78617c Mid refactor change some more stuff 2018-08-12 21:04:47 +10:00
Andrei Miulescu e65ddd7b6f Move some commands around 2018-08-12 20:22:20 +10:00
Jesse Duffield c01bc09442 WIP refactor 2018-08-12 19:50:55 +10:00
Andrei Miulescu dcd461d29f Restrucure project in a way where it is more modular 2018-08-12 19:31:27 +10:00
Jesse Duffield 98c22a36fd rearrange test repo generators 2018-08-12 15:54:59 +10:00
Jesse Duffield 7bfd8155c2 bump version to v0.1.52 2018-08-12 12:01:50 +10:00
Jesse Duffield ed1518fd66 fix CPU issues caused by resizing popup panels 2018-08-12 12:00:30 +10:00
Jesse Duffield 400301e8fa bump gocui fork to support getting view dimensions 2018-08-12 11:39:37 +10:00
Jesse Duffield f97a098c6f Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-12 11:05:24 +10:00
Jesse Duffield 2b3bdc8b8f rename merge conflict test repo 2018-08-12 11:05:21 +10:00
Jesse Duffield 7323e08fdb Merge pull request #127 from ponsfrilus/master
Proposal for a slightly better README.md
2018-08-12 00:51:31 +10:00
Jesse Duffield 838ed4f170 Merge pull request #104 from maxice8/add-void-readme
README.md: Add Void Linux instructions
2018-08-12 00:43:43 +10:00
Jesse Duffield feba6b5318 Merge pull request #129 from ponsfrilus/patch-2
Use <kbd> tags
2018-08-12 00:42:50 +10:00
Nicolas Borboën 27234c1cab Use <kbd> tags
and that close #128
2018-08-11 12:13:14 +02:00
Jesse Duffield 8f6329c402 if you are using gpgsign, must use git editor to commit 2018-08-11 19:28:32 +10:00
Nicolas Borboën 0ac56f5ade Proposal for a slighty bettre README.md
* Text wrapped to 80 chars;
* Kind of table of content;
* Launchpad PPA link added;
* AUR package on a bullet list;
* Missing ponctuation added;
* Youtube tutorial and keybindings on a bullet list.
2018-08-11 11:11:55 +02:00
Jesse Duffield 471a7de418 bump version to v0.1.51 2018-08-11 17:08:20 +10:00
Jesse Duffield 77191ea67c show output line by line in deploy script 2018-08-11 17:07:56 +10:00
Jesse Duffield 176aa62fe0 bump version to v0.1.50 2018-08-11 17:06:50 +10:00
Jesse Duffield 1419be1aab support commit message via git editor using shift+C keybinding 2018-08-11 16:55:39 +10:00
Jesse Duffield 0ac306fe2a fix whitespace 2018-08-11 16:55:15 +10:00
Jesse Duffield f0840c0f46 fallback to vi when trying to edit file and no EDITOR/VISUAL is defined 2018-08-11 16:55:05 +10:00
Jesse Duffield 6d4d6d3ac0 bump version to v0.1.49 2018-08-11 16:22:49 +10:00
Jesse Duffield 2dba6f6733 support case insensitive branch names 2018-08-11 16:11:17 +10:00
Jesse Duffield aec125df70 Merge branch 'master' into add-void-readme 2018-08-11 15:50:42 +10:00
Jesse Duffield 9626ebdf35 correct typo in keybinding for delete branch 2018-08-11 15:45:38 +10:00
Jesse Duffield 2c140445e5 Merge branch 'master' into feature/deleting-branches 2018-08-11 15:43:56 +10:00
Jesse Duffield 62a231abb7 handle commit select on any commits panel refresh 2018-08-11 15:34:57 +10:00
Jesse Duffield 753ca75e55 clear commit panel after confirming 2018-08-11 15:26:02 +10:00
Jesse Duffield 5c8f0d4c9d gitignore test repo 2018-08-11 15:23:57 +10:00
Jesse Duffield 000a709783 update test repo generators including test for unicode characters 2018-08-11 15:22:41 +10:00
Jesse Duffield 5c185572a7 delete test file that was accidentally committed 2018-08-11 15:12:30 +10:00
Jesse Duffield bb86d527e1 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-11 15:12:10 +10:00
Jesse Duffield 0e3dec1069 Merge branch 'master' into feature/add-fixup-option-into-commits-panel 2018-08-11 15:11:19 +10:00
Jesse Duffield 7e141283f6 merge branch master 2018-08-11 15:09:37 +10:00
Jesse Duffield e46f3b3393 add spew dependency to vendor 2018-08-11 15:04:42 +10:00
Jesse Duffield 73e740d1ba clean up fixup code
reduce log clutter
add log dumping with spew
2018-08-11 15:04:02 +10:00
Jesse Duffield f1eaeec9ee remove time logging 2018-08-11 14:47:11 +10:00
Jesse Duffield a713fff362 Merge pull request #98 from frealgagu/master
Adding arch linux packages to README.md
2018-08-11 14:04:44 +10:00
Jesse Duffield 6d3d40c41f handle error on confirmation panel resize 2018-08-11 13:27:34 +10:00
Jesse Duffield 2137d3f6d2 Merge branch 'feature/multiline-commit-restoring' of https://github.com/jesseduffield/lazygit into feature/multiline-commit-restoring 2018-08-11 13:24:15 +10:00
Jesse Duffield 8ae346787a revert use of stored values in confirmation panels 2018-08-11 13:24:05 +10:00
Jesse Duffield b8daf71db6 Delete ZHgalGrWSF 2018-08-11 13:19:54 +10:00
Jesse Duffield fd13cf14b4 Merge branch 'feature/multiline-commit-restoring' 2018-08-11 13:19:17 +10:00
Jesse Duffield 47bf649a69 switch focus back to files view after confirming commit message 2018-08-11 13:18:33 +10:00
Jesse Duffield 3b018e040f make
commit
messages
multilined
and add ability save commit message between edits
2018-08-11 13:17:20 +10:00
Jesse Duffield b2fbccd392 remove time logging 2018-08-11 12:35:17 +10:00
Fredy Alberto García Güiza 542fd8e88a Fixing grammar about arch linux packages in README.md 2018-08-10 19:47:16 -05:00
Jesse Duffield 9fbc332c9a Merge pull request #114 from glvr182/feature/add-repo-name
Feature: Added repository name to status
2018-08-11 09:51:11 +10:00
Jesse Duffield 1ef794e09f Update README.md 2018-08-11 09:43:22 +10:00
Hubert Baumgartner bfa47d3b91 extenden delete branch with error message and confirmation 2018-08-10 20:19:58 +02:00
Hubert Baumgartner 48cea4e1c4 added branch delete functionallity 2018-08-10 16:46:03 +02:00
Jesse Duffield 7aa884ed8f step one on restoring multiline commits 2018-08-10 23:36:54 +10:00
Glenn Vriesman 7eb673e574 Feature: Added repository name to status 2018-08-10 15:10:15 +02:00
Jesse Duffield f20121cb0b add FIXME note about trimming the trailing newline upon confirming in a prompt panel 2018-08-10 23:08:03 +10:00
Jesse Duffield aa4160d57a merge feature/clearing-commit-panel into master 2018-08-10 22:49:54 +10:00
Jesse Duffield 8bc6832546 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-10 22:46:24 +10:00
Jesse Duffield 4853d186ee add git plumbing to Gopkg.lock 2018-08-10 22:46:04 +10:00
Jesse Duffield c3611df8d8 Merge pull request #112 from jesseduffield/feature/case-insensitive-branch-name-comparisons
101: Compare branches for name equality regardless of case
2018-08-10 22:26:44 +10:00
Jesse Duffield 59650cff26 compare branches for name equality regardless of case 2018-08-10 22:24:10 +10:00
Jesse Duffield f9abcdb159 Merge branch 'feature/branch-refactor' 2018-08-10 22:13:48 +10:00
Jesse Duffield 28505dddaf move color functions into utils 2018-08-10 22:09:10 +10:00
Jesse Duffield 95b7c1d0a4 revert to using the direct git command for getting the current branch because it breaks if you've just done a git init 2018-08-10 22:08:12 +10:00
Jesse Duffield eb9f01ecfa move withPadding into utils file 2018-08-10 21:51:21 +10:00
Jesse Duffield a8c6f31bc6 Merge pull request #107 from antham/master
Apply gofmt
2018-08-10 21:42:50 +10:00
Jesse Duffield 1fded005c4 revert to using default border color 2018-08-10 21:40:21 +10:00
Jesse Duffield c470c1f575 keep asterisk at the checked out branch 2018-08-10 21:38:51 +10:00
Jesse Duffield d08241b2ea Obtain branches in a more robust way. Begin refactor work on gitcommands 2018-08-10 21:34:17 +10:00
Anthony HAMON de7ab80539 apply gofmt -s -w 2018-08-10 09:54:21 +02:00
Ching-Hsuan Yen d3abd9eab1 Add fixup option into commits panel 2018-08-10 13:44:42 +08:00
Jesse Duffield 3f89b5bf71 Merge pull request #105 from jesseduffield/feature/add-go-git
Explicitly add go-git dependency
2018-08-10 11:51:51 +10:00
Jesse Duffield 87872f5514 explicitly add go-git dependency 2018-08-10 11:33:49 +10:00
maxice8 bf9a53fada README.md: Add Void Linux instructions 2018-08-09 19:39:18 -03:00
frealgagu 3adf5368dd Adding arch linux packages to README.md 2018-08-09 09:13:24 -05:00
Jesse Duffield ed6f21ee74 bump version to v0.1.48 2018-08-09 23:35:06 +10:00
Jesse Duffield 75a186614a add scroll keybinding to displayed files panel options 2018-08-09 23:34:50 +10:00
Jesse Duffield 18aa5b1bbe bump version to v0.1.47 2018-08-09 23:34:16 +10:00
Jesse Duffield 89209d1253 bump version to v0.1.46 2018-08-09 23:27:11 +10:00
Jesse Duffield bcad80250a add basic vim keybindings
add keybinding for the tab key to begin a newline when writing a commit message
it would have been shift+enter but currently that is not supported by gocui
2018-08-09 23:26:31 +10:00
Jesse Duffield 44eaccfd14 switch to using the log package rather than directly writing to file 2018-08-09 20:29:58 +10:00
Jesse Duffield 9537645d0c dynamic width for confirmation panel and better handling of a squashed terminal 2018-08-09 19:49:36 +10:00
Jesse Duffield d08e3a55a1 WIP hard reset 2018-08-09 19:33:35 +10:00
Jesse Duffield 2cd0bd8125 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-09 19:02:19 +10:00
Jesse Duffield cc31cb1abe remove double quote escapes in commit message for auto version bumper 2018-08-09 19:02:16 +10:00
Jesse Duffield a56643fe64 refactor repeater functions and refresh file panel every ten seconds 2018-08-09 19:01:42 +10:00
Jesse Duffield 2386283e45 Update README.md 2018-08-09 16:07:25 +10:00
Jesse Duffield 58977ed7f3 remove the dist folder after goreleaser runs 2018-08-09 15:47:55 +10:00
Jesse Duffield a068548bcb remove speed monitoring 2018-08-09 15:44:28 +10:00
Jesse Duffield b2f8b8b345 "bump version to v0.1.45" 2018-08-09 15:24:39 +10:00
Jesse Duffield 5f70b2d9cd throw error when git username not configured 2018-08-09 15:24:12 +10:00
Jesse Duffield f33b2b2277 "bump version to v0.1.44" 2018-08-09 14:46:10 +10:00
Jesse Duffield dbf65a422a bump dependencies 2018-08-09 14:41:58 +10:00
Jesse Duffield ace8544512 create log if debugging and the file doesn't already exist 2018-08-09 14:36:26 +10:00
Jesse Duffield 4832d365f1 use go-git for commits 2018-08-09 14:33:51 +10:00
Jesse Duffield bebe94b4b3 don't call projectPath until we know we're in debug mode 2018-08-09 13:37:48 +10:00
Jesse Duffield 750445dc8b use platform agnostic filepaths 2018-08-09 13:29:25 +10:00
Jesse Duffield 1f5f80b1bf platform independent path reading 2018-08-09 13:21:30 +10:00
Jesse Duffield 5cc34e7801 factor out platform specific logic into a struct on state 2018-08-09 13:14:24 +10:00
Jesse Duffield ce8884f509 "bump version to v0.1.43" 2018-08-09 12:56:11 +10:00
Jesse Duffield 481a05f116 check for VERSION file in project directory rather than current directory 2018-08-09 12:55:41 +10:00
Jesse Duffield 6e8abbcdda use fallback file VERSION 2018-08-09 12:25:32 +10:00
Jesse Duffield 273eb6244b "bump version to v0.1.42" 2018-08-09 12:10:33 +10:00
Jesse Duffield 467741fa54 add basic script to bump patch number and call goreleaser 2018-08-09 12:10:22 +10:00
Jesse Duffield a00bbf709f "bump version to v0.1.41" 2018-08-09 12:09:30 +10:00
Jesse Duffield b90e66dca1 "bump version to v0.1.40" 2018-08-09 12:02:37 +10:00
Jesse Duffield 77eea90b0b "bump version to v0.1.39" 2018-08-09 12:00:23 +10:00
Jesse Duffield 79b012990b Update README.md 2018-08-09 11:07:41 +10:00
Jesse Duffield 45c0b9404a use zip for windows binaries 2018-08-09 11:05:10 +10:00
Jesse Duffield 50924f31b0 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-09 11:00:57 +10:00
Jesse Duffield 705d273ad3 test comment to see if goreleaser only releases on new commits 2018-08-09 11:00:50 +10:00
Jesse Duffield 30c6fc2300 Update README.md 2018-08-09 10:48:57 +10:00
Jesse Duffield 16b202f227 Update README.md 2018-08-09 10:46:57 +10:00
Jesse Duffield 7c1dbb7c66 Update README.md 2018-08-09 10:46:27 +10:00
Jesse Duffield 41152881db Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-09 10:32:18 +10:00
Jesse Duffield d33fff54a3 point to homebrew repo 2018-08-09 10:32:12 +10:00
Jesse Duffield 3bf621de65 Update README.md 2018-08-09 10:21:45 +10:00
Jesse Duffield 0c84055abd show error on git add --patching untracked file 2018-08-09 09:33:18 +10:00
Jesse Duffield 5d9df3ca07 Merge pull request #86 from dawidd6/patch-1
Precise supported ubuntu releases by ppa
2018-08-09 09:25:21 +10:00
Dawid Dziurla 6581bec1ce precise supported ubuntu releases by ppa 2018-08-08 23:21:41 +02:00
Jesse Duffield ce3f81a2d3 remove github token 2018-08-09 00:26:32 +10:00
Jesse Duffield bc479a9bf5 correct repo name 2018-08-08 23:29:59 +10:00
Jesse Duffield 83a9a6d1f5 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-08 23:28:59 +10:00
Jesse Duffield ca0b3debe9 attempt brew formula 2018-08-08 23:28:52 +10:00
Jesse Duffield 84a2b1ceb9 Update README.md 2018-08-08 23:21:35 +10:00
Jesse Duffield 5951811a8b fix releaser 2018-08-08 23:16:52 +10:00
Jesse Duffield 968f3b2c1c revert to stock standard goreleaser yml 2018-08-08 23:13:26 +10:00
Jesse Duffield aacbb72e6c use env github token 2018-08-08 23:09:39 +10:00
Jesse Duffield 48ab294922 remove newline in github token 2018-08-08 23:06:50 +10:00
Jesse Duffield 555996642d try just pointing at the directory 2018-08-08 23:04:51 +10:00
Jesse Duffield aad4269128 fix yml 2018-08-08 23:03:10 +10:00
Jesse Duffield b3fbe8453f fix yml format 2018-08-08 23:00:27 +10:00
Jesse Duffield ffac0e6420 Merge branch 'feature/gorelease' 2018-08-08 22:54:49 +10:00
Jesse Duffield 7371765d47 bring back white borders for everybody 2018-08-08 22:53:24 +10:00
Jesse Duffield 7f75808499 cleanup for goreleaser 2018-08-08 22:51:18 +10:00
Jesse Duffield 778cb14dc4 update to use goreleaser ldflags 2018-08-08 22:48:37 +10:00
Jesse Duffield 00c679a3f0 swap travis for goreleaser 2018-08-08 22:40:01 +10:00
Jesse Duffield d9ec6f9890 switch border color back to black for osx 2018-08-08 21:53:28 +10:00
Jesse Duffield 9858bfe4c3 use brighter panels for linux 2018-08-08 21:46:56 +10:00
Jesse Duffield feada164d0 use file glob 2018-08-08 21:22:08 +10:00
Jesse Duffield a1706ef2ee remove 1.7 because I'm not using it 2018-08-08 21:09:51 +10:00
Jesse Duffield 1bd3aa9708 remove version number from filename and use regex to pick files to deploy 2018-08-08 21:08:05 +10:00
Jesse Duffield d0aaf94068 use default platforms 2018-08-08 21:04:04 +10:00
Jesse Duffield 8054d85782 add more archs to travis.yml 2018-08-08 20:59:32 +10:00
Jesse Duffield 31a8be5f32 update keybindings 2018-08-08 20:53:14 +10:00
Jesse Duffield ca04655a09 merge master/better-file-opening into master 2018-08-08 20:50:45 +10:00
Jesse Duffield 4281cc2884 add git config check and editing ability 2018-08-08 20:45:12 +10:00
Jesse Duffield 8013f18177 add test script that reads user input for subprocess testing 2018-08-08 20:44:06 +10:00
Jesse Duffield c965333756 "opening and editing" 2018-08-08 19:46:21 +10:00
Jesse Duffield 54408a912c merge moving keybindings to its own file 2018-08-08 19:24:33 +10:00
Jesse Duffield 3839719154 "move keybindings into its own file" 2018-08-08 19:18:41 +10:00
Jesse Duffield e8c4bf20f6 merge master 2018-08-08 19:13:13 +10:00
Jesse Duffield fbadbdd771 version with tag 2018-08-08 18:57:27 +10:00
Jesse Duffield c6aee678c0 bump dep 2018-08-08 18:57:03 +10:00
Jesse Duffield c4c27262f2 allow go 1.7 to fail 2018-08-08 18:02:18 +10:00
Jesse Duffield a253b0b897 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-08 08:59:09 +10:00
Jesse Duffield 5ca47c3f47 merge master 2018-08-08 08:58:24 +10:00
Jesse Duffield 456c593c72 Update README.md 2018-08-08 08:49:37 +10:00
Jesse Duffield 3b264806ef add version number 2018-08-08 08:32:52 +10:00
Jesse Duffield 92e75d4602 "step one towards dealing with gpgsign" 2018-08-08 08:24:24 +10:00
Jesse Duffield 7add598235 give everybody permission 2018-08-08 08:13:40 +10:00
Jesse Duffield 2853aba951 appending version number to binaries 2018-08-08 08:07:43 +10:00
Jesse Duffield 8cc444182f make binaries executable 2018-08-08 08:02:33 +10:00
Jesse Duffield 2a25ce014b use correct filenames 2018-08-08 07:56:55 +10:00
Jesse Duffield 411c02324f use gox default output 2018-08-08 07:54:46 +10:00
Jesse Duffield 2f50cbf2b8 use gox default output 2018-08-08 07:54:11 +10:00
Jesse Duffield 417cb97dc6 add file to command 2018-08-08 07:49:45 +10:00
Jesse Duffield fb5d25c9e9 Merge branch 'master' into feature/better-file-opening 2018-08-08 07:41:55 +10:00
Jesse Duffield f580572e70 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-08 07:40:04 +10:00
Jesse Duffield ba30e9e450 log some travis ci stuff 2018-08-08 07:39:58 +10:00
Nicolas Borboën 30d79bfa2c Merge remote-tracking branch 'upstream/master' into ponsfrilus/cli-version 2018-08-07 16:17:01 +02:00
Nicolas Borboën 4d9d2b134f Add lazygit --v version
* Recover Rev and Build Date from build args
* Moved `debuggingPointer` and `versionFlag` to `var()`
* Print version and exit in case of `-v` or `--v`
2018-08-07 16:15:23 +02:00
Nicolas Borboën 6cb0a14f33 Add build date to build cmd 2018-08-07 16:11:53 +02:00
Jesse Duffield 51d3e679bf Merge pull request #66 from ponsfrilus/patch-1
[fix] link to code of conduct
2018-08-07 23:21:22 +10:00
Jesse Duffield bab884f1df nonrelative path to binaries 2018-08-07 23:18:18 +10:00
Jesse Duffield 1730089b09 try master branch for dep 2018-08-07 23:04:55 +10:00
Nicolas Borboën 8c823965ab [fix] link to code of conduct 2018-08-07 14:59:22 +02:00
Jesse Duffield aa6a0bd43b Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-07 22:53:38 +10:00
Jesse Duffield d781a8e650 if you had one shot 2018-08-07 22:53:29 +10:00
Jesse Duffield 4528cf95b9 fix wrapping 2018-08-07 22:48:40 +10:00
Jesse Duffield dd6cdc02f0 Merge pull request #65 from ponsfrilus/ponsfrilus/coc-cg
Code of Conduct + Contributing guide proposal
2018-08-07 22:46:43 +10:00
Nicolas Borboën 2311675d08 It appears that markdown files are better handeled by GitHub with extensions. 2018-08-07 14:38:58 +02:00
Nicolas Borboën cda365a93f Contributing guide proposal 2018-08-07 14:32:04 +02:00
Jesse Duffield b567a86ee5 another day another attempt at CI 2018-08-07 22:30:06 +10:00
Nicolas Borboën a6cb0feff1 Contributing guide added
This is a mix between
  * https://gist.github.com/PurpleBooth/b24679402957c63ec426
  *
https://github.com/thoughtbot/factory_bot_rails/blob/master/CONTRIBUTING.md
  * https://gist.github.com/briandk/3d2e8b3ec8daf5a27a62
  * https://github.com/nayafia/contributing-template
2018-08-07 14:28:52 +02:00
Jesse Duffield af766c848c reverting to 386 because it worked before 2018-08-07 22:27:33 +10:00
Nicolas Borboën ade0dc447e Code of conduct added
* Based on contributor-covenant.org
2018-08-07 14:27:11 +02:00
Jesse Duffield 8aca30ee4c Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-07 22:26:12 +10:00
Jesse Duffield d5a73c0166 experimenting 2018-08-07 22:26:08 +10:00
Jesse Duffield 53044e20c9 Merge pull request #63 from dawidd6/ubuntu
Set minimal ubuntu version supported by ppa
2018-08-07 22:20:45 +10:00
Jesse Duffield 59ea1491db back to amd64 2018-08-07 22:20:04 +10:00
Jesse Duffield 69f47fddc4 back to go 1.7 2018-08-07 22:17:42 +10:00
Jesse Duffield 75e1a2d62f support other go again 2018-08-07 22:14:30 +10:00
Jesse Duffield b715236c0a get gox 2018-08-07 22:13:42 +10:00
Jesse Duffield 4e8f909141 juse use go 1.7 2018-08-07 22:05:23 +10:00
Jesse Duffield 3c82edb301 comment out failing build steps 2018-08-07 22:02:34 +10:00
Jesse Duffield 3dafb78b1d change liniux platform 2018-08-07 21:58:10 +10:00
Jesse Duffield abfbd59d67 try with sudo 2018-08-07 21:55:55 +10:00
Jesse Duffield fbd377606a remove older go versions 2018-08-07 21:53:31 +10:00
Jesse Duffield ee7fad1433 update travis 2018-08-07 21:44:26 +10:00
Dawid Dziurla 6925ceeb6e set minimal ubuntu version supported by ppa 2018-08-07 13:42:39 +02:00
Jesse Duffield 4d425de5d0 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-08-07 21:35:30 +10:00
Jesse Duffield 19af3f967a Merge pull request #62 from ncubrian/hotfix/ignore_crash
fix: use createErrorPanel in handleIgnoreFile when returning No changed files
2018-08-07 21:34:37 +10:00
Jesse Duffield 138a5d86ed attempt at automatic binary releases 2018-08-07 21:32:51 +10:00
Jesse Duffield acae855ace initial travis config 2018-08-07 21:15:06 +10:00
Rogers 50e4f74350 fix: use createErrorPanel in handleIgnoreFile 2018-08-07 19:04:41 +08:00
Jesse Duffield 5a624764a8 support patched adding 2018-08-07 19:50:35 +10:00
Jesse Duffield 790d5a1745 Merge pull request #60 from jesseduffield/feature/get-branches-refactor
Refactor getting branches
2018-08-07 19:35:49 +10:00
Jesse Duffield c81922f8cf rename recency to prefix 2018-08-07 19:32:25 +10:00
Jesse Duffield 232e1c74e4 refactor into smaller functions 2018-08-07 19:31:19 +10:00
Jesse Duffield 2b37c9b19c ensure current branch is on top of the branch list 2018-08-07 19:26:47 +10:00
Jesse Duffield c8bacb4186 refactor 2018-08-07 19:23:02 +10:00
Jesse Duffield a1aa031252 revert to using bash instead of sh 2018-08-07 19:20:27 +10:00
Jesse Duffield c4f3637e21 better function name 2018-08-07 19:16:54 +10:00
Jesse Duffield 6cf6fecb64 refactor getting branches 2018-08-07 19:13:41 +10:00
Jesse Duffield b541987007 fixup 2018-08-07 18:37:48 +10:00
Jesse Duffield 2d4801c39d merge updated keybinding structure 2018-08-07 18:14:49 +10:00
Jesse Duffield 7fe54e889d merge master 2018-08-07 18:13:45 +10:00
Jesse Duffield f6a9c727fa run subprocess cleanly 2018-08-07 18:05:43 +10:00
Jesse Duffield f8ca0ddcad Update README.md 2018-08-07 17:55:02 +10:00
Jesse Duffield 138f40d7ae Merge branch 'master' into feature/use-dep 2018-08-07 17:12:37 +10:00
Jesse Duffield b80e8111c6 Update README.md 2018-08-07 15:50:56 +10:00
Jesse Duffield 6df4a3ff41 merge windows support hotfix 2018-08-07 15:45:04 +10:00
Jesse Duffield a70753364c platform specific shell usage 2018-08-07 15:21:50 +10:00
Jesse Duffield 948f6a1f7a return on error when merging branches 2018-08-07 14:43:43 +10:00
Jesse Duffield 46fb4c5f0a swap out bash command for a git one 2018-08-07 14:23:10 +10:00
Jesse Duffield e23ed80eaa use git branch when merging branches 2018-08-07 14:10:15 +10:00
Jesse Duffield ab03902d08 return on error when merging branches 2018-08-07 14:08:56 +10:00
Jesse Duffield 9bfaa9f62c Merge branch 'master' into hotfix/windows-support 2018-08-07 14:05:08 +10:00
Jesse Duffield 28caaf6f1c invert platform check 2018-08-07 14:01:41 +10:00
Jesse Duffield 384d2e3c83 use sh instead of bash 2018-08-07 13:44:00 +10:00
Jesse Duffield a4f4a16237 fix panel outlines for windows 2018-08-07 13:31:45 +10:00
Jesse Duffield a4a975a69c don't panic on no files when pressing d 2018-08-07 12:51:03 +10:00
Jesse Duffield 6985e52949 handle error from git log that arises from lack of tracking 2018-08-07 12:49:31 +10:00
Jesse Duffield eabf07248a Merge branch 'master' into feature/use-dep 2018-08-07 12:31:51 +10:00
Jesse Duffield ba9485ae57 support more merge conflict headers 2018-08-07 10:41:14 +10:00
Jesse Duffield 236eabb811 support Updated upstream message in merge panel 2018-08-07 10:39:49 +10:00
Jesse Duffield f11edda6a2 limit commits in graph output for performance 2018-08-07 10:09:29 +10:00
Jesse Duffield 7fb77418cc refactor keybindings 2018-08-07 09:54:07 +10:00
Jesse Duffield dcf87e2765 Merge pull request #50 from robthr/patch-1
Added macOS installation note (from #43)
2018-08-07 09:38:22 +10:00
Malcolm Robinson 90e488d5a4 Added macOS installation note (from #43) 2018-08-07 09:34:45 +10:00
Jesse Duffield 31f6ef1c29 Merge pull request #40 from jukefr/patch-1
add p (pull) and P (push)
2018-08-07 08:29:03 +10:00
Jesse Duffield c6ab935779 make push keybinding more explicit 2018-08-07 08:27:08 +10:00
Jesse Duffield 9c2e1dfc6e Merge pull request #47 from karlmutch/master
Modified reference to HEAD in one case, others appear to exist for ra…
2018-08-07 08:26:15 +10:00
Karl Mutch 16e3d5f092 Modified reference to HEAD in one case, others appear to exist for ranges but I am not familiar enough with these. 2018-08-06 13:30:21 -07:00
Kevin Jullien 7dc4878e0b add p (pull) and P (push) 2018-08-06 17:18:03 +02:00
Jesse Duffield 694b192b74 fix incorrect checked out branch display 2018-08-07 00:41:59 +10:00
Jesse Duffield 9e5c04d57d Update README.md 2018-08-07 00:08:54 +10:00
Jesse Duffield 91ecf1e499 Update README.md 2018-08-07 00:07:42 +10:00
Jesse Duffield 7e5d7bfe38 fix windows bash conditional error 2018-08-06 23:53:28 +10:00
Jesse Duffield 9067c3be3e handling file edit 2018-08-06 23:29:00 +10:00
Jesse Duffield fc2e3a5316 Merge pull request #36 from tomyfalgui/patch-1
Swapped incorrect cli keywords
2018-08-06 23:03:37 +10:00
Tomas Alejandro V. Falgui III 17cf4cec31 Switched incorrect cli keywords 2018-08-06 20:53:17 +08:00
Jesse Duffield 69378b8ff4 add documentation comment about osx scrolling 2018-08-06 21:47:46 +10:00
Jesse Duffield fbc09e2093 add keybindings doc to readme 2018-08-06 21:35:30 +10:00
Jesse Duffield afc3d4a997 add keybindings doc 2018-08-06 21:32:43 +10:00
Jesse Duffield caea649733 remove old comment 2018-08-06 21:14:01 +10:00
Jesse Duffield a02d3a0c4e show graph when selecting branch in branch panel 2018-08-06 21:13:52 +10:00
Jesse Duffield 3ee9687540 Merge pull request #20 from dawidd6/master
Add installation instructions for ubuntu
2018-08-06 20:38:35 +10:00
Jesse Duffield 15f982daae Merge branch 'master' into feature/use-dep 2018-08-06 19:11:53 +10:00
Jesse Duffield cf73d4f558 standardise error handling of command functions 2018-08-06 19:01:27 +10:00
Jesse Duffield b1918f2f68 no panic on git commit error 2018-08-06 18:55:08 +10:00
Jesse Duffield 0e0acc90e1 Merge pull request #29 from antham/master
Add goreportcard
2018-08-06 18:35:54 +10:00
Jesse Duffield f08ffef7f3 Merge pull request #31 from ponsfrilus/ponsfrilus-patch-1
Update README.md
2018-08-06 18:30:47 +10:00
Dawid Dziurla c38dc16def add instalation instructions for ubuntu 2018-08-06 10:17:05 +02:00
Nicolas Borboën 61815013cb Update README.md
* punctuation added where missing;
* capitalized first letter of sentences;
* PR/Issue links.
2018-08-06 09:05:16 +02:00
Jesse Duffield e5f0a89bf1 better contrast for bottom options banner 2018-08-06 16:31:24 +10:00
Jesse Duffield b1e6735d8d better contrast 2018-08-06 16:11:29 +10:00
Anthony HAMON 6b5c08d449 add goreportcard 2018-08-06 07:42:41 +02:00
Anthony HAMON 4836e6c906 remove useless else 2018-08-06 07:41:59 +02:00
Anthony HAMON 684e8b2e80 remove useless condition 2018-08-06 07:41:29 +02:00
Anthony HAMON 7b7621c18c apply gofmt -s -w 2018-08-06 07:37:14 +02:00
Jesse Duffield 9a3b565806 add vscode keybinding 2018-08-06 13:49:15 +10:00
Jesse Duffield e8aba2e517 prune unnecessary stuff 2018-08-06 12:24:01 +10:00
Jesse Duffield da227003c7 use dep 2018-08-06 00:38:38 +10:00
Jesse Duffield 6126ddd373 fix spacing 2018-08-06 00:04:11 +10:00
Jesse Duffield 59885e45df deal with month time unit in reflog output 2018-08-06 00:02:41 +10:00
Jesse Duffield 6e585c54a2 controlling overlapping edges with a single flag 2018-08-05 22:18:59 +10:00
Jesse Duffield ac8264e9c2 move panelspacing variable into a constant 2018-08-05 22:02:19 +10:00
Jesse Duffield 1c99aaff43 basic support for overlapping panels 2018-08-05 22:00:02 +10:00
Jesse Duffield 0df11e27fa add refresh option to files panel 2018-08-05 21:28:34 +10:00
Jesse Duffield 0aa587f55a return gracefully if there are no files when attempting to open one 2018-08-05 19:54:09 +10:00
Jesse Duffield 934e7a2e71 add link to go installation guide in README 2018-08-05 18:46:17 +10:00
Jesse Duffield 01540866bf handle no-file error gracefully when trying to stage 2018-08-05 18:34:50 +10:00
Jesse Duffield 8aacd6915b set upstream to origin branchname on push 2018-08-05 18:19:27 +10:00
Jesse Duffield 67e56e5fbc support carriage returns for windows machines 2018-08-05 17:13:12 +10:00
Jesse Duffield 79703c0087 Merge pull request #13 from TonyChol/patch-1
Fixed a typo in README.md
2018-08-05 16:37:12 +10:00
Zhibin Cai 74cb78cbe6 Fixed a typo in README.md
Fixed a typo about zsh alias: `echo "alias lg='lazygit'" >> ~/.zshrc`
2018-08-04 23:21:06 -07:00
Jesse Duffield 3c0eeba187 Update README.md 2018-08-05 14:13:21 +10:00
Jesse Duffield e21f840350 fix readme 2018-08-05 13:03:09 +10:00
Jesse Duffield d780549cea Merge pull request #2 from robertely/patch-1
Correct gocui link
2018-08-05 12:45:51 +10:00
Jesse Duffield 12f475544e Create LICENSE 2018-08-05 12:32:37 +10:00
Robert Ely b422c5cc86 Correct gocui link 2018-08-04 19:40:04 -06:00
Jesse Duffield 3790ef3e46 add tab keybinding back in 2018-07-29 10:46:37 +10:00
Jesse Duffield 5c271b8a70 add navigate option to every panels options 2018-07-29 10:40:54 +10:00
Jesse Duffield 8b0db89edb Update README.md 2018-07-29 10:30:40 +10:00
Jesse Duffield 2dfef09e55 show whitespace in diffs again 2018-07-28 16:52:20 +10:00
Jesse Duffield d6dbd46793 fix view cycling 2018-07-22 12:58:39 +10:00
Jesse Duffield 001ea1002d update options 2018-07-22 12:58:09 +10:00
Jesse Duffield 5dbe262d2d moving loader and adding previous view function (unfinished) 2018-07-22 12:07:36 +10:00
Jesse Duffield f0447be989 removing test files 2018-07-21 18:55:19 +10:00
Jesse Duffield d832eab20c loading animation for confirmation view 2018-07-21 18:37:00 +10:00
Jesse Duffield fab194e923 better handling of merge conflicts 2018-07-21 17:48:27 +10:00
Jesse Duffield a47c889cbb merge with develop 2018-07-21 16:06:38 +10:00
Jesse Duffield 61dcbb456d updating doc 2018-07-21 16:00:05 +10:00
Jesse Duffield 37d9ed6712 test script to make repo with a merge conflict 2018-07-21 15:57:54 +10:00
Jesse Duffield e059a87ae2 refreshing files if there's an error while pulling because chances are it's a merge conflict 2018-07-21 15:57:23 +10:00
Jesse Duffield 087cc7362a merge develop 2018-07-21 15:55:47 +10:00
Jesse Duffield 16df4786c0 fix up code that was used to test this very application (yes I'm ashamed) 2018-07-21 15:53:52 +10:00
Jesse Duffield dea751280e better handling of branches and untracked files 2018-07-21 15:51:18 +10:00
Jesse Duffield bcdfe242ac Update README.md 2018-06-10 12:56:38 +10:00
Jesse Duffield 0a1c4b7cbe Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-06-10 12:55:26 +10:00
Jesse Duffield 42cb8e4abf remove y/n options from prompt 2018-06-10 12:55:15 +10:00
Jesse Duffield e80be83065 Update README.md 2018-06-10 12:52:55 +10:00
Jesse Duffield b2e0bb49fb Update README.md 2018-06-10 12:49:12 +10:00
Jesse Duffield 36df4c825f Update README.md 2018-06-10 12:27:22 +10:00
Jesse Duffield 56bf7cfee8 Update README.md 2018-06-10 12:11:40 +10:00
Jesse Duffield 76d4c62995 Update README.md 2018-06-10 11:53:16 +10:00
Jesse Duffield 4a483c112e better confirmation panel messages 2018-06-10 11:52:30 +10:00
Jesse Duffield 211715fa77 merge with feature branch 2018-06-10 11:48:22 +10:00
Jesse Duffield 5a143ea500 this will cause a conflict 2018-06-10 11:48:07 +10:00
Jesse Duffield 5fd3d11789 Merge branch 'master' of https://github.com/jesseduffield/lazygit 2018-06-10 11:37:24 +10:00
Jesse Duffield 691972b544 scroll to merge conflict 2018-06-10 11:37:10 +10:00
Jesse Duffield 21dd06989d add handler for refreshing files 2018-06-10 11:36:47 +10:00
Jesse Duffield 43f0cf42e6 use log instead of diff for now 2018-06-10 11:36:27 +10:00
Jesse Duffield 08174ca848 Update README.md 2018-06-10 11:35:35 +10:00
Jesse Duffield 5e3481ca58 Update README.md 2018-06-10 11:16:47 +10:00
Jesse Duffield dda94949d4 Update README.md 2018-06-10 00:49:13 +10:00
Jesse Duffield 7f01bfa24e Update README.md 2018-06-10 00:43:11 +10:00
Jesse Duffield 4750aacb9b Update README.md 2018-06-10 00:40:54 +10:00
Jesse Duffield ea51578f5c Update README.md 2018-06-10 00:40:33 +10:00
Jesse Duffield 57611d355c Update README.md 2018-06-10 00:37:03 +10:00
Jesse Duffield 595959db52 Update README.md 2018-06-10 00:10:28 +10:00
Jesse Duffield 129be0b364 Update README.md 2018-06-10 00:07:25 +10:00
Jesse Duffield 30ce316209 Create README.md 2018-06-10 00:06:06 +10:00
Jesse Duffield 027ea74ca9 merge with example feature branch 2018-06-09 22:49:40 +10:00
Jesse Duffield 37b5bc7cb3 mess with merge panel 2018-06-09 22:47:54 +10:00
Jesse Duffield 336a494862 mess with merge panel values 2018-06-09 22:44:30 +10:00
Jesse Duffield 6167eb5cc0 dealing with no checkouts in reflog and checking out new branches 2018-06-09 19:30:59 +10:00
Jesse Duffield d413d4319f update gitignore 2018-06-09 19:06:52 +10:00
Jesse Duffield 7653ff9a24 add support for merging 2018-06-09 19:06:33 +10:00
Jesse Duffield 4f6ae62e79 moving view helpers out of gui file 2018-06-06 12:17:49 +10:00
Jesse Duffield ceeca40fe5 remove log of directory 2018-06-05 19:32:27 +10:00
Jesse Duffield 1378143889 move log commands into main file 2018-06-05 19:32:03 +10:00
Jesse Duffield 0d2076c57c generalised logs 2018-06-05 19:30:55 +10:00
Jesse Duffield 68a23f14e8 remove another test file 2018-06-05 19:03:54 +10:00
Jesse Duffield 0715487730 remove get_branches bash script 2018-06-05 19:02:20 +10:00
Jesse Duffield dd511acbdd remove test files 2018-06-05 19:02:02 +10:00
Jesse Duffield 9cd78f719e remove comments 2018-06-05 18:54:07 +10:00
Jesse Duffield 9c018c6138 factoring out error panel creation 2018-06-05 18:49:10 +10:00
Jesse Duffield d1ead5b0cf add stash panel 2018-06-05 18:48:46 +10:00
Jesse Duffield 164ac72c5a generalise commit panel into confirmation panel 2018-06-05 18:47:57 +10:00
Jesse Duffield d89cab146a Switch to forked repo of gocui 2018-06-05 18:47:31 +10:00
Jesse Duffield f2bb6128a9 Merge branch 'hotfix/test_hotfix' 2018-06-02 13:52:52 +10:00
Jesse Duffield 80bcc7c16e More stuff 2018-06-02 13:51:03 +10:00
Jesse Duffield a0c8fc8899 loading file diff after refreshing files incase cursor is now at a different file 2018-06-02 09:06:02 +10:00
Jesse Duffield 7cdcef8c93 picking up new files upon file refresh 2018-06-02 09:05:20 +10:00
Jesse Duffield 5ccea4f5d9 ignore notes 2018-06-02 09:03:39 +10:00
Jesse Duffield 157278e06e stop tracking notes 2018-06-02 08:45:30 +10:00
Jesse Duffield 103a6fd219 logging durations and more stuff 2018-06-02 08:35:49 +10:00
Jesse Duffield a555a75565 clearing status before re-writing contents 2018-06-01 23:25:15 +10:00
Jesse Duffield b6eaa44cc2 more stuff 2018-06-01 23:23:31 +10:00
Jesse Duffield ec78c795dd More stuff 2018-05-27 16:32:09 +10:00
Jesse Duffield 787e5d13ed Showing modal when no files to commit 2018-05-26 17:18:00 +10:00
Jesse Duffield 843927dd26 more fixing 2018-05-26 16:08:18 +10:00
Jesse Duffield 06713f608b fixing up commit message deletion 2018-05-26 16:08:08 +10:00
Jesse Duffield 112893f73c reverting to using delete 2018-05-26 15:51:28 +10:00
Jesse Duffield 00dca6f76d sending panel to back rather than deleting 2018-05-26 15:47:22 +10:00
Jesse Duffield 10fd353a50 More stuff 2018-05-26 15:44:44 +10:00
Jesse Duffield bb12309c7c Breaking into different files 2018-05-26 13:23:39 +10:00
Jesse Duffield fe99e70983 hkghghjg 2018-05-22 10:51:54 +10:00
Jesse Duffield d62f41a4f1 TEst 2018-05-21 23:04:10 +10:00
Jesse Duffield 301d34ef3d Test 2018-05-21 23:03:06 +10:00
Jesse Duffield 796286e98e Another test 2018-05-21 23:01:41 +10:00
Jesse Duffield 7d70ed5be1 update 2018-05-21 22:34:02 +10:00
Jesse Duffield f465a5fe48 Test File 4 2018-05-21 22:29:24 +10:00
Jesse Duffield 56f9dfd856 delete testFile2 2018-05-21 22:27:35 +10:00
Jesse Duffield dfbbad5d95 Test again 2018-05-21 22:20:51 +10:00
Jesse Duffield 3cb228aac8 test message 2018-05-21 22:19:00 +10:00
Jesse Duffield c7f4af2b41 "Test" 2018-05-21 22:14:16 +10:00
Jesse Duffield 810bd54e68 "test" 2018-05-21 22:10:43 +10:00
Jesse Duffield 9fc194f0cd Test commit 2018-05-21 22:08:58 +10:00
Jesse Duffield ac1fa346ac test file 2018-05-21 20:52:48 +10:00
Jesse Duffield 30c4c6e576 another test file adding stuff 2018-05-20 19:06:04 +10:00
Jesse Duffield 6c81766972 test file on hotfix branch 2018-05-20 19:05:21 +10:00
Jesse Duffield cd5a2a3c6d test file 2018-05-20 19:03:24 +10:00
Jesse Duffield b24632caf6 branches shell script 2018-05-20 19:00:34 +10:00
Jesse Duffield 4b511863f9 improved UI 2018-05-19 17:04:33 +10:00
Jesse Duffield 023a39a903 initial commit 2018-05-19 11:16:34 +10:00
Jesse Duffield bcd5e65878 second commit 2018-05-13 14:52:20 +10:00
Jesse Duffield 4f2b1608b4 initial commit 2018-05-13 13:23:45 +10:00
1258 changed files with 400662 additions and 3140 deletions
+73
View File
@@ -0,0 +1,73 @@
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.11
working_directory: /go/src/github.com/jesseduffield/lazygit
steps:
- checkout
- run:
name: Ensure go.mod file is up to date
command: |
export GO111MODULE=on
rm go.sum
mv go.mod /tmp/
go mod init
export GO111MODULE=auto
if [ $(diff /tmp/go.mod go.mod|wc -l) -gt 0 ]; then
diff /tmp/go.mod go.mod
exit 1;
fi
- run:
name: Run gofmt -s
command: |
if [ $(find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;|wc -l) -gt 0 ]; then
find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;
exit 1;
fi
- restore_cache:
keys:
- pkg-cache-{{ checksum "Gopkg.lock" }}-v3
- run:
name: Run tests
command: |
./test.sh
- run:
name: Compile project on every platform
command: |
go get github.com/mitchellh/gox
gox -parallel 10 -os "linux freebsd netbsd windows" -osarch "darwin/i386 darwin/amd64"
- run:
name: Push on codecov result
command: |
bash <(curl -s https://codecov.io/bash)
- save_cache:
key: pkg-cache-{{ checksum "Gopkg.lock" }}-v3
paths:
- ~/.cache/go-build
release:
docker:
- image: circleci/golang:1.10
working_directory: /go/src/github.com/jesseduffield/lazygit
steps:
- checkout
- run:
name: Run gorelease
command: |
curl -sL https://git.io/goreleaser | bash
workflows:
version: 2
build:
jobs:
- build
release:
jobs:
- release:
filters:
tags:
only: /v[0-9]+(\.[0-9]+)*/
branches:
ignore: /.*/
+29
View File
@@ -0,0 +1,29 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows]
- Lazygit Version [e.g. v0.1.45]
- The last commit id if you built project from sources (run : ```git-rev parse HEAD```)
**Additional context**
Add any other context about the problem here.
+17
View File
@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+26
View File
@@ -0,0 +1,26 @@
# Please do not add personal files
# Logs
*.log
# Hidden
.*
# TODO
TODO.*
# Notes
*.notes
# Tests
test/repos/repo
coverage.txt
# Binaries
lazygit
# Exceptions
!.gitignore
!.goreleaser.yml
!.circleci/
!.github/
+64
View File
@@ -0,0 +1,64 @@
# This is an example goreleaser.yaml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
builds:
- env:
- CGO_ENABLED=0
goos:
- freebsd
- windows
- darwin
- linux
goarch:
- amd64
- arm
- arm64
- 386
# Default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}`.
ldflags:
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.buildSource=binaryRelease
archive:
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: 32-bit
amd64: x86_64
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: '{{ .Tag }}-next'
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- '^bump'
brew:
# Reporitory to push the tap to.
github:
owner: jesseduffield
name: homebrew-lazygit
# Your app's homepage.
# Default is empty.
homepage: 'https://github.com/jesseduffield/lazygit/'
# Your app's description.
# Default is empty.
description: 'A simple terminal UI for git commands, written in Go'
# # Packages your package depends on.
# dependencies:
# - git
# - zsh
# # Packages that conflict with your package.
# conflicts:
# - svn
# - bash
# test comment to see if goreleaser only releases on new commits
+74
View File
@@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the [project leader](https://github.com/jesseduffield).
All complaints will be reviewed and investigated and will result in a response that
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
+35
View File
@@ -0,0 +1,35 @@
# Contributing
♥ We love pull requests from everyone !
When contributing to this repository, please first discuss the change you wish
to make via issue, email, or any other method with the owners of this repository
before making a change.
## So all code changes happen through Pull Requests
Pull requests are the best way to propose changes to the codebase. We actively
welcome your pull requests:
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests.
3. If you've added code that need documentation, update the documentation.
4. Make sure your code follows the [effective go](https://golang.org/doc/effective_go.html) guidelines as much as possible.
5. Be sure to test your modifications.
6. Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
7. Issue that pull request!
## Code of conduct
Please note by participating in this project, you agree to abide by the [code of conduct].
[code of conduct]: https://github.com/jesseduffield/lazygit/blob/master/CODE-OF-CONDUCT.md
## Any contributions you make will be under the MIT Software License
In short, when you submit code changes, your submissions are understood to be
under the same [MIT License](http://choosealicense.com/licenses/mit/) that
covers the project. Feel free to contact the maintainers if that's a concern.
## Report bugs using Github's [issues](https://github.com/jesseduffield/lazygit/issues)
We use GitHub issues to track public bugs. Report a bug by [opening a new
issue](https://github.com/jesseduffield/lazygit/issues/new); it's that easy!
+13
View File
@@ -0,0 +1,13 @@
# run with:
# docker build -t lazygit .
# docker run -it lazygit:latest
FROM golang:alpine
RUN apk add -U git xdg-utils
ADD . /go/src/github.com/jesseduffield/lazygit
RUN go install github.com/jesseduffield/lazygit
WORKDIR /go/src/github.com/jesseduffield/lazygit
Generated
+634
View File
@@ -0,0 +1,634 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:e24ea5dbc89fbab51635ee32e5be4f61a9267cae20788efcae4c07efb4abec99"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/s3",
"service/sts",
]
pruneopts = "NUT"
revision = "4324bc9d8865bdb3e6aa86ec7772ca1272d2750e"
version = "v1.15.21"
[[projects]]
branch = "master"
digest = "1:37011b20a70e205b93ebea5287e1afa5618db54bf3998c36ff5a8e4b146a170a"
name = "github.com/bgentry/go-netrc"
packages = ["netrc"]
pruneopts = "NUT"
revision = "9fd32a8b3d3d3f9d43c341bfe098430e07609480"
[[projects]]
branch = "master"
digest = "1:cd7ba2b29e93e2a8384e813dfc80ebb0f85d9214762e6ca89bb55a58092eab87"
name = "github.com/cloudfoundry/jibber_jabber"
packages = ["."]
pruneopts = "NUT"
revision = "bcc4c8345a21301bf47c032ff42dd1aae2fe3027"
[[projects]]
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "NUT"
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:de4a74b504df31145ffa8ca0c4edbffa2f3eb7f466753962184611b618fa5981"
name = "github.com/emirpasic/gods"
packages = [
"containers",
"lists",
"lists/arraylist",
"trees",
"trees/binaryheap",
"utils",
]
pruneopts = "NUT"
revision = "f6c17b524822278a87e3b3bd809fec33b51f5b46"
version = "v1.9.0"
[[projects]]
digest = "1:ade392a843b2035effb4b4a2efa2c3bab3eb29b992e98bacf9c898b0ecb54e45"
name = "github.com/fatih/color"
packages = ["."]
pruneopts = "NUT"
revision = "5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4"
version = "v1.7.0"
[[projects]]
digest = "1:1b91ae0dc69a41d4c2ed23ea5cffb721ea63f5037ca4b81e6d6771fbb8f45129"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
pruneopts = "NUT"
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
digest = "1:74d9b0a7b4107b41e0ade759fac64502876f82d29fb23d77b3dd24b194ee3dd5"
name = "github.com/go-ini/ini"
packages = ["."]
pruneopts = "NUT"
revision = "5cf292cae48347c2490ac1a58fe36735fb78df7e"
version = "v1.38.2"
[[projects]]
branch = "master"
digest = "1:4a8ed9b8cf22bd03bee5d74179fa06a282e4a73b6de949f7a865ff56cd2537e0"
name = "github.com/golang-collections/collections"
packages = ["stack"]
pruneopts = "NUT"
revision = "604e922904d35e97f98a774db7881f049cd8d970"
[[projects]]
branch = "master"
digest = "1:a5d940c38bf56f121721bfa747c66356df387cb9d5318c570c6d4170aab62862"
name = "github.com/hashicorp/go-cleanhttp"
packages = ["."]
pruneopts = "NUT"
revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d"
[[projects]]
branch = "master"
digest = "1:b634d733abf079dc191d359e5a8d31479f1795d00e656f8a018a459571046266"
name = "github.com/hashicorp/go-getter"
packages = ["helper/url"]
pruneopts = "NUT"
revision = "4bda8fa99001c61db3cad96b421d4c12a81f256d"
[[projects]]
branch = "master"
digest = "1:fbab03227343a0285fc74a68dd2ff46cda7edecbbe5a3e98d2cecd00cc67b217"
name = "github.com/hashicorp/go-safetemp"
packages = ["."]
pruneopts = "NUT"
revision = "b1a1dbde6fdc11e3ae79efd9039009e22d4ae240"
[[projects]]
digest = "1:0b06ffe0c0764e413a6738e3f045d6bb14117359aef80a09f8c60fbff2ecad6b"
name = "github.com/hashicorp/go-version"
packages = ["."]
pruneopts = "NUT"
revision = "b5a281d3160aa11950a6182bd9a9dc2cb1e02d50"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:11c6c696067d3127ecf332b10f89394d386d9083f82baf71f40f2da31841a009"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
"json/parser",
"json/scanner",
"json/token",
]
pruneopts = "NUT"
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
[[projects]]
branch = "master"
digest = "1:d457d39e88f678ed14ac29517c3d74927a48dbc6a9f073fa241cf364a68cbe5c"
name = "github.com/heroku/rollrus"
packages = ["."]
pruneopts = "NUT"
revision = "fc0cef2ff331aebb24cd4e9ded7e20650f3d7006"
[[projects]]
branch = "master"
digest = "1:62fe3a7ea2050ecbd753a71889026f83d73329337ada66325cbafd5dea5f713d"
name = "github.com/jbenet/go-context"
packages = ["io"]
pruneopts = "NUT"
revision = "d14ea06fba99483203c19d92cfcd13ebe73135f4"
[[projects]]
branch = "master"
digest = "1:490643e333b848f3d6ab772c21082d706663dcf4a3c0fbe9a4b4ef7b205ce6c7"
name = "github.com/jesseduffield/go-getter"
packages = ["."]
pruneopts = "NUT"
revision = "906e15686e6309ff310c1c10463ab53287c3a678"
[[projects]]
branch = "master"
digest = "1:66bb9b4a5abb704642fccba52a84a7f7feef2d9623f87b700e52a6695044723f"
name = "github.com/jesseduffield/gocui"
packages = ["."]
pruneopts = "NUT"
revision = "03e26ff3f1de2c1bc2205113c3aba661312eee00"
[[projects]]
branch = "master"
digest = "1:3ab130f65766f5b7cc944d557df31c6a007ec017151705ec1e1b8719f2689021"
name = "github.com/jesseduffield/termbox-go"
packages = ["."]
pruneopts = "NUT"
revision = "1e272ff78dcb4c448870f464fda1cdcf2bf0b3dd"
[[projects]]
digest = "1:ac6d01547ec4f7f673311b4663909269bfb8249952de3279799289467837c3cc"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = "NUT"
revision = "0b12d6b5"
[[projects]]
branch = "master"
digest = "1:263f9b0a0bcbfff9d5e7d9f2aa11f53995d98214fe0fb97e429e7a5f4534a0f9"
name = "github.com/kardianos/osext"
packages = ["."]
pruneopts = "NUT"
revision = "ae77be60afb1dcacde03767a8c37337fad28ac14"
[[projects]]
digest = "1:8021af4dcbd531ae89433c8c3a6520e51064114aaf8eb1724c3cf911c497c9ba"
name = "github.com/kevinburke/ssh_config"
packages = ["."]
pruneopts = "NUT"
revision = "9fc7bb800b555d63157c65a904c86a2cc7b4e795"
version = "0.4"
[[projects]]
digest = "1:d244f8666a838fe6ad70ec8fe77f50ebc29fdc3331a2729ba5886bef8435d10d"
name = "github.com/magiconair/properties"
packages = ["."]
pruneopts = "NUT"
revision = "c2353362d570a7bfa228149c62842019201cfb71"
version = "v1.8.0"
[[projects]]
digest = "1:08c231ec84231a7e23d67e4b58f975e1423695a32467a362ee55a803f9de8061"
name = "github.com/mattn/go-colorable"
packages = ["."]
pruneopts = "NUT"
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
digest = "1:bc4f7eec3b7be8c6cb1f0af6c1e3333d5bb71072951aaaae2f05067b0803f287"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = "NUT"
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
digest = "1:cb591533458f6eb6e2c1065ff3eac6b50263d7847deb23fc9f79b25bc608970e"
name = "github.com/mattn/go-runewidth"
packages = ["."]
pruneopts = "NUT"
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
version = "v0.0.2"
[[projects]]
digest = "1:a25c9a6b41e100f4ce164db80260f2b687095ba9d8b46a1d6072d3686cc020db"
name = "github.com/mgutz/str"
packages = ["."]
pruneopts = "NUT"
revision = "968bf66e3da857419e4f6e71b2d5c9ae95682dc4"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:a4df73029d2c42fabcb6b41e327d2f87e685284ec03edf76921c267d9cfc9c23"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
pruneopts = "NUT"
revision = "58046073cbffe2f25d425fe1331102f55cf719de"
[[projects]]
branch = "master"
digest = "1:18b773b92ac82a451c1276bd2776c1e55ce057ee202691ab33c8d6690efcc048"
name = "github.com/mitchellh/go-testing-interface"
packages = ["."]
pruneopts = "NUT"
revision = "a61a99592b77c9ba629d254a693acffaeb4b7e28"
[[projects]]
branch = "master"
digest = "1:5fe20cfe4ef484c237cec9f947b2a6fa90bad4b8610fd014f0e4211e13d82d5d"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = "NUT"
revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac"
[[projects]]
digest = "1:2c34c77bf3ec848da26e48af58fc511ed52750961fa848399d122882b8890928"
name = "github.com/nicksnyder/go-i18n"
packages = [
"v2/i18n",
"v2/internal",
"v2/internal/plural",
]
pruneopts = "NUT"
revision = "a16b91a3ba80db3a2301c70d1d302d42251c9079"
version = "v2.0.0-beta.5"
[[projects]]
digest = "1:cf254277d898b713195cc6b4a3fac8bf738b9f1121625df27843b52b267eec6c"
name = "github.com/pelletier/go-buffruneio"
packages = ["."]
pruneopts = "NUT"
revision = "c37440a7cf42ac63b919c752ca73a85067e05992"
version = "v0.2.0"
[[projects]]
digest = "1:51ea800cff51752ff68e12e04106f5887b4daec6f9356721238c28019f0b42db"
name = "github.com/pelletier/go-toml"
packages = ["."]
pruneopts = "NUT"
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.2.0"
[[projects]]
digest = "1:5cf3f025cbee5951a4ee961de067c8a89fc95a5adabead774f82822efabab121"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = "NUT"
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = "NUT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:d917313f309bda80d27274d53985bc65651f81a5b66b820749ac7f8ef061fd04"
name = "github.com/sergi/go-diff"
packages = ["diffmatchpatch"]
pruneopts = "NUT"
revision = "1744e2970ca51c86172c8190fadad617561ed6e7"
version = "v1.0.0"
[[projects]]
digest = "1:41618aee8828e62dfe62d44f579c06892d0e98907d1c6d5bcd83bfe8536ec5a3"
name = "github.com/shibukawa/configdir"
packages = ["."]
pruneopts = "NUT"
revision = "e180dbdc8da04c4fa04272e875ce64949f38bd3e"
[[projects]]
digest = "1:b2339e83ce9b5c4f79405f949429a7f68a9a904fed903c672aac1e7ceb7f5f02"
name = "github.com/sirupsen/logrus"
packages = ["."]
pruneopts = "NUT"
revision = "3e01752db0189b9157070a0e1668a620f9a85da2"
version = "v1.0.6"
[[projects]]
digest = "1:330e9062b308ac597e28485699c02223bd052437a6eed32a173c9227dcb9d95a"
name = "github.com/spf13/afero"
packages = [
".",
"mem",
]
pruneopts = "NUT"
revision = "787d034dfe70e44075ccc060d346146ef53270ad"
version = "v1.1.1"
[[projects]]
digest = "1:3fa7947ca83b98ae553590d993886e845a4bff19b7b007e869c6e0dd3b9da9cd"
name = "github.com/spf13/cast"
packages = ["."]
pruneopts = "NUT"
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:f29f83301ed096daed24a90f4af591b7560cb14b9cc3e1827abbf04db7269ab5"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
pruneopts = "NUT"
revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2"
[[projects]]
digest = "1:e3707aeaccd2adc89eba6c062fec72116fe1fc1ba71097da85b4d8ae1668a675"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = "NUT"
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
version = "v1.0.2"
[[projects]]
digest = "1:454979540e2a1582f375a17c106cf4e11e3bcac4baffb4af23e515c87f87de13"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = "NUT"
revision = "907c19d40d9a6c9bb55f040ff4ae45271a4754b9"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:0e9a5ac14bcc11f205031a671b28c7e05cb88b2ebbe06f383c1ab0b2c12c7cb5"
name = "github.com/spkg/bom"
packages = ["."]
pruneopts = "NUT"
revision = "59b7046e48ad6bac800c5e1dd5142282cbfcf154"
[[projects]]
digest = "1:ccca1dcd18bc54e23b517a3c5babeff2e3924a7d8fc1932162225876cfe4bfb0"
name = "github.com/src-d/gcfg"
packages = [
".",
"scanner",
"token",
"types",
]
pruneopts = "NUT"
revision = "f187355171c936ac84a82793659ebb4936bc1c23"
version = "v1.3.0"
[[projects]]
digest = "1:bacb8b590716ab7c33f2277240972c9582d389593ee8d66fc10074e0508b8126"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = "NUT"
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.2"
[[projects]]
branch = "master"
digest = "1:e42372d3f4921ec35df07f9b23239631e9d28580f7c1edcca212bc6daddc68fe"
name = "github.com/stvp/roll"
packages = ["."]
pruneopts = "NUT"
revision = "3627a5cbeaeaa68023abd02bb8687925265f2f63"
[[projects]]
digest = "1:cd5ffc5bda4e0296ab3e4de90dbb415259c78e45e7fab13694b14cde8ab74541"
name = "github.com/tcnksm/go-gitconfig"
packages = ["."]
pruneopts = "NUT"
revision = "d154598bacbf4501c095a309753c5d4af66caa81"
version = "v0.1.2"
[[projects]]
digest = "1:07e8742c479bab0066149ad02a710024154e76874fd0a2dba002d87702725825"
name = "github.com/ulikunitz/xz"
packages = [
".",
"internal/hash",
"internal/xlog",
"lzma",
]
pruneopts = "NUT"
revision = "0c6b41e72360850ca4f98dc341fd999726ea007f"
version = "v0.5.4"
[[projects]]
digest = "1:3148cb3478c26a92b4c1a18abb9428234b281e278af6267840721a24b6cbc6a3"
name = "github.com/xanzy/ssh-agent"
packages = ["."]
pruneopts = "NUT"
revision = "640f0ab560aeb89d523bb6ac322b1244d5c3796c"
version = "v0.2.0"
[[projects]]
branch = "master"
digest = "1:dfcb1b2db354cafa48fc3cdafe4905a08bec4a9757919ab07155db0ca23855b4"
name = "golang.org/x/crypto"
packages = [
"cast5",
"curve25519",
"ed25519",
"ed25519/internal/edwards25519",
"internal/chacha20",
"internal/subtle",
"openpgp",
"openpgp/armor",
"openpgp/elgamal",
"openpgp/errors",
"openpgp/packet",
"openpgp/s2k",
"poly1305",
"ssh",
"ssh/agent",
"ssh/knownhosts",
"ssh/terminal",
]
pruneopts = "NUT"
revision = "de0752318171da717af4ce24d0a2e8626afaeb11"
[[projects]]
branch = "master"
digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70"
name = "golang.org/x/net"
packages = ["context"]
pruneopts = "NUT"
revision = "c39426892332e1bb5ec0a434a079bf82f5d30c54"
[[projects]]
branch = "master"
digest = "1:ec76a40fbfda0c329ee58f4e3b14b4279a939efce89eca020e934e2e5234eddd"
name = "golang.org/x/sys"
packages = [
"unix",
"windows",
]
pruneopts = "NUT"
revision = "98c5dad5d1a0e8a73845ecc8897d0bd56586511d"
[[projects]]
digest = "1:a95288ef1ef4dfad6cba7fe30843e1683f71bc28c912ca1ba3f6a539d44db739"
name = "golang.org/x/text"
packages = [
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"transform",
"unicode/cldr",
"unicode/norm",
]
pruneopts = "NUT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
digest = "1:47a697b155f5214ff14e68e39ce9c2e8d93e1fb035ae5ba7e247d044e0ce64e3"
name = "gopkg.in/src-d/go-billy.v4"
packages = [
".",
"helper/chroot",
"helper/polyfill",
"osfs",
"util",
]
pruneopts = "NUT"
revision = "83cf655d40b15b427014d7875d10850f96edba14"
version = "v4.2.0"
[[projects]]
digest = "1:e66078da2bd6e53c72518d7f6ae0c3c8c7f34c0df12c39435ce34a6bce165525"
name = "gopkg.in/src-d/go-git.v4"
packages = [
".",
"config",
"internal/revision",
"plumbing",
"plumbing/cache",
"plumbing/filemode",
"plumbing/format/config",
"plumbing/format/diff",
"plumbing/format/gitignore",
"plumbing/format/idxfile",
"plumbing/format/index",
"plumbing/format/objfile",
"plumbing/format/packfile",
"plumbing/format/pktline",
"plumbing/object",
"plumbing/protocol/packp",
"plumbing/protocol/packp/capability",
"plumbing/protocol/packp/sideband",
"plumbing/revlist",
"plumbing/storer",
"plumbing/transport",
"plumbing/transport/client",
"plumbing/transport/file",
"plumbing/transport/git",
"plumbing/transport/http",
"plumbing/transport/internal/common",
"plumbing/transport/server",
"plumbing/transport/ssh",
"storage",
"storage/filesystem",
"storage/filesystem/dotgit",
"storage/memory",
"utils/binary",
"utils/diff",
"utils/ioutil",
"utils/merkletrie",
"utils/merkletrie/filesystem",
"utils/merkletrie/index",
"utils/merkletrie/internal/frame",
"utils/merkletrie/noder",
]
pruneopts = "NUT"
revision = "43d17e14b714665ab5bc2ecc220b6740779d733f"
[[projects]]
digest = "1:b233ad4ec87ac916e7bf5e678e98a2cb9e8b52f6de6ad3e11834fc7a71b8e3bf"
name = "gopkg.in/warnings.v0"
packages = ["."]
pruneopts = "NUT"
revision = "ec4a0fea49c7b46c2aeb0b51aac55779c607e52b"
version = "v0.1.2"
[[projects]]
digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "NUT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/cloudfoundry/jibber_jabber",
"github.com/fatih/color",
"github.com/golang-collections/collections/stack",
"github.com/heroku/rollrus",
"github.com/jesseduffield/go-getter",
"github.com/jesseduffield/gocui",
"github.com/kardianos/osext",
"github.com/mgutz/str",
"github.com/nicksnyder/go-i18n/v2/i18n",
"github.com/shibukawa/configdir",
"github.com/sirupsen/logrus",
"github.com/spf13/viper",
"github.com/spkg/bom",
"github.com/stretchr/testify/assert",
"github.com/tcnksm/go-gitconfig",
"golang.org/x/text/language",
"gopkg.in/src-d/go-git.v4",
"gopkg.in/src-d/go-git.v4/plumbing",
"gopkg.in/yaml.v2",
]
solver-name = "gps-cdcl"
solver-version = 1
+46
View File
@@ -0,0 +1,46 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
[prune]
go-tests = true
unused-packages = true
non-go = true
[[constraint]]
name = "github.com/fatih/color"
version = "1.7.0"
[[constraint]]
branch = "master"
name = "github.com/golang-collections/collections"
[[constraint]]
branch = "master"
name = "github.com/jesseduffield/gocui"
[[constraint]]
name = "gopkg.in/src-d/go-git.v4"
revision = "43d17e14b714665ab5bc2ecc220b6740779d733f"
[[constraint]]
branch = "master"
name = "github.com/spkg/bom"
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Jesse Duffield
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+142
View File
@@ -0,0 +1,142 @@
# lazygit [![CircleCI](https://circleci.com/gh/jesseduffield/lazygit.svg?style=svg)](https://circleci.com/gh/jesseduffield/lazygit) [![codecov](https://codecov.io/gh/jesseduffield/lazygit/branch/master/graph/badge.svg)](https://codecov.io/gh/jesseduffield/lazygit) [![Go Report Card](https://goreportcard.com/badge/github.com/jesseduffield/lazygit)](https://goreportcard.com/report/github.com/jesseduffield/lazygit) [![GolangCI](https://golangci.com/badges/github.com/jesseduffield/lazygit.svg)](https://golangci.com) [![GoDoc](https://godoc.org/github.com/jesseduffield/lazygit?status.svg)](http://godoc.org/github.com/jesseduffield/lazygit) [![GitHub tag](https://img.shields.io/github/tag/jesseduffield/lazygit.svg)]()
A simple terminal UI for git commands, written in Go with the [gocui](https://github.com/jroimartin/gocui "gocui") library.
Are YOU tired of typing every git command directly into the terminal, but you're
too stubborn to use Sourcetree because you'll never forgive Atlassian for making
Jira? This is the app for you!
![Gif](/docs/resources/lazygit-example.gif)
* [Installation](https://github.com/jesseduffield/lazygit#installation)
* [Usage](https://github.com/jesseduffield/lazygit#usage),
[Keybindings](https://github.com/jesseduffield/lazygit/blob/master/docs/Keybindings.md)
* [Cool Features](https://github.com/jesseduffield/lazygit#cool-features)
* [Contributing](https://github.com/jesseduffield/lazygit#contributing)
* [Video Tutorial](https://www.youtube.com/watch?v=VDXvbHZYeKY)
* [Twitch Stream](https://www.twitch.tv/jesseduffield)
## Installation
### Homebrew
```sh
brew tap jesseduffield/lazygit
brew install lazygit
```
### Ubuntu
Packages for Ubuntu 16.04, 18.04 and 18.10 are available via [Launchpad PPA](https://launchpad.net/~lazygit-team).
**Release builds**
Built from git tags. Supposed to be more stable.
```sh
sudo add-apt-repository ppa:lazygit-team/release
sudo apt-get update
sudo apt-get install lazygit
```
**Daily builds**
Built from master branch once in 24 hours (or more sometimes).
```sh
sudo add-apt-repository ppa:lazygit-team/daily
sudo apt-get update
sudo apt-get install lazygit
```
### Void Linux
Packages for Void Linux are available in the distro repo
They follow upstream latest releases
```sh
sudo xbps-install -S lazygit
```
### Arch Linux
Packages for Arch Linux are available via AUR (Arch User Repository).
There are two packages. The stable one which is built with the latest release
and the git version which builds from the most recent commit.
* Stable: https://aur.archlinux.org/packages/lazygit/
* Development: https://aur.archlinux.org/packages/lazygit-git/
Instruction of how to install AUR content can be found here:
https://wiki.archlinux.org/index.php/Arch_User_Repository
### Binary Release (Windows/Linux/OSX)
You can download a binary release [here](https://github.com/jesseduffield/lazygit/releases).
### Go
```sh
go get github.com/jesseduffield/lazygit
```
Please note:
If you get an error claiming that lazygit cannot be found or is not defined, you
may need to add `~/go/bin` to your $PATH (MacOS/Linux), or `%HOME%\go\bin`
(Windows). Not to be mistaked for `C:\Go\bin` (which is for Go's own binaries,
not apps like Lazygit).
## Usage
Call `lazygit` in your terminal inside a git repository. If you want, you can
also add an alias for this with `echo "alias lg='lazygit'" >> ~/.zshrc` (or
whichever rc file you're using).
* Basic video tutorial [here](https://www.youtube.com/watch?v=VDXvbHZYeKY).
* List of keybindings
[here](/docs/Keybindings.md).
## Cool features
* Adding files easily
* Resolving merge conflicts
* Easily check out recent branches
* Scroll through logs/diffs of branches/commits/stash
* Quick pushing/pulling
* Squash down and rename commits
### Resolving merge conflicts
![Gif](/docs/resources/resolving-merge-conflicts.gif)
### Viewing commit diffs
![Viewing Commit Diffs](/docs/resources/viewing-commit-diffs.png)
## Milestones
- [x] Easy Installation (homebrew, release binaries)
- [ ] Configurable Keybindings
- [ ] Configurable Color Themes
- [ ] Spawning Subprocesses (help needed - have a look at https://github.com/jesseduffield/lazygit/pull/18)
- [ ] Maintainability
- [ ] Performance
- [ ] i18n
## Contributing
We love your input! Please check out the [contributing guide](CONTRIBUTING.md).
For contributor discussion about things not better discussed here in the repo, join the slack channel
[![Slack](/docs/resources/slack_rgb.png)](https://join.slack.com/t/lazygit/shared_invite/enQtNDE3MjIwNTYyMDA0LTM3Yjk3NzdiYzhhNTA1YjM4Y2M4MWNmNDBkOTI0YTE4YjQ1ZmI2YWRhZTgwNjg2YzhhYjg3NDBlMmQyMTI5N2M)
## Donate
If you would like to support the development of lazygit, please donate
[![Donate](https://d1iczxrky3cnb2.cloudfront.net/button-medium-blue.png)](https://donorbox.org/lazygit)
## Work in progress
This is still a work in progress so there's still bugs to iron out and as this
is my first project in Go the code could no doubt use an increase in quality,
but I'll be improving on it whenever I find the time. If you have any feedback
feel free to [raise an issue](https://github.com/jesseduffield/lazygit/issues)/[submit a PR](https://github.com/jesseduffield/lazygit/pulls).
## Social
If you want to see what I (Jesse) am up to in terms of development, follow me on
[twitter](https://twitter.com/DuffieldJesse) or watch me program on
[twitch](https://www.twitch.tv/jesseduffield).
## Alternatives
If you find that lazygit doesn't quite satisfy your requirements, these may be a better fit:
- [tig](https://github.com/jonas/tig)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 MiB

-243
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

-157
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 962 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

-191
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

+78
View File
@@ -0,0 +1,78 @@
# User Config:
## Default:
```
gui:
# stuff relating to the UI
scrollHeight: 2 # how many lines you scroll by
theme:
activeBorderColor:
- white
- bold
inactiveBorderColor:
- white
optionsTextColor:
- blue
commitLength:
show: true
update:
method: prompt # can be: prompt | background | never
days: 14 # how often an update is checked for
reporting: 'undetermined' # one of: 'on' | 'off' | 'undetermined'
confirmOnQuit: false
```
## Platform Defaults:
### Windows:
```
os:
openCommand: 'cmd /c "start "" {{filename}}"'
```
### Linux:
```
os:
openCommand: 'sh -c "xdg-open {{filename}} >/dev/null"'
```
### OSX:
```
os:
openCommand: 'open {{filename}}'
```
### Recommended Config Values:
for users of VSCode
```
os:
openCommand: 'code -r {{filename}}'
```
## Color Attributes:
For color attributes you can choose an array of attributes (with max one color attribute)
The available attributes are:
- default
- black
- red
- green
- yellow
- blue
- magenta
- cyan
- white
- bold
- reverse # useful for high-contrast
- underline
## Example Coloring:
![border example](/docs/resources/colored-border-example.png)
+85
View File
@@ -0,0 +1,85 @@
# Keybindings:
## Global:
<pre>
<kbd>←</kbd><kbd>→</kbd><kbd>↑</kbd><kbd>↓</kbd>/<kbd>h</kbd><kbd>j</kbd><kbd>k</kbd><kbd>l</kbd>: navigate
<kbd>PgUp</kbd>/<kbd>PgDn</kbd> or <kbd>ctrl</kbd>+<kbd>u</kbd>/<kbd>ctrl</kbd>+<kbd>d</kbd>: scroll diff panel
(for <kbd>PgUp</kbd> and <kbd>PgDn</kbd>, use <kbd>fn</kbd>+<kbd>up</kbd>/<kbd>fn</kbd>+<kbd>down</kbd> on osx)
<kbd>q</kbd>: quit
<kbd>p</kbd>: pull
<kbd>shift</kbd>+<kbd>P</kbd>: push
</pre>
## Status Panel:
<pre>
<kbd>e</kbd>: edit config file
<kbd>o</kbd>: open config file
</pre>
## Files Panel:
<pre>
<kbd>space</kbd>: toggle staged
<kbd>a</kbd>: stage/unstage all
<kbd>c</kbd>: commit changes
<kbd>shift</kbd>+<kbd>C</kbd>: commit using git editor
<kbd>shift</kbd>+<kbd>S</kbd>: stash files
<kbd>t</kbd>: add patched (i.e. pick chunks of a file to add)
<kbd>o</kbd>: open
<kbd>e</kbd>: edit
<kbd>s</kbd>: open in sublime (requires 'subl' command)
<kbd>v</kbd>: open in vscode (requires 'code' command)
<kbd>i</kbd>: add to .gitignore
<kbd>d</kbd>: delete if untracked checkout if tracked (aka go away)
<kbd>shift</kbd>+<kbd>R</kbd>: refresh files
<kbd>shift</kbd>+<kbd>A</kbd>: abort merge
</pre>
## Branches Panel:
<pre>
<kbd>space</kbd>: checkout branch
<kbd>f</kbd>: force checkout branch
<kbd>m</kbd>: merge into currently checked out branch
<kbd>c</kbd>: checkout by name
<kbd>n</kbd>: new branch
<kbd>d</kbd>: delete branch
<kbd>D</kbd>: force delete branch
</pre>
## Commits Panel:
<pre>
<kbd>s</kbd>: squash down (only available for topmost commit)
<kbd>r</kbd>: rename commit
<kbd>shift</kbd>+<kbd>R</kbd>: rename commit using git editor
<kbd>g</kbd>: reset to this commit
</pre>
## Stash Panel:
<pre>
<kbd>space</kbd>: apply
<kbd>g</kbd>: pop
<kbd>d</kbd>: drop
</pre>
## Popup Panel:
<pre>
<kbd>esc</kbd>: close/cancel
<kbd>enter</kbd>: confirm
<kbd>tab</kbd>: enter newline (if editing)
</pre>
## Resolving Merge Conflicts (Diff Panel):
<pre>
<kbd>←</kbd><kbd>→</kbd>/<kbd>h</kbd><kbd>l</kbd>: navigate conflicts
<kbd>↑</kbd><kbd>↓</kbd>/<kbd>k</kbd><kbd>j</kbd>: select hunk
<kbd>space</kbd>: pick hunk
<kbd>b</kbd>: pick both hunks
<kbd>z</kbd>: undo (only available while still inside diff panel)
</pre>

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

+62
View File
@@ -0,0 +1,62 @@
module github.com/jesseduffield/lazygit
require (
github.com/aws/aws-sdk-go v1.15.21
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/davecgh/go-spew v1.1.0
github.com/emirpasic/gods v1.9.0
github.com/fatih/color v1.7.0
github.com/fsnotify/fsnotify v1.4.7
github.com/go-ini/ini v1.38.2
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186
github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc
github.com/hashicorp/go-version v1.0.0
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce
github.com/heroku/rollrus v0.0.0-20180515183152-fc0cef2ff331
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63
github.com/jesseduffield/gocui v0.0.0-20180921065632-03e26ff3f1de
github.com/jesseduffield/termbox-go v0.0.0-20180919093808-1e272ff78dcb
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1
github.com/kevinburke/ssh_config v0.0.0-20180317175531-9fc7bb800b55
github.com/magiconair/properties v1.8.0
github.com/mattn/go-colorable v0.0.9
github.com/mattn/go-isatty v0.0.3
github.com/mattn/go-runewidth v0.0.2
github.com/mgutz/str v1.2.0
github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77
github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699
github.com/nicksnyder/go-i18n v0.0.0-20180803040939-a16b91a3ba80
github.com/pelletier/go-buffruneio v0.2.0
github.com/pelletier/go-toml v1.2.0
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0
github.com/sergi/go-diff v1.0.0
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0
github.com/sirupsen/logrus v1.0.6
github.com/spf13/afero v1.1.1
github.com/spf13/cast v1.2.0
github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834
github.com/spf13/pflag v1.0.2
github.com/spf13/viper v1.1.0
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
github.com/src-d/gcfg v1.3.0
github.com/stretchr/testify v1.2.2
github.com/stvp/roll v0.0.0-20170522205222-3627a5cbeaea
github.com/tcnksm/go-gitconfig v0.1.2
github.com/ulikunitz/xz v0.5.4
github.com/xanzy/ssh-agent v0.2.0
golang.org/x/crypto v0.0.0-20180808211826-de0752318171
golang.org/x/net v0.0.0-20180811021610-c39426892332
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0
golang.org/x/text v0.3.0
gopkg.in/src-d/go-billy.v4 v4.2.0
gopkg.in/src-d/go-git.v4 v4.0.0-20180807092216-43d17e14b714
gopkg.in/warnings.v0 v0.1.2
gopkg.in/yaml.v2 v2.2.1
)
+119
View File
@@ -0,0 +1,119 @@
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go v1.15.21 h1:STLvc6RrpycslC1NRtTvt/YSgDkIGCTrB9K9vE5R2oQ=
github.com/aws/aws-sdk-go v1.15.21/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo=
github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-ini/ini v1.38.2 h1:6Hl/z3p3iFkA0dlDfzYxuFuUGD+kaweypF6btsR2/Q4=
github.com/go-ini/ini v1.38.2/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 h1:URgjUo+bs1KwatoNbwG0uCO4dHN4r1jsp4a5AGgHRjo=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001 h1:MFPzqpPED05pFyGjNPJEC2sXM6EHTzFyvX+0s0JoZ48=
github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001/go.mod h1:6rdJFnhkXnzGOJbvkrdv4t9nLwKcVA+tmbQeUlkIzrU=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc h1:wAa9fGALVHfjYxZuXRnmuJG2CnwRpJYOTvY6YdErAh0=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno=
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/heroku/rollrus v0.0.0-20180515183152-fc0cef2ff331 h1:qio0y/sQdhbHRA3cmgczo04MaSV2zw+n46G1owvgWIk=
github.com/heroku/rollrus v0.0.0-20180515183152-fc0cef2ff331/go.mod h1:BT+PgT529opmb6mcUY+Fg0IwVRRmwqFyavEMU17GnBg=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63 h1:Nrr/yUxNjXWYK0B3IqcFlYh1ICnesJDB4ogcfOVc5Ns=
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63/go.mod h1:fNqjRf+4XnTo2PrGN1JRb79b/BeoHwP4lU00f39SQY0=
github.com/jesseduffield/gocui v0.0.0-20180919095827-4fca348422d8 h1:XxX+IqNOFDh1PnU4eZDzUomoKbuKCvwyEm5an/IxLQU=
github.com/jesseduffield/gocui v0.0.0-20180919095827-4fca348422d8/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
github.com/jesseduffield/termbox-go v0.0.0-20180919093808-1e272ff78dcb h1:cFHYEWpQEfzFZVKiKZytCUX4UwQixKSw0kd3WhluPsY=
github.com/jesseduffield/termbox-go v0.0.0-20180919093808-1e272ff78dcb/go.mod h1:anMibpZtqNxjDbxrcDEAwSdaJ37vyUeM1f/M4uekib4=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro=
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kevinburke/ssh_config v0.0.0-20180317175531-9fc7bb800b55 h1:S38dC4mEwxdw/U41+97VWdbun8mTcTjwg5Ujfg8QPME=
github.com/kevinburke/ssh_config v0.0.0-20180317175531-9fc7bb800b55/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=
github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff h1:jM4Eo4qMmmcqePS3u6X2lcEELtVuXWkWJIS/pRI3oSk=
github.com/mitchellh/go-homedir v0.0.0-20180801233206-58046073cbff/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699 h1:KXZJFdun9knAVAR8tg/aHJEr5DgtcbqyvzacK+CDCaI=
github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nicksnyder/go-i18n v0.0.0-20180803040939-a16b91a3ba80 h1:7ory6RlsEkeK89iyV7Imz3sVz8YHeSw29w3PehpCWC0=
github.com/nicksnyder/go-i18n v0.0.0-20180803040939-a16b91a3ba80/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5 h1:/TjjTS4kg7vC+05gD0LE4+97f/+PRFICnK/7wJPk7kE=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5/go.mod h1:4Opqa6/HIv0lhG3WRAkqzO0afezkRhxXI0P8EJkqeRU=
github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y=
github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I=
github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834 h1:kJI9pPzfsULT/72wy7mxkRQZPtKWgFdCA2RTGZ4v8/E=
github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.1.0 h1:V7OZpY8i3C1x/pDmU0zNNlfVoDz112fSYvtWMjjS3f4=
github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
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/src-d/gcfg v1.3.0 h1:2BEDr8r0I0b8h/fOqwtxCEiq2HJu8n2JGZJQFGXWLjg=
github.com/src-d/gcfg v1.3.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stvp/roll v0.0.0-20170522205222-3627a5cbeaea h1:jysxIKov/4GJ33wI2aRvuIK7yBwB28E5almlgDLPRpM=
github.com/stvp/roll v0.0.0-20170522205222-3627a5cbeaea/go.mod h1:Ffmqrj3nXIMIjeA4uW3Qjj0Ud9eDoTG0fu4JxyAr/tE=
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
github.com/ulikunitz/xz v0.5.4 h1:zATC2OoZ8H1TZll3FpbX+ikwmadbO699PE06cIkm9oU=
github.com/ulikunitz/xz v0.5.4/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro=
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
golang.org/x/crypto v0.0.0-20180808211826-de0752318171 h1:vYogbvSFj2YXcjQxFHu/rASSOt9sLytpCaSkiwQ135I=
golang.org/x/crypto v0.0.0-20180808211826-de0752318171/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180811021610-c39426892332 h1:efGso+ep0DjyCBJPjvoz0HI6UldX4Md2F1rZFe1ir0E=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0 h1:8H8QZJ30plJyIVj60H3lr8TZGIq2Fh3Cyrs/ZNg1foU=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.0.0-20171214130843-f21a4dfb5e38/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/src-d/go-billy.v4 v4.2.0 h1:VGbrP1EsYxtvVPEiHui+4//imr4E5MGEFLx66bQtusg=
gopkg.in/src-d/go-billy.v4 v4.2.0/go.mod h1:ZHSF0JP+7oD97194otDUCD7Ofbk63+xFcfWP5bT6h+Q=
gopkg.in/src-d/go-git.v4 v4.0.0-20180807092216-43d17e14b714 h1:+wM2BGgQ1znCKBexOB4OrGVSDw8mtKNUSq3wqxZhi/k=
gopkg.in/src-d/go-git.v4 v4.0.0-20180807092216-43d17e14b714/go.mod h1:CzbUWqMn4pvmvndg3gnh5iZFmSsbhyhUWdI0IQ60AQo=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+54
View File
@@ -0,0 +1,54 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"github.com/jesseduffield/lazygit/pkg/app"
"github.com/jesseduffield/lazygit/pkg/config"
)
var (
commit string
version = "unversioned"
date string
buildSource = "unknown"
configFlag = flag.Bool("config", false, "Print the current default config")
debuggingFlag = flag.Bool("debug", false, "a boolean")
versionFlag = flag.Bool("v", false, "Print the current version")
)
func projectPath(path string) string {
gopath := os.Getenv("GOPATH")
return filepath.FromSlash(gopath + "/src/github.com/jesseduffield/lazygit/" + path)
}
func main() {
flag.Parse()
if *versionFlag {
fmt.Printf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH)
os.Exit(0)
}
if *configFlag {
fmt.Printf("%s\n", config.GetDefaultConfig())
os.Exit(0)
}
appConfig, err := config.NewAppConfig("lazygit", version, commit, date, buildSource, debuggingFlag)
if err != nil {
log.Fatal(err.Error())
}
app, err := app.Setup(appConfig)
if err != nil {
app.Log.Error(err.Error())
log.Fatal(err.Error())
}
app.Gui.RunWithSubprocesses()
}
+104
View File
@@ -0,0 +1,104 @@
package app
import (
"io"
"io/ioutil"
"os"
"github.com/heroku/rollrus"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/updates"
"github.com/sirupsen/logrus"
)
// App struct
type App struct {
closers []io.Closer
Config config.AppConfigurer
Log *logrus.Entry
OSCommand *commands.OSCommand
GitCommand *commands.GitCommand
Gui *gui.Gui
Tr *i18n.Localizer
Updater *updates.Updater // may only need this on the Gui
}
func newProductionLogger(config config.AppConfigurer) *logrus.Logger {
log := logrus.New()
log.Out = ioutil.Discard
return log
}
func newDevelopmentLogger() *logrus.Logger {
log := logrus.New()
file, err := os.OpenFile("development.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
panic("unable to log to file") // TODO: don't panic (also, remove this call to the `panic` function)
}
log.SetOutput(file)
return log
}
func newLogger(config config.AppConfigurer) *logrus.Entry {
var log *logrus.Logger
environment := "production"
if config.GetDebug() {
environment = "development"
log = newDevelopmentLogger()
} else {
log = newProductionLogger(config)
}
if config.GetUserConfig().GetString("reporting") == "on" {
// this isn't really a secret token: it only has permission to push new rollbar items
hook := rollrus.NewHook("23432119147a4367abf7c0de2aa99a2d", environment)
log.Hooks.Add(hook)
}
return log.WithFields(logrus.Fields{
"debug": config.GetDebug(),
"version": config.GetVersion(),
"commit": config.GetCommit(),
"buildDate": config.GetBuildDate(),
})
}
// Setup bootstrap a new application
func Setup(config config.AppConfigurer) (*App, error) {
app := &App{
closers: []io.Closer{},
Config: config,
}
var err error
app.Log = newLogger(config)
app.OSCommand = commands.NewOSCommand(app.Log, config)
app.Tr = i18n.NewLocalizer(app.Log)
app.Updater, err = updates.NewUpdater(app.Log, config, app.OSCommand, app.Tr)
if err != nil {
return app, err
}
app.GitCommand, err = commands.NewGitCommand(app.Log, app.OSCommand, app.Tr)
if err != nil {
return app, err
}
app.Gui, err = gui.NewGui(app.Log, app.GitCommand, app.OSCommand, app.Tr, config, app.Updater)
if err != nil {
return app, err
}
return app, nil
}
// Close closes any resources
func (app *App) Close() error {
for _, closer := range app.closers {
err := closer.Close()
if err != nil {
return err
}
}
return nil
}
+39
View File
@@ -0,0 +1,39 @@
package commands
import (
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/lazygit/pkg/utils"
)
// Branch : A git branch
// duplicating this for now
type Branch struct {
Name string
Recency string
}
// GetDisplayStrings returns the dispaly string of branch
func (b *Branch) GetDisplayStrings() []string {
return []string{b.Recency, utils.ColoredString(b.Name, b.GetColor())}
}
// GetColor branch color
func (b *Branch) GetColor() color.Attribute {
switch b.getType() {
case "feature":
return color.FgGreen
case "bugfix":
return color.FgYellow
case "hotfix":
return color.FgRed
default:
return color.FgWhite
}
}
// expected to return feature/bugfix/hotfix or blank string
func (b *Branch) getType() string {
return strings.Split(b.Name, "/")[0]
}
+26
View File
@@ -0,0 +1,26 @@
package commands
import (
"github.com/fatih/color"
)
// Commit : A git commit
type Commit struct {
Sha string
Name string
Pushed bool
DisplayString string
}
func (c *Commit) GetDisplayStrings() []string {
red := color.New(color.FgRed)
yellow := color.New(color.FgYellow)
white := color.New(color.FgWhite)
shaColor := yellow
if c.Pushed {
shaColor = red
}
return []string{shaColor.Sprint(c.Sha), white.Sprint(c.Name)}
}
+36
View File
@@ -0,0 +1,36 @@
package commands
import "github.com/fatih/color"
// File : A file from git status
// duplicating this for now
type File struct {
Name string
HasStagedChanges bool
HasUnstagedChanges bool
Tracked bool
Deleted bool
HasMergeConflicts bool
DisplayString string
Type string // one of 'file', 'directory', and 'other'
}
// GetDisplayStrings returns the display string of a file
func (f *File) GetDisplayStrings() []string {
// potentially inefficient to be instantiating these color
// objects with each render
red := color.New(color.FgRed)
green := color.New(color.FgGreen)
if !f.Tracked && !f.HasStagedChanges {
return []string{red.Sprint(f.DisplayString)}
}
output := green.Sprint(f.DisplayString[0:1])
output += red.Sprint(f.DisplayString[1:3])
if f.HasUnstagedChanges {
output += red.Sprint(f.Name)
} else {
output += green.Sprint(f.Name)
}
return []string{output}
}
+527
View File
@@ -0,0 +1,527 @@
package commands
import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus"
gitconfig "github.com/tcnksm/go-gitconfig"
gogit "gopkg.in/src-d/go-git.v4"
)
func verifyInGitRepo(runCmd func(string) error) error {
return runCmd("git status")
}
func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir func(string) error) error {
for {
f, err := stat(".git")
if err == nil && f.IsDir() {
return nil
}
if !os.IsNotExist(err) {
return err
}
if err = chdir(".."); err != nil {
return err
}
}
}
func setupRepositoryAndWorktree(openGitRepository func(string) (*gogit.Repository, error), sLocalize func(string) string) (repository *gogit.Repository, worktree *gogit.Worktree, err error) {
repository, err = openGitRepository(".")
if err != nil {
if strings.Contains(err.Error(), `unquoted '\' must be followed by new line`) {
return nil, nil, errors.New(sLocalize("GitconfigParseErr"))
}
return
}
worktree, err = repository.Worktree()
if err != nil {
return
}
return
}
// GitCommand is our main git interface
type GitCommand struct {
Log *logrus.Entry
OSCommand *OSCommand
Worktree *gogit.Worktree
Repo *gogit.Repository
Tr *i18n.Localizer
getGlobalGitConfig func(string) (string, error)
getLocalGitConfig func(string) (string, error)
removeFile func(string) error
}
// NewGitCommand it runs git commands
func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer) (*GitCommand, error) {
var worktree *gogit.Worktree
var repo *gogit.Repository
fs := []func() error{
func() error {
return verifyInGitRepo(osCommand.RunCommand)
},
func() error {
return navigateToRepoRootDirectory(os.Stat, os.Chdir)
},
func() error {
var err error
repo, worktree, err = setupRepositoryAndWorktree(gogit.PlainOpen, tr.SLocalize)
return err
},
}
for _, f := range fs {
if err := f(); err != nil {
return nil, err
}
}
return &GitCommand{
Log: log,
OSCommand: osCommand,
Tr: tr,
Worktree: worktree,
Repo: repo,
getGlobalGitConfig: gitconfig.Global,
getLocalGitConfig: gitconfig.Local,
removeFile: os.RemoveAll,
}, nil
}
// GetStashEntries stash entryies
func (c *GitCommand) GetStashEntries() []*StashEntry {
rawString, _ := c.OSCommand.RunCommandWithOutput("git stash list --pretty='%gs'")
stashEntries := []*StashEntry{}
for i, line := range utils.SplitLines(rawString) {
stashEntries = append(stashEntries, stashEntryFromLine(line, i))
}
return stashEntries
}
func stashEntryFromLine(line string, index int) *StashEntry {
return &StashEntry{
Name: line,
Index: index,
DisplayString: line,
}
}
// GetStashEntryDiff stash diff
func (c *GitCommand) GetStashEntryDiff(index int) (string, error) {
return c.OSCommand.RunCommandWithOutput("git stash show -p --color stash@{" + fmt.Sprint(index) + "}")
}
// GetStatusFiles git status files
func (c *GitCommand) GetStatusFiles() []*File {
statusOutput, _ := c.GitStatus()
statusStrings := utils.SplitLines(statusOutput)
files := []*File{}
for _, statusString := range statusStrings {
change := statusString[0:2]
stagedChange := change[0:1]
unstagedChange := statusString[1:2]
filename := c.OSCommand.Unquote(statusString[3:])
_, untracked := map[string]bool{"??": true, "A ": true, "AM": true}[change]
_, hasNoStagedChanges := map[string]bool{" ": true, "U": true, "?": true}[stagedChange]
file := &File{
Name: filename,
DisplayString: statusString,
HasStagedChanges: !hasNoStagedChanges,
HasUnstagedChanges: unstagedChange != " ",
Tracked: !untracked,
Deleted: unstagedChange == "D" || stagedChange == "D",
HasMergeConflicts: change == "UU",
Type: c.OSCommand.FileType(filename),
}
files = append(files, file)
}
c.Log.Info(files) // TODO: use a dumper-esque log here
return files
}
// StashDo modify stash
func (c *GitCommand) StashDo(index int, method string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git stash %s stash@{%d}", method, index))
}
// StashSave save stash
// TODO: before calling this, check if there is anything to save
func (c *GitCommand) StashSave(message string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git stash save %s", c.OSCommand.Quote(message)))
}
// MergeStatusFiles merge status files
func (c *GitCommand) MergeStatusFiles(oldFiles, newFiles []*File) []*File {
if len(oldFiles) == 0 {
return newFiles
}
appendedIndexes := []int{}
// retain position of files we already could see
result := []*File{}
for _, oldFile := range oldFiles {
for newIndex, newFile := range newFiles {
if oldFile.Name == newFile.Name {
result = append(result, newFile)
appendedIndexes = append(appendedIndexes, newIndex)
break
}
}
}
// append any new files to the end
for index, newFile := range newFiles {
if !includesInt(appendedIndexes, index) {
result = append(result, newFile)
}
}
return result
}
func includesInt(list []int, a int) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
// GetBranchName branch name
func (c *GitCommand) GetBranchName() (string, error) {
return c.OSCommand.RunCommandWithOutput("git symbolic-ref --short HEAD")
}
// ResetHard does the equivalent of `git reset --hard HEAD`
func (c *GitCommand) ResetHard() error {
return c.Worktree.Reset(&gogit.ResetOptions{Mode: gogit.HardReset})
}
// UpstreamDifferenceCount checks how many pushables/pullables there are for the
// current branch
func (c *GitCommand) UpstreamDifferenceCount() (string, string) {
pushableCount, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..head --count")
if err != nil {
return "?", "?"
}
pullableCount, err := c.OSCommand.RunCommandWithOutput("git rev-list head..@{u} --count")
if err != nil {
return "?", "?"
}
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
}
// GetCommitsToPush Returns the sha's of the commits that have not yet been pushed
// to the remote branch of the current branch, a map is returned to ease look up
func (c *GitCommand) GetCommitsToPush() map[string]bool {
pushables := map[string]bool{}
o, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..head --abbrev-commit")
if err != nil {
return pushables
}
for _, p := range utils.SplitLines(o) {
pushables[p] = true
}
return pushables
}
// RenameCommit renames the topmost commit with the given name
func (c *GitCommand) RenameCommit(name string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git commit --allow-empty --amend -m %s", c.OSCommand.Quote(name)))
}
// Fetch fetch git repo
func (c *GitCommand) Fetch() error {
return c.OSCommand.RunCommand("git fetch")
}
// ResetToCommit reset to commit
func (c *GitCommand) ResetToCommit(sha string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git reset %s", sha))
}
// NewBranch create new branch
func (c *GitCommand) NewBranch(name string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout -b %s", name))
}
// DeleteBranch delete branch
func (c *GitCommand) DeleteBranch(branch string, force bool) error {
command := "git branch -d"
if force {
command = "git branch -D"
}
return c.OSCommand.RunCommand(fmt.Sprintf("%s %s", command, branch))
}
// ListStash list stash
func (c *GitCommand) ListStash() (string, error) {
return c.OSCommand.RunCommandWithOutput("git stash list")
}
// Merge merge
func (c *GitCommand) Merge(branchName string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git merge --no-edit %s", branchName))
}
// AbortMerge abort merge
func (c *GitCommand) AbortMerge() error {
return c.OSCommand.RunCommand("git merge --abort")
}
// usingGpg tells us whether the user has gpg enabled so that we can know
// whether we need to run a subprocess to allow them to enter their password
func (c *GitCommand) usingGpg() bool {
gpgsign, _ := c.getLocalGitConfig("commit.gpgsign")
if gpgsign == "" {
gpgsign, _ = c.getGlobalGitConfig("commit.gpgsign")
}
value := strings.ToLower(gpgsign)
return value == "true" || value == "1" || value == "yes" || value == "on"
}
// Commit commits to git
func (c *GitCommand) Commit(message string) (*exec.Cmd, error) {
command := fmt.Sprintf("git commit -m %s", c.OSCommand.Quote(message))
if c.usingGpg() {
return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil
}
return nil, c.OSCommand.RunCommand(command)
}
// Pull pulls from repo
func (c *GitCommand) Pull() error {
return c.OSCommand.RunCommand("git pull --no-edit")
}
// Push pushes to a branch
func (c *GitCommand) Push(branchName string, force bool) error {
forceFlag := ""
if force {
forceFlag = "--force-with-lease "
}
return c.OSCommand.RunCommand(fmt.Sprintf("git push %s -u origin %s", forceFlag, branchName))
}
// SquashPreviousTwoCommits squashes a commit down to the one below it
// retaining the message of the higher commit
func (c *GitCommand) SquashPreviousTwoCommits(message string) error {
// TODO: test this
if err := c.OSCommand.RunCommand("git reset --soft HEAD^"); err != nil {
return err
}
// TODO: if password is required, we need to return a subprocess
return c.OSCommand.RunCommand(fmt.Sprintf("git commit --amend -m %s", c.OSCommand.Quote(message)))
}
// SquashFixupCommit squashes a 'FIXUP' commit into the commit beneath it,
// retaining the commit message of the lower commit
func (c *GitCommand) SquashFixupCommit(branchName string, shaValue string) error {
commands := []string{
fmt.Sprintf("git checkout -q %s", shaValue),
fmt.Sprintf("git reset --soft %s^", shaValue),
fmt.Sprintf("git commit --amend -C %s^", shaValue),
fmt.Sprintf("git rebase --onto HEAD %s %s", shaValue, branchName),
}
for _, command := range commands {
c.Log.Info(command)
if output, err := c.OSCommand.RunCommandWithOutput(command); err != nil {
ret := output
// We are already in an error state here so we're just going to append
// the output of these commands
output, _ := c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git branch -d %s", shaValue))
ret += output
output, _ = c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git checkout %s", branchName))
ret += output
c.Log.Info(ret)
return errors.New(ret)
}
}
return nil
}
// CatFile obtains the content of a file
func (c *GitCommand) CatFile(fileName string) (string, error) {
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("cat %s", c.OSCommand.Quote(fileName)))
}
// StageFile stages a file
func (c *GitCommand) StageFile(fileName string) error {
return c.OSCommand.RunCommand(fmt.Sprintf("git add %s", c.OSCommand.Quote(fileName)))
}
// StageAll stages all files
func (c *GitCommand) StageAll() error {
return c.OSCommand.RunCommand("git add -A")
}
// UnstageAll stages all files
func (c *GitCommand) UnstageAll() error {
return c.OSCommand.RunCommand("git reset")
}
// UnStageFile unstages a file
func (c *GitCommand) UnStageFile(fileName string, tracked bool) error {
command := "git rm --cached %s"
if tracked {
command = "git reset HEAD %s"
}
return c.OSCommand.RunCommand(fmt.Sprintf(command, c.OSCommand.Quote(fileName)))
}
// GitStatus returns the plaintext short status of the repo
func (c *GitCommand) GitStatus() (string, error) {
return c.OSCommand.RunCommandWithOutput("git status --untracked-files=all --short")
}
// IsInMergeState states whether we are still mid-merge
func (c *GitCommand) IsInMergeState() (bool, error) {
output, err := c.OSCommand.RunCommandWithOutput("git status --untracked-files=all")
if err != nil {
return false, err
}
return strings.Contains(output, "conclude merge") || strings.Contains(output, "unmerged paths"), nil
}
// RemoveFile directly
func (c *GitCommand) RemoveFile(file *File) error {
// if the file isn't tracked, we assume you want to delete it
if file.HasStagedChanges {
if err := c.OSCommand.RunCommand(fmt.Sprintf("git reset -- %s", file.Name)); err != nil {
return err
}
}
if !file.Tracked {
return c.removeFile(file.Name)
}
// if the file is tracked, we assume you want to just check it out
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout -- %s", file.Name))
}
// Checkout checks out a branch, with --force if you set the force arg to true
func (c *GitCommand) Checkout(branch string, force bool) error {
forceArg := ""
if force {
forceArg = "--force "
}
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout %s %s", forceArg, branch))
}
// AddPatch prepares a subprocess for adding a patch by patch
// this will eventually be swapped out for a better solution inside the Gui
func (c *GitCommand) AddPatch(filename string) *exec.Cmd {
return c.OSCommand.PrepareSubProcess("git", "add", "--patch", filename)
}
// PrepareCommitSubProcess prepares a subprocess for `git commit`
func (c *GitCommand) PrepareCommitSubProcess() *exec.Cmd {
return c.OSCommand.PrepareSubProcess("git", "commit")
}
// PrepareCommitAmendSubProcess prepares a subprocess for `git commit --amend --allow-empty`
func (c *GitCommand) PrepareCommitAmendSubProcess() *exec.Cmd {
return c.OSCommand.PrepareSubProcess("git", "commit", "--amend", "--allow-empty")
}
// GetBranchGraph gets the color-formatted graph of the log for the given branch
// Currently it limits the result to 100 commits, but when we get async stuff
// working we can do lazy loading
func (c *GitCommand) GetBranchGraph(branchName string) (string, error) {
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 %s", branchName))
}
// GetCommits obtains the commits of the current branch
func (c *GitCommand) GetCommits() []*Commit {
pushables := c.GetCommitsToPush()
log := c.GetLog()
commits := []*Commit{}
// now we can split it up and turn it into commits
for _, line := range utils.SplitLines(log) {
splitLine := strings.Split(line, " ")
sha := splitLine[0]
_, pushed := pushables[sha]
commits = append(commits, &Commit{
Sha: sha,
Name: strings.Join(splitLine[1:], " "),
Pushed: pushed,
DisplayString: strings.Join(splitLine, " "),
})
}
return commits
}
// GetLog gets the git log (currently limited to 30 commits for performance
// until we work out lazy loading
func (c *GitCommand) GetLog() string {
// currently limiting to 30 for performance reasons
// TODO: add lazyloading when you scroll down
result, err := c.OSCommand.RunCommandWithOutput("git log --oneline -30")
if err != nil {
// assume if there is an error there are no commits yet for this branch
return ""
}
return result
}
// Ignore adds a file to the gitignore for the repo
func (c *GitCommand) Ignore(filename string) error {
return c.OSCommand.AppendLineToFile(".gitignore", filename)
}
// Show shows the diff of a commit
func (c *GitCommand) Show(sha string) string {
result, err := c.OSCommand.RunCommandWithOutput("git show --color " + sha)
if err != nil {
panic(err)
}
return result
}
// Diff returns the diff of a file
func (c *GitCommand) Diff(file *File) string {
cachedArg := ""
fileName := c.OSCommand.Quote(file.Name)
if file.HasStagedChanges && !file.HasUnstagedChanges {
cachedArg = "--cached"
}
trackedArg := "--"
if !file.Tracked && !file.HasStagedChanges {
trackedArg = "--no-index /dev/null"
}
command := fmt.Sprintf("%s %s %s %s", "git diff --color ", cachedArg, trackedArg, fileName)
// for now we assume an error means the file was deleted
s, _ := c.OSCommand.RunCommandWithOutput(command)
return s
}
+9
View File
@@ -0,0 +1,9 @@
package commands
// Conflict : A git conflict with a start middle and end corresponding to line
// numbers in the file where the conflict bars appear
type Conflict struct {
Start int
Middle int
End int
}
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
package commands
import (
"errors"
"os"
"os/exec"
"strings"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/mgutz/str"
"github.com/sirupsen/logrus"
gitconfig "github.com/tcnksm/go-gitconfig"
)
// Platform stores the os state
type Platform struct {
os string
shell string
shellArg string
escapedQuote string
openCommand string
fallbackEscapedQuote string
}
// OSCommand holds all the os commands
type OSCommand struct {
Log *logrus.Entry
Platform *Platform
Config config.AppConfigurer
command func(string, ...string) *exec.Cmd
getGlobalGitConfig func(string) (string, error)
getenv func(string) string
}
// NewOSCommand os command runner
func NewOSCommand(log *logrus.Entry, config config.AppConfigurer) *OSCommand {
return &OSCommand{
Log: log,
Platform: getPlatform(),
Config: config,
command: exec.Command,
getGlobalGitConfig: gitconfig.Global,
getenv: os.Getenv,
}
}
// RunCommandWithOutput wrapper around commands returning their output and error
func (c *OSCommand) RunCommandWithOutput(command string) (string, error) {
c.Log.WithField("command", command).Info("RunCommand")
splitCmd := str.ToArgv(command)
c.Log.Info(splitCmd)
return sanitisedCommandOutput(
c.command(splitCmd[0], splitCmd[1:]...).CombinedOutput(),
)
}
// RunCommand runs a command and just returns the error
func (c *OSCommand) RunCommand(command string) error {
_, err := c.RunCommandWithOutput(command)
return err
}
// FileType tells us if the file is a file, directory or other
func (c *OSCommand) FileType(path string) string {
fileInfo, err := os.Stat(path)
if err != nil {
return "other"
}
if fileInfo.IsDir() {
return "directory"
}
return "file"
}
// RunDirectCommand wrapper around direct commands
func (c *OSCommand) RunDirectCommand(command string) (string, error) {
c.Log.WithField("command", command).Info("RunDirectCommand")
return sanitisedCommandOutput(
c.command(c.Platform.shell, c.Platform.shellArg, command).
CombinedOutput(),
)
}
func sanitisedCommandOutput(output []byte, err error) (string, error) {
outputString := string(output)
if err != nil {
// errors like 'exit status 1' are not very useful so we'll create an error
// from the combined output
if outputString == "" {
return "", err
}
return outputString, errors.New(outputString)
}
return outputString, nil
}
// OpenFile opens a file with the given
func (c *OSCommand) OpenFile(filename string) error {
commandTemplate := c.Config.GetUserConfig().GetString("os.openCommand")
templateValues := map[string]string{
"filename": c.Quote(filename),
}
command := utils.ResolvePlaceholderString(commandTemplate, templateValues)
err := c.RunCommand(command)
return err
}
// EditFile opens a file in a subprocess using whatever editor is available,
// falling back to core.editor, VISUAL, EDITOR, then vi
func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) {
editor, _ := c.getGlobalGitConfig("core.editor")
if editor == "" {
editor = c.getenv("VISUAL")
}
if editor == "" {
editor = c.getenv("EDITOR")
}
if editor == "" {
if err := c.RunCommand("which vi"); err == nil {
editor = "vi"
}
}
if editor == "" {
return nil, errors.New("No editor defined in $VISUAL, $EDITOR, or git config")
}
return c.PrepareSubProcess(editor, filename), nil
}
// PrepareSubProcess iniPrepareSubProcessrocess then tells the Gui to switch to it
func (c *OSCommand) PrepareSubProcess(cmdName string, commandArgs ...string) *exec.Cmd {
return c.command(cmdName, commandArgs...)
}
// Quote wraps a message in platform-specific quotation marks
func (c *OSCommand) Quote(message string) string {
message = strings.Replace(message, "`", "\\`", -1)
escapedQuote := c.Platform.escapedQuote
if strings.Contains(message, c.Platform.escapedQuote) {
escapedQuote = c.Platform.fallbackEscapedQuote
}
return escapedQuote + message + escapedQuote
}
// Unquote removes wrapping quotations marks if they are present
// this is needed for removing quotes from staged filenames with spaces
func (c *OSCommand) Unquote(message string) string {
return strings.Replace(message, `"`, "", -1)
}
// AppendLineToFile adds a new line in file
func (c *OSCommand) AppendLineToFile(filename, line string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString("\n" + line)
return err
}
+18
View File
@@ -0,0 +1,18 @@
// +build !windows
package commands
import (
"runtime"
)
func getPlatform() *Platform {
return &Platform{
os: runtime.GOOS,
shell: "bash",
shellArg: "-c",
escapedQuote: "'",
openCommand: "open {{filename}}",
fallbackEscapedQuote: "\"",
}
}
+359
View File
@@ -0,0 +1,359 @@
package commands
import (
"os"
"os/exec"
"testing"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
yaml "gopkg.in/yaml.v2"
)
func newDummyOSCommand() *OSCommand {
return NewOSCommand(newDummyLog(), newDummyAppConfig())
}
func newDummyAppConfig() *config.AppConfig {
appConfig := &config.AppConfig{
Name: "lazygit",
Version: "unversioned",
Commit: "",
BuildDate: "",
Debug: false,
BuildSource: "",
UserConfig: viper.New(),
}
_ = yaml.Unmarshal([]byte{}, appConfig.AppState)
return appConfig
}
func TestOSCommandRunCommandWithOutput(t *testing.T) {
type scenario struct {
command string
test func(string, error)
}
scenarios := []scenario{
{
"echo -n '123'",
func(output string, err error) {
assert.NoError(t, err)
assert.EqualValues(t, "123", output)
},
},
{
"rmdir unexisting-folder",
func(output string, err error) {
assert.Regexp(t, "rmdir.*unexisting-folder.*", err.Error())
},
},
}
for _, s := range scenarios {
s.test(newDummyOSCommand().RunCommandWithOutput(s.command))
}
}
func TestOSCommandRunCommand(t *testing.T) {
type scenario struct {
command string
test func(error)
}
scenarios := []scenario{
{
"rmdir unexisting-folder",
func(err error) {
assert.Regexp(t, "rmdir.*unexisting-folder.*", err.Error())
},
},
}
for _, s := range scenarios {
s.test(newDummyOSCommand().RunCommand(s.command))
}
}
func TestOSCommandOpenFile(t *testing.T) {
type scenario struct {
filename string
command func(string, ...string) *exec.Cmd
test func(error)
}
scenarios := []scenario{
{
"test",
func(name string, arg ...string) *exec.Cmd {
return exec.Command("exit", "1")
},
func(err error) {
assert.Error(t, err)
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "open", name)
assert.Equal(t, []string{"test"}, arg)
return exec.Command("echo")
},
func(err error) {
assert.NoError(t, err)
},
},
{
"filename with spaces",
func(name string, arg ...string) *exec.Cmd {
assert.Equal(t, "open", name)
assert.Equal(t, []string{"filename with spaces"}, arg)
return exec.Command("echo")
},
func(err error) {
assert.NoError(t, err)
},
},
}
for _, s := range scenarios {
OSCmd := newDummyOSCommand()
OSCmd.command = s.command
OSCmd.Config.GetUserConfig().Set("os.openCommand", "open {{filename}}")
s.test(OSCmd.OpenFile(s.filename))
}
}
func TestOSCommandEditFile(t *testing.T) {
type scenario struct {
filename string
command func(string, ...string) *exec.Cmd
getenv func(string) string
getGlobalGitConfig func(string) (string, error)
test func(*exec.Cmd, error)
}
scenarios := []scenario{
{
"test",
func(name string, arg ...string) *exec.Cmd {
return exec.Command("exit", "1")
},
func(env string) string {
return ""
},
func(cf string) (string, error) {
return "", nil
},
func(cmd *exec.Cmd, err error) {
assert.EqualError(t, err, "No editor defined in $VISUAL, $EDITOR, or git config")
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
if name == "which" {
return exec.Command("exit", "1")
}
assert.EqualValues(t, "nano", name)
return nil
},
func(env string) string {
return ""
},
func(cf string) (string, error) {
return "nano", nil
},
func(cmd *exec.Cmd, err error) {
assert.NoError(t, err)
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
if name == "which" {
return exec.Command("exit", "1")
}
assert.EqualValues(t, "nano", name)
return nil
},
func(env string) string {
if env == "VISUAL" {
return "nano"
}
return ""
},
func(cf string) (string, error) {
return "", nil
},
func(cmd *exec.Cmd, err error) {
assert.NoError(t, err)
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
if name == "which" {
return exec.Command("exit", "1")
}
assert.EqualValues(t, "emacs", name)
return nil
},
func(env string) string {
if env == "EDITOR" {
return "emacs"
}
return ""
},
func(cf string) (string, error) {
return "", nil
},
func(cmd *exec.Cmd, err error) {
assert.NoError(t, err)
},
},
{
"test",
func(name string, arg ...string) *exec.Cmd {
if name == "which" {
return exec.Command("echo")
}
assert.EqualValues(t, "vi", name)
return nil
},
func(env string) string {
return ""
},
func(cf string) (string, error) {
return "", nil
},
func(cmd *exec.Cmd, err error) {
assert.NoError(t, err)
},
},
}
for _, s := range scenarios {
OSCmd := newDummyOSCommand()
OSCmd.command = s.command
OSCmd.getGlobalGitConfig = s.getGlobalGitConfig
OSCmd.getenv = s.getenv
s.test(OSCmd.EditFile(s.filename))
}
}
func TestOSCommandQuote(t *testing.T) {
osCommand := newDummyOSCommand()
actual := osCommand.Quote("hello `test`")
expected := osCommand.Platform.escapedQuote + "hello \\`test\\`" + osCommand.Platform.escapedQuote
assert.EqualValues(t, expected, actual)
}
// TestOSCommandQuoteSingleQuote tests the quote function with ' quotes explicitly for Linux
func TestOSCommandQuoteSingleQuote(t *testing.T) {
osCommand := newDummyOSCommand()
osCommand.Platform.os = "linux"
actual := osCommand.Quote("hello 'test'")
expected := osCommand.Platform.fallbackEscapedQuote + "hello 'test'" + osCommand.Platform.fallbackEscapedQuote
assert.EqualValues(t, expected, actual)
}
// TestOSCommandQuoteSingleQuote tests the quote function with " quotes explicitly for Linux
func TestOSCommandQuoteDoubleQuote(t *testing.T) {
osCommand := newDummyOSCommand()
osCommand.Platform.os = "linux"
actual := osCommand.Quote(`hello "test"`)
expected := osCommand.Platform.escapedQuote + "hello \"test\"" + osCommand.Platform.escapedQuote
assert.EqualValues(t, expected, actual)
}
func TestOSCommandUnquote(t *testing.T) {
osCommand := newDummyOSCommand()
actual := osCommand.Unquote(`hello "test"`)
expected := "hello test"
assert.EqualValues(t, expected, actual)
}
func TestOSCommandFileType(t *testing.T) {
type scenario struct {
path string
setup func()
test func(string)
}
scenarios := []scenario{
{
"testFile",
func() {
if _, err := os.Create("testFile"); err != nil {
panic(err)
}
},
func(output string) {
assert.EqualValues(t, "file", output)
},
},
{
"file with spaces",
func() {
if _, err := os.Create("file with spaces"); err != nil {
panic(err)
}
},
func(output string) {
assert.EqualValues(t, "file", output)
},
},
{
"testDirectory",
func() {
if err := os.Mkdir("testDirectory", 0644); err != nil {
panic(err)
}
},
func(output string) {
assert.EqualValues(t, "directory", output)
},
},
{
"nonExistant",
func() {},
func(output string) {
assert.EqualValues(t, "other", output)
},
},
}
for _, s := range scenarios {
s.setup()
s.test(newDummyOSCommand().FileType(s.path))
_ = os.RemoveAll(s.path)
}
}
+11
View File
@@ -0,0 +1,11 @@
package commands
func getPlatform() *Platform {
return &Platform{
os: "windows",
shell: "cmd",
shellArg: "/c",
escapedQuote: `\"`,
fallbackEscapedQuote: "\\'",
}
}
+13
View File
@@ -0,0 +1,13 @@
package commands
// StashEntry : A git stash entry
type StashEntry struct {
Index int
Name string
DisplayString string
}
// GetDisplayStrings returns the dispaly string of branch
func (s *StashEntry) GetDisplayStrings() []string {
return []string{s.DisplayString}
}
+256
View File
@@ -0,0 +1,256 @@
package config
import (
"bytes"
"io/ioutil"
"path/filepath"
"github.com/shibukawa/configdir"
"github.com/spf13/viper"
yaml "gopkg.in/yaml.v2"
)
// AppConfig contains the base configuration fields required for lazygit.
type AppConfig struct {
Debug bool `long:"debug" env:"DEBUG" default:"false"`
Version string `long:"version" env:"VERSION" default:"unversioned"`
Commit string `long:"commit" env:"COMMIT"`
BuildDate string `long:"build-date" env:"BUILD_DATE"`
Name string `long:"name" env:"NAME" default:"lazygit"`
BuildSource string `long:"build-source" env:"BUILD_SOURCE" default:""`
UserConfig *viper.Viper
AppState *AppState
}
// AppConfigurer interface allows individual app config structs to inherit Fields
// from AppConfig and still be used by lazygit.
type AppConfigurer interface {
GetDebug() bool
GetVersion() string
GetCommit() string
GetBuildDate() string
GetName() string
GetBuildSource() string
GetUserConfig() *viper.Viper
GetAppState() *AppState
WriteToUserConfig(string, string) error
SaveAppState() error
LoadAppState() error
}
// NewAppConfig makes a new app config
func NewAppConfig(name, version, commit, date string, buildSource string, debuggingFlag *bool) (*AppConfig, error) {
userConfig, err := LoadConfig("config", true)
if err != nil {
return nil, err
}
appConfig := &AppConfig{
Name: "lazygit",
Version: version,
Commit: commit,
BuildDate: date,
Debug: *debuggingFlag,
BuildSource: buildSource,
UserConfig: userConfig,
AppState: &AppState{},
}
if err := appConfig.LoadAppState(); err != nil {
return nil, err
}
return appConfig, nil
}
// GetDebug returns debug flag
func (c *AppConfig) GetDebug() bool {
return c.Debug
}
// GetVersion returns debug flag
func (c *AppConfig) GetVersion() string {
return c.Version
}
// GetCommit returns debug flag
func (c *AppConfig) GetCommit() string {
return c.Commit
}
// GetBuildDate returns debug flag
func (c *AppConfig) GetBuildDate() string {
return c.BuildDate
}
// GetName returns debug flag
func (c *AppConfig) GetName() string {
return c.Name
}
// GetBuildSource returns the source of the build. For builds from goreleaser
// this will be binaryBuild
func (c *AppConfig) GetBuildSource() string {
return c.BuildSource
}
// GetUserConfig returns the user config
func (c *AppConfig) GetUserConfig() *viper.Viper {
return c.UserConfig
}
// GetAppState returns the app state
func (c *AppConfig) GetAppState() *AppState {
return c.AppState
}
func newViper(filename string) (*viper.Viper, error) {
v := viper.New()
v.SetConfigType("yaml")
v.SetConfigName(filename)
return v, nil
}
// LoadConfig gets the user's config
func LoadConfig(filename string, withDefaults bool) (*viper.Viper, error) {
v, err := newViper(filename)
if err != nil {
return nil, err
}
if withDefaults {
if err = LoadDefaults(v, GetDefaultConfig()); err != nil {
return nil, err
}
if err = LoadDefaults(v, GetPlatformDefaultConfig()); err != nil {
return nil, err
}
}
if err = LoadAndMergeFile(v, filename+".yml"); err != nil {
return nil, err
}
return v, nil
}
// LoadDefaults loads in the defaults defined in this file
func LoadDefaults(v *viper.Viper, defaults []byte) error {
return v.MergeConfig(bytes.NewBuffer(defaults))
}
func prepareConfigFile(filename string) (string, error) {
// chucking my name there is not for vanity purposes, the xdg spec (and that
// function) requires a vendor name. May as well line up with github
configDirs := configdir.New("jesseduffield", "lazygit")
folder := configDirs.QueryFolderContainsFile(filename)
if folder == nil {
// create the file as empty
folders := configDirs.QueryFolders(configdir.Global)
if err := folders[0].WriteFile(filename, []byte{}); err != nil {
return "", err
}
folder = configDirs.QueryFolderContainsFile(filename)
}
return filepath.Join(folder.Path, filename), nil
}
// LoadAndMergeFile Loads the config/state file, creating
// the file as an empty one if it does not exist
func LoadAndMergeFile(v *viper.Viper, filename string) error {
configPath, err := prepareConfigFile(filename)
if err != nil {
return err
}
v.AddConfigPath(filepath.Dir(configPath))
return v.MergeInConfig()
}
// WriteToUserConfig adds a key/value pair to the user's config and saves it
func (c *AppConfig) WriteToUserConfig(key, value string) error {
// reloading the user config directly (without defaults) so that we're not
// writing any defaults back to the user's config
v, err := LoadConfig("config", false)
if err != nil {
return err
}
v.Set(key, value)
return v.WriteConfig()
}
// SaveAppState marhsalls the AppState struct and writes it to the disk
func (c *AppConfig) SaveAppState() error {
marshalledAppState, err := yaml.Marshal(c.AppState)
if err != nil {
return err
}
filepath, err := prepareConfigFile("state.yml")
if err != nil {
return err
}
return ioutil.WriteFile(filepath, marshalledAppState, 0644)
}
// LoadAppState loads recorded AppState from file
func (c *AppConfig) LoadAppState() error {
filepath, err := prepareConfigFile("state.yml")
if err != nil {
return err
}
appStateBytes, err := ioutil.ReadFile(filepath)
if err != nil {
return err
}
if len(appStateBytes) == 0 {
return yaml.Unmarshal(getDefaultAppState(), c.AppState)
}
return yaml.Unmarshal(appStateBytes, c.AppState)
}
// GetDefaultConfig returns the application default configuration
func GetDefaultConfig() []byte {
return []byte(
`gui:
## stuff relating to the UI
scrollHeight: 2
theme:
activeBorderColor:
- white
- bold
inactiveBorderColor:
- white
optionsTextColor:
- blue
commitLength:
show: true
update:
method: prompt # can be: prompt | background | never
days: 14 # how often a update is checked for
reporting: 'undetermined' # one of: 'on' | 'off' | 'undetermined'
confirmOnQuit: false
`)
}
// AppState stores data between runs of the app like when the last update check
// was performed and which other repos have been checked out
type AppState struct {
LastUpdateCheck int64
RecentRepos []string
}
func getDefaultAppState() []byte {
return []byte(`
lastUpdateCheck: 0
recentRepos: []
`)
}
// // commenting this out until we use it again
// func homeDirectory() string {
// usr, err := user.Current()
// if err != nil {
// log.Fatal(err)
// }
// return usr.HomeDir
// }
+10
View File
@@ -0,0 +1,10 @@
// +build !windows,!linux
package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() []byte {
return []byte(
`os:
openCommand: 'open {{filename}}'`)
}
+8
View File
@@ -0,0 +1,8 @@
package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() []byte {
return []byte(
`os:
openCommand: 'sh -c "xdg-open {{filename}} >/dev/null"'`)
}
+8
View File
@@ -0,0 +1,8 @@
package config
// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() []byte {
return []byte(
`os:
openCommand: 'cmd /c "start "" {{filename}}"'`)
}
+163
View File
@@ -0,0 +1,163 @@
package git
import (
"regexp"
"strings"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus"
"gopkg.in/src-d/go-git.v4/plumbing"
)
// context:
// we want to only show 'safe' branches (ones that haven't e.g. been deleted)
// which `git branch -a` gives us, but we also want the recency data that
// git reflog gives us.
// So we get the HEAD, then append get the reflog branches that intersect with
// our safe branches, then add the remaining safe branches, ensuring uniqueness
// along the way
// BranchListBuilder returns a list of Branch objects for the current repo
type BranchListBuilder struct {
Log *logrus.Entry
GitCommand *commands.GitCommand
}
// NewBranchListBuilder builds a new branch list builder
func NewBranchListBuilder(log *logrus.Entry, gitCommand *commands.GitCommand) (*BranchListBuilder, error) {
return &BranchListBuilder{
Log: log,
GitCommand: gitCommand,
}, nil
}
func (b *BranchListBuilder) obtainCurrentBranch() *commands.Branch {
// I used go-git for this, but that breaks if you've just done a git init,
// even though you're on 'master'
branchName, err := b.GitCommand.OSCommand.RunCommandWithOutput("git symbolic-ref --short HEAD")
if err != nil {
branchName, err = b.GitCommand.OSCommand.RunCommandWithOutput("git rev-parse --short HEAD")
if err != nil {
panic(err.Error())
}
}
return &commands.Branch{Name: strings.TrimSpace(branchName), Recency: " *"}
}
func (b *BranchListBuilder) obtainReflogBranches() []*commands.Branch {
branches := make([]*commands.Branch, 0)
rawString, err := b.GitCommand.OSCommand.RunCommandWithOutput("git reflog -n100 --pretty='%cr|%gs' --grep-reflog='checkout: moving' HEAD")
if err != nil {
return branches
}
branchLines := utils.SplitLines(rawString)
for _, line := range branchLines {
timeNumber, timeUnit, branchName := branchInfoFromLine(line)
timeUnit = abbreviatedTimeUnit(timeUnit)
branch := &commands.Branch{Name: branchName, Recency: timeNumber + timeUnit}
branches = append(branches, branch)
}
return branches
}
func (b *BranchListBuilder) obtainSafeBranches() []*commands.Branch {
branches := make([]*commands.Branch, 0)
bIter, err := b.GitCommand.Repo.Branches()
if err != nil {
panic(err)
}
err = bIter.ForEach(func(b *plumbing.Reference) error {
name := b.Name().Short()
branches = append(branches, &commands.Branch{Name: name})
return nil
})
return branches
}
func (b *BranchListBuilder) appendNewBranches(finalBranches, newBranches, existingBranches []*commands.Branch, included bool) []*commands.Branch {
for _, newBranch := range newBranches {
if included == branchIncluded(newBranch.Name, existingBranches) {
finalBranches = append(finalBranches, newBranch)
}
}
return finalBranches
}
func sanitisedReflogName(reflogBranch *commands.Branch, safeBranches []*commands.Branch) string {
for _, safeBranch := range safeBranches {
if strings.ToLower(safeBranch.Name) == strings.ToLower(reflogBranch.Name) {
return safeBranch.Name
}
}
return reflogBranch.Name
}
// Build the list of branches for the current repo
func (b *BranchListBuilder) Build() []*commands.Branch {
branches := make([]*commands.Branch, 0)
head := b.obtainCurrentBranch()
safeBranches := b.obtainSafeBranches()
if len(safeBranches) == 0 {
return append(branches, head)
}
reflogBranches := b.obtainReflogBranches()
reflogBranches = uniqueByName(append([]*commands.Branch{head}, reflogBranches...))
for i, reflogBranch := range reflogBranches {
reflogBranches[i].Name = sanitisedReflogName(reflogBranch, safeBranches)
}
branches = b.appendNewBranches(branches, reflogBranches, safeBranches, true)
branches = b.appendNewBranches(branches, safeBranches, branches, false)
return branches
}
func branchIncluded(branchName string, branches []*commands.Branch) bool {
for _, existingBranch := range branches {
if strings.ToLower(existingBranch.Name) == strings.ToLower(branchName) {
return true
}
}
return false
}
func uniqueByName(branches []*commands.Branch) []*commands.Branch {
finalBranches := make([]*commands.Branch, 0)
for _, branch := range branches {
if branchIncluded(branch.Name, finalBranches) {
continue
}
finalBranches = append(finalBranches, branch)
}
return finalBranches
}
// A line will have the form '10 days ago master' so we need to strip out the
// useful information from that into timeNumber, timeUnit, and branchName
func branchInfoFromLine(line string) (string, string, string) {
r := regexp.MustCompile("\\|.*\\s")
line = r.ReplaceAllString(line, " ")
words := strings.Split(line, " ")
return words[0], words[1], words[len(words)-1]
}
func abbreviatedTimeUnit(timeUnit string) string {
r := regexp.MustCompile("s$")
timeUnit = r.ReplaceAllString(timeUnit, "")
timeUnitMap := map[string]string{
"hour": "h",
"minute": "m",
"second": "s",
"week": "w",
"year": "y",
"day": "d",
"month": "m",
}
return timeUnitMap[timeUnit]
}
+44
View File
@@ -0,0 +1,44 @@
package gui
import "github.com/jesseduffield/lazygit/pkg/utils"
type appStatus struct {
name string
statusType string
duration int
}
type statusManager struct {
statuses []appStatus
}
func (m *statusManager) removeStatus(name string) {
newStatuses := []appStatus{}
for _, status := range m.statuses {
if status.name != name {
newStatuses = append(newStatuses, status)
}
}
m.statuses = newStatuses
}
func (m *statusManager) addWaitingStatus(name string) {
m.removeStatus(name)
newStatus := appStatus{
name: name,
statusType: "waiting",
duration: 0,
}
m.statuses = append([]appStatus{newStatus}, m.statuses...)
}
func (m *statusManager) getStatusString() string {
if len(m.statuses) == 0 {
return ""
}
topStatus := m.statuses[0]
if topStatus.statusType == "waiting" {
return topStatus.name + " " + utils.Loader()
}
return topStatus.name
}
+168
View File
@@ -0,0 +1,168 @@
package gui
import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/git"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) handleBranchPress(g *gocui.Gui, v *gocui.View) error {
index := gui.getItemPosition(gui.getBranchesView(g))
if index == 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("AlreadyCheckedOutBranch"))
}
branch := gui.getSelectedBranch(gui.getBranchesView(g))
if err := gui.GitCommand.Checkout(branch.Name, false); err != nil {
gui.createErrorPanel(g, err.Error())
}
return gui.refreshSidePanels(g)
}
func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error {
branch := gui.getSelectedBranch(v)
message := gui.Tr.SLocalize("SureForceCheckout")
title := gui.Tr.SLocalize("ForceCheckoutBranch")
return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.Checkout(branch.Name, true); err != nil {
gui.createErrorPanel(g, err.Error())
}
return gui.refreshSidePanels(g)
}, nil)
}
func (gui *Gui) handleCheckoutByName(g *gocui.Gui, v *gocui.View) error {
gui.createPromptPanel(g, v, gui.Tr.SLocalize("BranchName")+":", func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.Checkout(gui.trimmedContent(v), false); err != nil {
return gui.createErrorPanel(g, err.Error())
}
return gui.refreshSidePanels(g)
})
return nil
}
func (gui *Gui) handleNewBranch(g *gocui.Gui, v *gocui.View) error {
branch := gui.State.Branches[0]
message := gui.Tr.TemplateLocalize(
"NewBranchNameBranchOff",
Teml{
"branchName": branch.Name,
},
)
gui.createPromptPanel(g, v, message, func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.NewBranch(gui.trimmedContent(v)); err != nil {
return gui.createErrorPanel(g, err.Error())
}
gui.refreshSidePanels(g)
return gui.handleBranchSelect(g, v)
})
return nil
}
func (gui *Gui) handleDeleteBranch(g *gocui.Gui, v *gocui.View) error {
return gui.deleteBranch(g, v, false)
}
func (gui *Gui) handleForceDeleteBranch(g *gocui.Gui, v *gocui.View) error {
return gui.deleteBranch(g, v, true)
}
func (gui *Gui) deleteBranch(g *gocui.Gui, v *gocui.View, force bool) error {
checkedOutBranch := gui.State.Branches[0]
selectedBranch := gui.getSelectedBranch(v)
if checkedOutBranch.Name == selectedBranch.Name {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantDeleteCheckOutBranch"))
}
title := gui.Tr.SLocalize("DeleteBranch")
var messageId string
if force {
messageId = "ForceDeleteBranchMessage"
} else {
messageId = "DeleteBranchMessage"
}
message := gui.Tr.TemplateLocalize(
messageId,
Teml{
"selectedBranchName": selectedBranch.Name,
},
)
return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.DeleteBranch(selectedBranch.Name, force); err != nil {
return gui.createErrorPanel(g, err.Error())
}
return gui.refreshSidePanels(g)
}, nil)
}
func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
checkedOutBranch := gui.State.Branches[0]
selectedBranch := gui.getSelectedBranch(v)
defer gui.refreshSidePanels(g)
if checkedOutBranch.Name == selectedBranch.Name {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantMergeBranchIntoItself"))
}
if err := gui.GitCommand.Merge(selectedBranch.Name); err != nil {
return gui.createErrorPanel(g, err.Error())
}
return nil
}
func (gui *Gui) getSelectedBranch(v *gocui.View) *commands.Branch {
lineNumber := gui.getItemPosition(v)
return gui.State.Branches[lineNumber]
}
func (gui *Gui) renderBranchesOptions(g *gocui.Gui) error {
return gui.renderGlobalOptions(g)
}
// may want to standardise how these select methods work
func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error {
if err := gui.renderBranchesOptions(g); err != nil {
return err
}
// This really shouldn't happen: there should always be a master branch
if len(gui.State.Branches) == 0 {
return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo"))
}
go func() {
branch := gui.getSelectedBranch(v)
diff, err := gui.GitCommand.GetBranchGraph(branch.Name)
if err != nil && strings.HasPrefix(diff, "fatal: ambiguous argument") {
diff = gui.Tr.SLocalize("NoTrackingThisBranch")
}
gui.renderString(g, "main", diff)
}()
return nil
}
// gui.refreshStatus is called at the end of this because that's when we can
// be sure there is a state.Branches array to pick the current branch from
func (gui *Gui) refreshBranches(g *gocui.Gui) error {
g.Update(func(g *gocui.Gui) error {
v, err := g.View("branches")
if err != nil {
panic(err)
}
builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand)
if err != nil {
return err
}
gui.State.Branches = builder.Build()
v.Clear()
list, err := utils.RenderList(gui.State.Branches)
if err != nil {
return err
}
fmt.Fprint(v, list)
gui.resetOrigin(v)
return gui.refreshStatus(g)
})
return nil
}
+91
View File
@@ -0,0 +1,91 @@
package gui
import (
"strconv"
"strings"
"github.com/jesseduffield/gocui"
)
func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error {
message := gui.trimmedContent(v)
if message == "" {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CommitWithoutMessageErr"))
}
sub, err := gui.GitCommand.Commit(message)
if err != nil {
// TODO need to find a way to send through this error
if err != gui.Errors.ErrSubProcess {
return gui.createErrorPanel(g, err.Error())
}
}
if sub != nil {
gui.SubProcess = sub
return gui.Errors.ErrSubProcess
}
gui.refreshFiles(g)
v.Clear()
v.SetCursor(0, 0)
g.SetViewOnBottom("commitMessage")
gui.switchFocus(g, v, gui.getFilesView(g))
return gui.refreshCommits(g)
}
func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error {
g.SetViewOnBottom("commitMessage")
return gui.switchFocus(g, v, gui.getFilesView(g))
}
func (gui *Gui) handleCommitFocused(g *gocui.Gui, v *gocui.View) error {
if _, err := g.SetViewOnTop("commitMessage"); err != nil {
return err
}
message := gui.Tr.TemplateLocalize(
"CloseConfirm",
Teml{
"keyBindClose": "esc",
"keyBindConfirm": "enter",
},
)
return gui.renderString(g, "options", message)
}
func (gui *Gui) simpleEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
switch {
case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
v.EditDelete(true)
case key == gocui.KeyDelete:
v.EditDelete(false)
case key == gocui.KeyArrowDown:
v.MoveCursor(0, 1, false)
case key == gocui.KeyArrowUp:
v.MoveCursor(0, -1, false)
case key == gocui.KeyArrowLeft:
v.MoveCursor(-1, 0, false)
case key == gocui.KeyArrowRight:
v.MoveCursor(1, 0, false)
case key == gocui.KeyTab:
v.EditNewLine()
case key == gocui.KeySpace:
v.EditWrite(' ')
case key == gocui.KeyInsert:
v.Overwrite = !v.Overwrite
default:
v.EditWrite(ch)
}
gui.RenderCommitLength()
}
func (gui *Gui) getBufferLength(view *gocui.View) string {
return " " + strconv.Itoa(strings.Count(view.Buffer(), "")-1) + " "
}
func (gui *Gui) RenderCommitLength() {
if !gui.Config.GetUserConfig().GetBool("gui.commitLength.show") {
return
}
v := gui.getCommitMessageView(gui.g)
v.Subtitle = gui.getBufferLength(v)
}
+173
View File
@@ -0,0 +1,173 @@
package gui
import (
"errors"
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) refreshCommits(g *gocui.Gui) error {
g.Update(func(*gocui.Gui) error {
gui.State.Commits = gui.GitCommand.GetCommits()
v, err := g.View("commits")
if err != nil {
panic(err)
}
v.Clear()
list, err := utils.RenderList(gui.State.Commits)
if err != nil {
return err
}
fmt.Fprint(v, list)
gui.refreshStatus(g)
if g.CurrentView().Name() == "commits" {
gui.handleCommitSelect(g, v)
}
return nil
})
return nil
}
func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error {
return gui.createConfirmationPanel(g, commitView, gui.Tr.SLocalize("ResetToCommit"), gui.Tr.SLocalize("SureResetThisCommit"), func(g *gocui.Gui, v *gocui.View) error {
commit, err := gui.getSelectedCommit(g)
if err != nil {
panic(err)
}
if err := gui.GitCommand.ResetToCommit(commit.Sha); err != nil {
return gui.createErrorPanel(g, err.Error())
}
if err := gui.refreshCommits(g); err != nil {
panic(err)
}
if err := gui.refreshFiles(g); err != nil {
panic(err)
}
gui.resetOrigin(commitView)
return gui.handleCommitSelect(g, nil)
}, nil)
}
func (gui *Gui) renderCommitsOptions(g *gocui.Gui) error {
return gui.renderGlobalOptions(g)
}
func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error {
if err := gui.renderCommitsOptions(g); err != nil {
return err
}
commit, err := gui.getSelectedCommit(g)
if err != nil {
if err.Error() != gui.Tr.SLocalize("NoCommitsThisBranch") {
return err
}
return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch"))
}
commitText := gui.GitCommand.Show(commit.Sha)
return gui.renderString(g, "main", commitText)
}
func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
if gui.getItemPosition(v) != 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlySquashTopmostCommit"))
}
if len(gui.State.Commits) == 1 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("YouNoCommitsToSquash"))
}
commit, err := gui.getSelectedCommit(g)
if err != nil {
return err
}
if err := gui.GitCommand.SquashPreviousTwoCommits(commit.Name); err != nil {
return gui.createErrorPanel(g, err.Error())
}
if err := gui.refreshCommits(g); err != nil {
panic(err)
}
gui.refreshStatus(g)
return gui.handleCommitSelect(g, v)
}
// TODO: move to files panel
func (gui *Gui) anyUnStagedChanges(files []*commands.File) bool {
for _, file := range files {
if file.Tracked && file.HasUnstagedChanges {
return true
}
}
return false
}
func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error {
if len(gui.State.Commits) == 1 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("YouNoCommitsToSquash"))
}
if gui.anyUnStagedChanges(gui.State.Files) {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantFixupWhileUnstagedChanges"))
}
branch := gui.State.Branches[0]
commit, err := gui.getSelectedCommit(g)
if err != nil {
return err
}
message := gui.Tr.SLocalize("SureFixupThisCommit")
gui.createConfirmationPanel(g, v, gui.Tr.SLocalize("Fixup"), message, func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.SquashFixupCommit(branch.Name, commit.Sha); err != nil {
return gui.createErrorPanel(g, err.Error())
}
if err := gui.refreshCommits(g); err != nil {
panic(err)
}
return gui.refreshStatus(g)
}, nil)
return nil
}
func (gui *Gui) handleRenameCommit(g *gocui.Gui, v *gocui.View) error {
if gui.getItemPosition(gui.getCommitsView(g)) != 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit"))
}
return gui.createPromptPanel(g, v, gui.Tr.SLocalize("renameCommit"), func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.RenameCommit(v.Buffer()); err != nil {
return gui.createErrorPanel(g, err.Error())
}
if err := gui.refreshCommits(g); err != nil {
panic(err)
}
return gui.handleCommitSelect(g, v)
})
}
func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error {
if gui.getItemPosition(gui.getCommitsView(g)) != 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("OnlyRenameTopCommit"))
}
gui.SubProcess = gui.GitCommand.PrepareCommitAmendSubProcess()
g.Update(func(g *gocui.Gui) error {
return gui.Errors.ErrSubProcess
})
return nil
}
func (gui *Gui) getSelectedCommit(g *gocui.Gui) (*commands.Commit, error) {
v, err := g.View("commits")
if err != nil {
panic(err)
}
if len(gui.State.Commits) == 0 {
return &commands.Commit{}, errors.New(gui.Tr.SLocalize("NoCommitsThisBranch"))
}
lineNumber := gui.getItemPosition(v)
if lineNumber > len(gui.State.Commits)-1 {
gui.Log.Info(gui.Tr.SLocalize("PotentialErrInGetselectedCommit"), gui.State.Commits, lineNumber)
return gui.State.Commits[len(gui.State.Commits)-1], nil
}
return gui.State.Commits[lineNumber], nil
}
+145
View File
@@ -0,0 +1,145 @@
// lots of this has been directly ported from one of the example files, will brush up later
// Copyright 2014 The gocui Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gui
import (
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
)
func (gui *Gui) wrappedConfirmationFunction(function func(*gocui.Gui, *gocui.View) error) func(*gocui.Gui, *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
if function != nil {
if err := function(g, v); err != nil {
return err
}
}
return gui.closeConfirmationPrompt(g)
}
}
func (gui *Gui) closeConfirmationPrompt(g *gocui.Gui) error {
view, err := g.View("confirmation")
if err != nil {
panic(err)
}
if err := gui.returnFocus(g, view); err != nil {
panic(err)
}
g.DeleteKeybindings("confirmation")
return g.DeleteView("confirmation")
}
func (gui *Gui) getMessageHeight(message string, width int) int {
lines := strings.Split(message, "\n")
lineCount := 0
for _, line := range lines {
lineCount += len(line)/width + 1
}
return lineCount
}
func (gui *Gui) getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, int) {
width, height := g.Size()
panelWidth := width / 2
panelHeight := gui.getMessageHeight(prompt, panelWidth)
return width/2 - panelWidth/2,
height/2 - panelHeight/2 - panelHeight%2 - 1,
width/2 + panelWidth/2,
height/2 + panelHeight/2
}
func (gui *Gui) createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, handleConfirm func(*gocui.Gui, *gocui.View) error) error {
gui.onNewPopupPanel()
confirmationView, err := gui.prepareConfirmationPanel(currentView, title, "")
if err != nil {
return err
}
confirmationView.Editable = true
return gui.setKeyBindings(g, handleConfirm, nil)
}
func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt string) (*gocui.View, error) {
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(gui.g, prompt)
confirmationView, err := gui.g.SetView("confirmation", x0, y0, x1, y1, 0)
if err != nil {
if err != gocui.ErrUnknownView {
return nil, err
}
confirmationView.Title = title
confirmationView.FgColor = gocui.ColorWhite
}
confirmationView.Clear()
if err := gui.switchFocus(gui.g, currentView, confirmationView); err != nil {
return nil, err
}
return confirmationView, nil
}
func (gui *Gui) onNewPopupPanel() {
gui.g.SetViewOnBottom("commitMessage")
}
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
gui.onNewPopupPanel()
g.Update(func(g *gocui.Gui) error {
// delete the existing confirmation panel if it exists
if view, _ := g.View("confirmation"); view != nil {
if err := gui.closeConfirmationPrompt(g); err != nil {
errMessage := gui.Tr.TemplateLocalize(
"CantCloseConfirmationPrompt",
Teml{
"error": err.Error(),
},
)
gui.Log.Error(errMessage)
}
}
confirmationView, err := gui.prepareConfirmationPanel(currentView, title, prompt)
if err != nil {
return err
}
confirmationView.Editable = false
if err := gui.renderString(g, "confirmation", prompt); err != nil {
return err
}
return gui.setKeyBindings(g, handleConfirm, handleClose)
})
return nil
}
func (gui *Gui) setKeyBindings(g *gocui.Gui, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
actions := gui.Tr.TemplateLocalize(
"CloseConfirm",
Teml{
"keyBindClose": "esc",
"keyBindConfirm": "enter",
},
)
if err := gui.renderString(g, "options", actions); err != nil {
return err
}
if err := g.SetKeybinding("confirmation", gocui.KeyEnter, gocui.ModNone, gui.wrappedConfirmationFunction(handleConfirm)); err != nil {
return err
}
return g.SetKeybinding("confirmation", gocui.KeyEsc, gocui.ModNone, gui.wrappedConfirmationFunction(handleClose))
}
func (gui *Gui) createMessagePanel(g *gocui.Gui, currentView *gocui.View, title, prompt string) error {
return gui.createConfirmationPanel(g, currentView, title, prompt, nil, nil)
}
func (gui *Gui) createErrorPanel(g *gocui.Gui, message string) error {
gui.Log.Error(message)
currentView := g.CurrentView()
colorFunction := color.New(color.FgRed).SprintFunc()
coloredMessage := colorFunction(strings.TrimSpace(message))
return gui.createConfirmationPanel(g, currentView, gui.Tr.SLocalize("Error"), coloredMessage, nil, nil)
}
+407
View File
@@ -0,0 +1,407 @@
package gui
import (
// "io"
// "io/ioutil"
// "strings"
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) stagedFiles() []*commands.File {
files := gui.State.Files
result := make([]*commands.File, 0)
for _, file := range files {
if file.HasStagedChanges {
result = append(result, file)
}
}
return result
}
func (gui *Gui) trackedFiles() []*commands.File {
files := gui.State.Files
result := make([]*commands.File, 0)
for _, file := range files {
if file.Tracked {
result = append(result, file)
}
}
return result
}
func (gui *Gui) stageSelectedFile(g *gocui.Gui) error {
file, err := gui.getSelectedFile(g)
if err != nil {
return err
}
return gui.GitCommand.StageFile(file.Name)
}
func (gui *Gui) handleFilePress(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
if err == gui.Errors.ErrNoFiles {
return nil
}
return err
}
if file.HasMergeConflicts {
return gui.handleSwitchToMerge(g, v)
}
if file.HasUnstagedChanges {
gui.GitCommand.StageFile(file.Name)
} else {
gui.GitCommand.UnStageFile(file.Name, file.Tracked)
}
if err := gui.refreshFiles(g); err != nil {
return err
}
return gui.handleFileSelect(g, v)
}
func (gui *Gui) allFilesStaged() bool {
for _, file := range gui.State.Files {
if file.HasUnstagedChanges {
return false
}
}
return true
}
func (gui *Gui) handleStageAll(g *gocui.Gui, v *gocui.View) error {
var err error
if gui.allFilesStaged() {
err = gui.GitCommand.UnstageAll()
} else {
err = gui.GitCommand.StageAll()
}
if err != nil {
_ = gui.createErrorPanel(g, err.Error())
}
if err := gui.refreshFiles(g); err != nil {
return err
}
return gui.handleFileSelect(g, v)
}
func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
if err == gui.Errors.ErrNoFiles {
return nil
}
return err
}
if !file.HasUnstagedChanges {
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileHasNoUnstagedChanges"))
}
if !file.Tracked {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CannotGitAdd"))
}
gui.SubProcess = gui.GitCommand.AddPatch(file.Name)
return gui.Errors.ErrSubProcess
}
func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) {
if len(gui.State.Files) == 0 {
return &commands.File{}, gui.Errors.ErrNoFiles
}
filesView, err := g.View("files")
if err != nil {
panic(err)
}
lineNumber := gui.getItemPosition(filesView)
return gui.State.Files[lineNumber], nil
}
func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
if err == gui.Errors.ErrNoFiles {
return nil
}
return err
}
var deleteVerb string
if file.Tracked {
deleteVerb = gui.Tr.SLocalize("checkout")
} else {
deleteVerb = gui.Tr.SLocalize("delete")
}
message := gui.Tr.TemplateLocalize(
"SureTo",
Teml{
"deleteVerb": deleteVerb,
"fileName": file.Name,
},
)
return gui.createConfirmationPanel(g, v, strings.Title(deleteVerb)+" file", message, func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.RemoveFile(file); err != nil {
return err
}
return gui.refreshFiles(g)
}, nil)
}
func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
return gui.createErrorPanel(g, err.Error())
}
if file.Tracked {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantIgnoreTrackFiles"))
}
if err := gui.GitCommand.Ignore(file.Name); err != nil {
return gui.createErrorPanel(g, err.Error())
}
return gui.refreshFiles(g)
}
func (gui *Gui) renderfilesOptions(g *gocui.Gui, file *commands.File) error {
return gui.renderGlobalOptions(g)
}
func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
if err != gui.Errors.ErrNoFiles {
return err
}
gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles"))
return gui.renderfilesOptions(g, nil)
}
if err := gui.renderfilesOptions(g, file); err != nil {
return err
}
var content string
if file.HasMergeConflicts {
return gui.refreshMergePanel(g)
}
content = gui.GitCommand.Diff(file)
return gui.renderString(g, "main", content)
}
func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && !gui.State.HasMergeConflicts {
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
}
commitMessageView := gui.getCommitMessageView(g)
g.Update(func(g *gocui.Gui) error {
g.SetViewOnTop("commitMessage")
gui.switchFocus(g, filesView, commitMessageView)
gui.RenderCommitLength()
return nil
})
return nil
}
// handleCommitEditorPress - handle when the user wants to commit changes via
// their editor rather than via the popup panel
func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles()) == 0 && !gui.State.HasMergeConflicts {
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
}
gui.PrepareSubProcess(g, "git", "commit")
return nil
}
// PrepareSubProcess - prepare a subprocess for execution and tell the gui to switch to it
func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) {
gui.SubProcess = gui.GitCommand.PrepareCommitSubProcess()
g.Update(func(g *gocui.Gui) error {
return gui.Errors.ErrSubProcess
})
}
func (gui *Gui) editFile(filename string) error {
sub, err := gui.OSCommand.EditFile(filename)
if err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
if sub != nil {
gui.SubProcess = sub
return gui.Errors.ErrSubProcess
}
return nil
}
func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
return err
}
return gui.editFile(file.Name)
}
func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
return err
}
return gui.openFile(file.Name)
}
func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error {
return gui.refreshFiles(g)
}
func (gui *Gui) refreshStateFiles() {
// get files to stage
files := gui.GitCommand.GetStatusFiles()
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
gui.updateHasMergeConflictStatus()
}
func (gui *Gui) updateHasMergeConflictStatus() error {
merging, err := gui.GitCommand.IsInMergeState()
if err != nil {
return err
}
gui.State.HasMergeConflicts = merging
return nil
}
func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
item, err := gui.getSelectedFile(g)
if err != nil {
if err != gui.Errors.ErrNoFiles {
return "", err
}
return "", gui.renderString(g, "main", gui.Tr.SLocalize("NoFilesDisplay"))
}
if item.Type != "file" {
return "", gui.renderString(g, "main", gui.Tr.SLocalize("NotAFile"))
}
cat, err := gui.GitCommand.CatFile(item.Name)
if err != nil {
gui.Log.Error(err)
return "", gui.renderString(g, "main", err.Error())
}
return cat, nil
}
func (gui *Gui) refreshFiles(g *gocui.Gui) error {
filesView, err := g.View("files")
if err != nil {
return err
}
gui.refreshStateFiles()
filesView.Clear()
list, err := utils.RenderList(gui.State.Files)
if err != nil {
return err
}
fmt.Fprint(filesView, list)
gui.correctCursor(filesView)
if filesView == g.CurrentView() {
gui.handleFileSelect(g, filesView)
}
return nil
}
func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error {
gui.createMessagePanel(g, v, "", gui.Tr.SLocalize("PullWait"))
go func() {
if err := gui.GitCommand.Pull(); err != nil {
gui.createErrorPanel(g, err.Error())
} else {
gui.closeConfirmationPrompt(g)
gui.refreshCommits(g)
gui.refreshStatus(g)
}
gui.refreshFiles(g)
}()
return nil
}
func (gui *Gui) pushWithForceFlag(currentView *gocui.View, force bool) error {
if err := gui.createMessagePanel(gui.g, currentView, "", gui.Tr.SLocalize("PushWait")); err != nil {
return err
}
go func() {
branchName := gui.State.Branches[0].Name
if err := gui.GitCommand.Push(branchName, force); err != nil {
_ = gui.createErrorPanel(gui.g, err.Error())
} else {
_ = gui.closeConfirmationPrompt(gui.g)
_ = gui.refreshCommits(gui.g)
_ = gui.refreshStatus(gui.g)
}
}()
return nil
}
func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
// if we have pullables we'll ask if the user wants to force push
_, pullables := gui.GitCommand.UpstreamDifferenceCount()
if pullables == "?" || pullables == "0" {
return gui.pushWithForceFlag(v, false)
}
err := gui.createConfirmationPanel(g, nil, gui.Tr.SLocalize("ForcePush"), gui.Tr.SLocalize("ForcePushPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.pushWithForceFlag(v, true)
}, nil)
return err
}
func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
mergeView, err := g.View("main")
if err != nil {
return err
}
file, err := gui.getSelectedFile(g)
if err != nil {
if err != gui.Errors.ErrNoFiles {
return err
}
return nil
}
if !file.HasMergeConflicts {
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileNoMergeCons"))
}
gui.switchFocus(g, v, mergeView)
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.AbortMerge(); err != nil {
return gui.createErrorPanel(g, err.Error())
}
gui.createMessagePanel(g, v, "", gui.Tr.SLocalize("MergeAborted"))
gui.refreshStatus(g)
return gui.refreshFiles(g)
}
func (gui *Gui) handleResetHard(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(g, v, gui.Tr.SLocalize("ClearFilePanel"), gui.Tr.SLocalize("SureResetHardHead"), func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.ResetHard(); err != nil {
gui.createErrorPanel(g, err.Error())
}
return gui.refreshFiles(g)
}, nil)
}
func (gui *Gui) openFile(filename string) error {
if err := gui.OSCommand.OpenFile(filename); err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
return nil
}
+437
View File
@@ -0,0 +1,437 @@
package gui
import (
// "io"
// "io/ioutil"
"errors"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
"time"
// "strings"
"github.com/golang-collections/collections/stack"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/updates"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sirupsen/logrus"
)
// OverlappingEdges determines if panel edges overlap
var OverlappingEdges = false
// SentinelErrors are the errors that have special meaning and need to be checked
// by calling functions. The less of these, the better
type SentinelErrors struct {
ErrSubProcess error
ErrNoFiles error
ErrSwitchRepo error
}
// GenerateSentinelErrors makes the sentinel errors for the gui. We're defining it here
// because we can't do package-scoped errors with localization, and also because
// it seems like package-scoped variables are bad in general
// https://dave.cheney.net/2017/06/11/go-without-package-scoped-variables
// In the future it would be good to implement some of the recommendations of
// that article. For now, if we don't need an error to be a sentinel, we will just
// define it inline. This has implications for error messages that pop up everywhere
// in that we'll be duplicating the default values. We may need to look at
// having a default localisation bundle defined, and just using keys-only when
// localising things in the code.
func (gui *Gui) GenerateSentinelErrors() {
gui.Errors = SentinelErrors{
ErrSubProcess: errors.New(gui.Tr.SLocalize("RunningSubprocess")),
ErrNoFiles: errors.New(gui.Tr.SLocalize("NoChangedFiles")),
ErrSwitchRepo: errors.New("switching repo"),
}
}
// Teml is short for template used to make the required map[string]interface{} shorter when using gui.Tr.SLocalize and gui.Tr.TemplateLocalize
type Teml i18n.Teml
// Gui wraps the gocui Gui object which handles rendering and events
type Gui struct {
g *gocui.Gui
Log *logrus.Entry
GitCommand *commands.GitCommand
OSCommand *commands.OSCommand
SubProcess *exec.Cmd
State guiState
Config config.AppConfigurer
Tr *i18n.Localizer
Errors SentinelErrors
Updater *updates.Updater
statusManager *statusManager
}
type guiState struct {
Files []*commands.File
Branches []*commands.Branch
Commits []*commands.Commit
StashEntries []*commands.StashEntry
PreviousView string
HasMergeConflicts bool
ConflictIndex int
ConflictTop bool
Conflicts []commands.Conflict
EditHistory *stack.Stack
Platform commands.Platform
Updating bool
}
// NewGui builds a new gui handler
func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config config.AppConfigurer, updater *updates.Updater) (*Gui, error) {
initialState := guiState{
Files: make([]*commands.File, 0),
PreviousView: "files",
Commits: make([]*commands.Commit, 0),
StashEntries: make([]*commands.StashEntry, 0),
ConflictIndex: 0,
ConflictTop: true,
Conflicts: make([]commands.Conflict, 0),
EditHistory: stack.New(),
Platform: *oSCommand.Platform,
}
gui := &Gui{
Log: log,
GitCommand: gitCommand,
OSCommand: oSCommand,
State: initialState,
Config: config,
Tr: tr,
Updater: updater,
statusManager: &statusManager{},
}
gui.GenerateSentinelErrors()
return gui, nil
}
func (gui *Gui) scrollUpMain(g *gocui.Gui, v *gocui.View) error {
mainView, _ := g.View("main")
ox, oy := mainView.Origin()
if oy >= 1 {
return mainView.SetOrigin(ox, oy-gui.Config.GetUserConfig().GetInt("gui.scrollHeight"))
}
return nil
}
func (gui *Gui) scrollDownMain(g *gocui.Gui, v *gocui.View) error {
mainView, _ := g.View("main")
ox, oy := mainView.Origin()
if oy < len(mainView.BufferLines()) {
return mainView.SetOrigin(ox, oy+gui.Config.GetUserConfig().GetInt("gui.scrollHeight"))
}
return nil
}
func (gui *Gui) handleRefresh(g *gocui.Gui, v *gocui.View) error {
return gui.refreshSidePanels(g)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// layout is called for every screen re-render e.g. when the screen is resized
func (gui *Gui) layout(g *gocui.Gui) error {
g.Highlight = true
width, height := g.Size()
version := gui.Config.GetVersion()
leftSideWidth := width / 3
statusFilesBoundary := 2
filesBranchesBoundary := 2 * height / 5 // height - 20
commitsBranchesBoundary := 3 * height / 5 // height - 10
commitsStashBoundary := height - 5 // height - 5
optionsVersionBoundary := width - max(len(version), 1)
minimumHeight := 16
minimumWidth := 10
appStatus := gui.statusManager.getStatusString()
appStatusOptionsBoundary := 0
if appStatus != "" {
appStatusOptionsBoundary = len(appStatus) + 2
}
panelSpacing := 1
if OverlappingEdges {
panelSpacing = 0
}
if height < minimumHeight || width < minimumWidth {
v, err := g.SetView("limit", 0, 0, max(width-1, 2), max(height-1, 2), 0)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("NotEnoughSpace")
v.Wrap = true
}
return nil
}
g.DeleteView("limit")
optionsTop := height - 2
// hiding options if there's not enough space
if height < 30 {
optionsTop = height - 1
}
v, err := g.SetView("main", leftSideWidth+panelSpacing, 0, width-1, optionsTop, gocui.LEFT)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("DiffTitle")
v.Wrap = true
v.FgColor = gocui.ColorWhite
}
if v, err := g.SetView("status", 0, 0, leftSideWidth, statusFilesBoundary, gocui.BOTTOM|gocui.RIGHT); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("StatusTitle")
v.FgColor = gocui.ColorWhite
}
filesView, err := g.SetView("files", 0, statusFilesBoundary+panelSpacing, leftSideWidth, filesBranchesBoundary, gocui.TOP|gocui.BOTTOM)
if err != nil {
if err != gocui.ErrUnknownView {
return err
}
filesView.Highlight = true
filesView.Title = gui.Tr.SLocalize("FilesTitle")
v.FgColor = gocui.ColorWhite
}
if v, err := g.SetView("branches", 0, filesBranchesBoundary+panelSpacing, leftSideWidth, commitsBranchesBoundary, gocui.TOP|gocui.BOTTOM); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("BranchesTitle")
v.FgColor = gocui.ColorWhite
}
if v, err := g.SetView("commits", 0, commitsBranchesBoundary+panelSpacing, leftSideWidth, commitsStashBoundary, gocui.TOP|gocui.BOTTOM); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("CommitsTitle")
v.FgColor = gocui.ColorWhite
}
if v, err := g.SetView("stash", 0, commitsStashBoundary+panelSpacing, leftSideWidth, optionsTop, gocui.TOP|gocui.RIGHT); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Title = gui.Tr.SLocalize("StashTitle")
v.FgColor = gocui.ColorWhite
}
if v, err := g.SetView("options", appStatusOptionsBoundary-1, optionsTop, optionsVersionBoundary-1, optionsTop+2, 0); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.Frame = false
if v.FgColor, err = gui.GetOptionsPanelTextColor(); err != nil {
return err
}
}
if gui.getCommitMessageView(g) == nil {
// doesn't matter where this view starts because it will be hidden
if commitMessageView, err := g.SetView("commitMessage", 0, 0, width/2, height/2, 0); err != nil {
if err != gocui.ErrUnknownView {
return err
}
g.SetViewOnBottom("commitMessage")
commitMessageView.Title = gui.Tr.SLocalize("CommitMessage")
commitMessageView.FgColor = gocui.ColorWhite
commitMessageView.Editable = true
commitMessageView.Editor = gocui.EditorFunc(gui.simpleEditor)
}
}
if appStatusView, err := g.SetView("appStatus", -1, optionsTop, width, optionsTop+2, 0); err != nil {
if err != gocui.ErrUnknownView {
return err
}
appStatusView.BgColor = gocui.ColorDefault
appStatusView.FgColor = gocui.ColorCyan
appStatusView.Frame = false
if _, err := g.SetViewOnBottom("appStatus"); err != nil {
return err
}
}
if v, err := g.SetView("version", optionsVersionBoundary-1, optionsTop, width, optionsTop+2, 0); err != nil {
if err != gocui.ErrUnknownView {
return err
}
v.BgColor = gocui.ColorDefault
v.FgColor = gocui.ColorGreen
v.Frame = false
if err := gui.renderString(g, "version", version); err != nil {
return err
}
// these are only called once (it's a place to put all the things you want
// to happen on startup after the screen is first rendered)
gui.Updater.CheckForNewUpdate(gui.onBackgroundUpdateCheckFinish, false)
if err := gui.updateRecentRepoList(); err != nil {
return err
}
gui.handleFileSelect(g, filesView)
gui.refreshFiles(g)
gui.refreshBranches(g)
gui.refreshCommits(g)
gui.refreshStashEntries(g)
if err := gui.switchFocus(g, nil, filesView); err != nil {
return err
}
if gui.Config.GetUserConfig().GetString("reporting") == "undetermined" {
if err := gui.promptAnonymousReporting(); err != nil {
return err
}
}
}
return gui.resizeCurrentPopupPanel(g)
}
func (gui *Gui) promptAnonymousReporting() error {
return gui.createConfirmationPanel(gui.g, nil, gui.Tr.SLocalize("AnonymousReportingTitle"), gui.Tr.SLocalize("AnonymousReportingPrompt"), func(g *gocui.Gui, v *gocui.View) error {
return gui.Config.WriteToUserConfig("reporting", "on")
}, func(g *gocui.Gui, v *gocui.View) error {
return gui.Config.WriteToUserConfig("reporting", "off")
})
}
func (gui *Gui) fetch(g *gocui.Gui) error {
gui.GitCommand.Fetch()
gui.refreshStatus(g)
return nil
}
func (gui *Gui) updateLoader(g *gocui.Gui) error {
if view, _ := g.View("confirmation"); view != nil {
content := gui.trimmedContent(view)
if strings.Contains(content, "...") {
staticContent := strings.Split(content, "...")[0] + "..."
if err := gui.renderString(g, "confirmation", staticContent+" "+utils.Loader()); err != nil {
return err
}
}
}
return nil
}
func (gui *Gui) renderAppStatus(g *gocui.Gui) error {
appStatus := gui.statusManager.getStatusString()
if appStatus != "" {
return gui.renderString(gui.g, "appStatus", appStatus)
}
return nil
}
func (gui *Gui) renderGlobalOptions(g *gocui.Gui) error {
return gui.renderOptionsMap(g, map[string]string{
"PgUp/PgDn": gui.Tr.SLocalize("scroll"),
"← → ↑ ↓": gui.Tr.SLocalize("navigate"),
"esc/q": gui.Tr.SLocalize("close"),
"x": gui.Tr.SLocalize("menu"),
})
}
func (gui *Gui) goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) {
go func() {
for range time.Tick(interval) {
function(g)
}
}()
}
// Run setup the gui with keybindings and start the mainloop
func (gui *Gui) Run() error {
g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges)
if err != nil {
return err
}
defer g.Close()
gui.g = g // TODO: always use gui.g rather than passing g around everywhere
if err := gui.SetColorScheme(); err != nil {
return err
}
gui.goEvery(g, time.Second*60, gui.fetch)
gui.goEvery(g, time.Second*10, gui.refreshFiles)
gui.goEvery(g, time.Millisecond*50, gui.updateLoader)
gui.goEvery(g, time.Millisecond*50, gui.renderAppStatus)
g.SetManagerFunc(gui.layout)
if err = gui.keybindings(g); err != nil {
return err
}
err = g.MainLoop()
return err
}
// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
// if the error returned from a run is a ErrSubProcess, it runs the subprocess
// otherwise it handles the error, possibly by quitting the application
func (gui *Gui) RunWithSubprocesses() {
for {
if err := gui.Run(); err != nil {
if err == gocui.ErrQuit {
break
} else if err == gui.Errors.ErrSwitchRepo {
continue
} else if err == gui.Errors.ErrSubProcess {
gui.SubProcess.Stdin = os.Stdin
gui.SubProcess.Stdout = os.Stdout
gui.SubProcess.Stderr = os.Stderr
gui.SubProcess.Run()
gui.SubProcess.Stdout = ioutil.Discard
gui.SubProcess.Stderr = ioutil.Discard
gui.SubProcess.Stdin = nil
gui.SubProcess = nil
} else {
log.Panicln(err)
}
}
}
}
func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error {
if gui.State.Updating {
return gui.createUpdateQuitConfirmation(g, v)
}
if gui.Config.GetUserConfig().GetBool("confirmOnQuit") {
return gui.createConfirmationPanel(g, v, "", gui.Tr.SLocalize("ConfirmQuit"), func(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}, nil)
}
return gocui.ErrQuit
}
+410
View File
@@ -0,0 +1,410 @@
package gui
import (
"github.com/jesseduffield/gocui"
)
// Binding - a keybinding mapping a key and modifier to a handler. The keypress
// is only handled if the given view has focus, or handled globally if the view
// is ""
type Binding struct {
ViewName string
Handler func(*gocui.Gui, *gocui.View) error
Key interface{} // FIXME: find out how to get `gocui.Key | rune`
Modifier gocui.Modifier
KeyReadable string
Description string
}
// GetDisplayStrings returns the display string of a file
func (b *Binding) GetDisplayStrings() []string {
return []string{b.GetKey(), b.Description}
}
func (b *Binding) GetKey() string {
r, ok := b.Key.(rune)
key := ""
if ok {
key = string(r)
} else if b.KeyReadable != "" {
key = b.KeyReadable
}
return key
}
func (gui *Gui) GetKeybindings() []*Binding {
bindings := []*Binding{
{
ViewName: "",
Key: 'q',
Modifier: gocui.ModNone,
Handler: gui.quit,
}, {
ViewName: "",
Key: gocui.KeyCtrlC,
Modifier: gocui.ModNone,
Handler: gui.quit,
}, {
ViewName: "",
Key: gocui.KeyEsc,
Modifier: gocui.ModNone,
Handler: gui.quit,
}, {
ViewName: "",
Key: gocui.KeyPgup,
Modifier: gocui.ModNone,
Handler: gui.scrollUpMain,
}, {
ViewName: "",
Key: gocui.KeyPgdn,
Modifier: gocui.ModNone,
Handler: gui.scrollDownMain,
}, {
ViewName: "",
Key: gocui.KeyCtrlU,
Modifier: gocui.ModNone,
Handler: gui.scrollUpMain,
}, {
ViewName: "",
Key: gocui.KeyCtrlD,
Modifier: gocui.ModNone,
Handler: gui.scrollDownMain,
}, {
ViewName: "",
Key: 'P',
Modifier: gocui.ModNone,
Handler: gui.pushFiles,
Description: gui.Tr.SLocalize("push"),
}, {
ViewName: "",
Key: 'p',
Modifier: gocui.ModNone,
Handler: gui.pullFiles,
Description: gui.Tr.SLocalize("pull"),
}, {
ViewName: "",
Key: 'R',
Modifier: gocui.ModNone,
Handler: gui.handleRefresh,
Description: gui.Tr.SLocalize("refresh"),
}, {
ViewName: "",
Key: 'x',
Modifier: gocui.ModNone,
Handler: gui.handleCreateOptionsMenu,
}, {
ViewName: "status",
Key: 'e',
Modifier: gocui.ModNone,
Handler: gui.handleEditConfig,
Description: gui.Tr.SLocalize("EditConfig"),
}, {
ViewName: "status",
Key: 'o',
Modifier: gocui.ModNone,
Handler: gui.handleOpenConfig,
Description: gui.Tr.SLocalize("OpenConfig"),
}, {
ViewName: "status",
Key: 'u',
Modifier: gocui.ModNone,
Handler: gui.handleCheckForUpdate,
Description: gui.Tr.SLocalize("checkForUpdate"),
}, {
ViewName: "status",
Key: 's',
Modifier: gocui.ModNone,
Handler: gui.handleCreateRecentReposMenu,
Description: gui.Tr.SLocalize("SwitchRepo"),
},
{
ViewName: "files",
Key: 'c',
Modifier: gocui.ModNone,
Handler: gui.handleCommitPress,
Description: gui.Tr.SLocalize("CommitChanges"),
}, {
ViewName: "files",
Key: 'C',
Modifier: gocui.ModNone,
Handler: gui.handleCommitEditorPress,
Description: gui.Tr.SLocalize("CommitChangesWithEditor"),
}, {
ViewName: "files",
Key: gocui.KeySpace,
Modifier: gocui.ModNone,
Handler: gui.handleFilePress,
KeyReadable: "space",
Description: gui.Tr.SLocalize("toggleStaged"),
}, {
ViewName: "files",
Key: 'd',
Modifier: gocui.ModNone,
Handler: gui.handleFileRemove,
Description: gui.Tr.SLocalize("removeFile"),
}, {
ViewName: "files",
Key: 'm',
Modifier: gocui.ModNone,
Handler: gui.handleSwitchToMerge,
Description: gui.Tr.SLocalize("resolveMergeConflicts"),
}, {
ViewName: "files",
Key: 'e',
Modifier: gocui.ModNone,
Handler: gui.handleFileEdit,
Description: gui.Tr.SLocalize("editFile"),
}, {
ViewName: "files",
Key: 'o',
Modifier: gocui.ModNone,
Handler: gui.handleFileOpen,
Description: gui.Tr.SLocalize("openFile"),
}, {
ViewName: "files",
Key: 'i',
Modifier: gocui.ModNone,
Handler: gui.handleIgnoreFile,
Description: gui.Tr.SLocalize("ignoreFile"),
}, {
ViewName: "files",
Key: 'r',
Modifier: gocui.ModNone,
Handler: gui.handleRefreshFiles,
Description: gui.Tr.SLocalize("refreshFiles"),
}, {
ViewName: "files",
Key: 'S',
Modifier: gocui.ModNone,
Handler: gui.handleStashSave,
Description: gui.Tr.SLocalize("stashFiles"),
}, {
ViewName: "files",
Key: 'A',
Modifier: gocui.ModNone,
Handler: gui.handleAbortMerge,
Description: gui.Tr.SLocalize("abortMerge"),
}, {
ViewName: "files",
Key: 'a',
Modifier: gocui.ModNone,
Handler: gui.handleStageAll,
Description: gui.Tr.SLocalize("toggleStagedAll"),
}, {
ViewName: "files",
Key: 't',
Modifier: gocui.ModNone,
Handler: gui.handleAddPatch,
Description: gui.Tr.SLocalize("addPatch"),
}, {
ViewName: "files",
Key: 'D',
Modifier: gocui.ModNone,
Handler: gui.handleResetHard,
Description: gui.Tr.SLocalize("resetHard"),
}, {
ViewName: "main",
Key: gocui.KeyEsc,
Modifier: gocui.ModNone,
Handler: gui.handleEscapeMerge,
}, {
ViewName: "main",
Key: gocui.KeySpace,
Modifier: gocui.ModNone,
Handler: gui.handlePickHunk,
}, {
ViewName: "main",
Key: 'b',
Modifier: gocui.ModNone,
Handler: gui.handlePickBothHunks,
}, {
ViewName: "main",
Key: gocui.KeyArrowLeft,
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevConflict,
}, {
ViewName: "main",
Key: gocui.KeyArrowRight,
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextConflict,
}, {
ViewName: "main",
Key: gocui.KeyArrowUp,
Modifier: gocui.ModNone,
Handler: gui.handleSelectTop,
}, {
ViewName: "main",
Key: gocui.KeyArrowDown,
Modifier: gocui.ModNone,
Handler: gui.handleSelectBottom,
}, {
ViewName: "main",
Key: 'h',
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevConflict,
}, {
ViewName: "main",
Key: 'l',
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextConflict,
}, {
ViewName: "main",
Key: 'k',
Modifier: gocui.ModNone,
Handler: gui.handleSelectTop,
}, {
ViewName: "main",
Key: 'j',
Modifier: gocui.ModNone,
Handler: gui.handleSelectBottom,
}, {
ViewName: "main",
Key: 'z',
Modifier: gocui.ModNone,
Handler: gui.handlePopFileSnapshot,
}, {
ViewName: "branches",
Key: gocui.KeySpace,
Modifier: gocui.ModNone,
Handler: gui.handleBranchPress,
KeyReadable: "space",
Description: gui.Tr.SLocalize("checkout"),
}, {
ViewName: "branches",
Key: 'c',
Modifier: gocui.ModNone,
Handler: gui.handleCheckoutByName,
Description: gui.Tr.SLocalize("checkoutByName"),
}, {
ViewName: "branches",
Key: 'F',
Modifier: gocui.ModNone,
Handler: gui.handleForceCheckout,
Description: gui.Tr.SLocalize("forceCheckout"),
}, {
ViewName: "branches",
Key: 'n',
Modifier: gocui.ModNone,
Handler: gui.handleNewBranch,
Description: gui.Tr.SLocalize("newBranch"),
}, {
ViewName: "branches",
Key: 'd',
Modifier: gocui.ModNone,
Handler: gui.handleDeleteBranch,
Description: gui.Tr.SLocalize("deleteBranch"),
}, {
ViewName: "branches",
Key: 'D',
Modifier: gocui.ModNone,
Handler: gui.handleForceDeleteBranch,
Description: gui.Tr.SLocalize("forceDeleteBranch"),
}, {
ViewName: "branches",
Key: 'm',
Modifier: gocui.ModNone,
Handler: gui.handleMerge,
Description: gui.Tr.SLocalize("mergeIntoCurrentBranch"),
}, {
ViewName: "commits",
Key: 's',
Modifier: gocui.ModNone,
Handler: gui.handleCommitSquashDown,
Description: gui.Tr.SLocalize("squashDown"),
}, {
ViewName: "commits",
Key: 'r',
Modifier: gocui.ModNone,
Handler: gui.handleRenameCommit,
Description: gui.Tr.SLocalize("renameCommit"),
}, {
ViewName: "commits",
Key: 'R',
Modifier: gocui.ModNone,
Handler: gui.handleRenameCommitEditor,
Description: gui.Tr.SLocalize("renameCommitEditor"),
}, {
ViewName: "commits",
Key: 'g',
Modifier: gocui.ModNone,
Handler: gui.handleResetToCommit,
Description: gui.Tr.SLocalize("resetToThisCommit"),
}, {
ViewName: "commits",
Key: 'f',
Modifier: gocui.ModNone,
Handler: gui.handleCommitFixup,
Description: gui.Tr.SLocalize("fixupCommit"),
}, {
ViewName: "stash",
Key: gocui.KeySpace,
Modifier: gocui.ModNone,
Handler: gui.handleStashApply,
KeyReadable: "space",
Description: gui.Tr.SLocalize("apply"),
}, {
ViewName: "stash",
Key: 'g',
Modifier: gocui.ModNone,
Handler: gui.handleStashPop,
Description: gui.Tr.SLocalize("pop"),
}, {
ViewName: "stash",
Key: 'd',
Modifier: gocui.ModNone,
Handler: gui.handleStashDrop,
Description: gui.Tr.SLocalize("drop"),
}, {
ViewName: "commitMessage",
Key: gocui.KeyEnter,
Modifier: gocui.ModNone,
Handler: gui.handleCommitConfirm,
}, {
ViewName: "commitMessage",
Key: gocui.KeyEsc,
Modifier: gocui.ModNone,
Handler: gui.handleCommitClose,
}, {
ViewName: "menu",
Key: gocui.KeyEsc,
Modifier: gocui.ModNone,
Handler: gui.handleMenuClose,
}, {
ViewName: "menu",
Key: 'q',
Modifier: gocui.ModNone,
Handler: gui.handleMenuClose,
},
}
// Would make these keybindings global but that interferes with editing
// input in the confirmation panel
for _, viewName := range []string{"status", "files", "branches", "commits", "stash", "menu"} {
bindings = append(bindings, []*Binding{
{ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: gui.previousView},
{ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.cursorUp},
{ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.cursorDown},
{ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: gui.previousView},
{ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: gui.cursorUp},
{ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: gui.cursorDown},
}...)
}
return bindings
}
func (gui *Gui) keybindings(g *gocui.Gui) error {
bindings := gui.GetKeybindings()
for _, binding := range bindings {
if err := g.SetKeybinding(binding.ViewName, binding.Key, binding.Modifier, binding.Handler); err != nil {
return err
}
}
return nil
}
+71
View File
@@ -0,0 +1,71 @@
package gui
import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) handleMenuSelect(g *gocui.Gui, v *gocui.View) error {
// doing nothing for now
// but it is needed for switch in newLineFocused
return nil
}
func (gui *Gui) renderMenuOptions(g *gocui.Gui) error {
optionsMap := map[string]string{
"esc/q": gui.Tr.SLocalize("close"),
"↑ ↓": gui.Tr.SLocalize("navigate"),
"space": gui.Tr.SLocalize("execute"),
}
return gui.renderOptionsMap(g, optionsMap)
}
func (gui *Gui) handleMenuClose(g *gocui.Gui, v *gocui.View) error {
if err := g.DeleteKeybinding("menu", gocui.KeySpace, gocui.ModNone); err != nil {
return err
}
err := g.DeleteView("menu")
if err != nil {
return err
}
return gui.returnFocus(g, v)
}
func (gui *Gui) createMenu(items interface{}, handlePress func(int) error) error {
list, err := utils.RenderList(items)
if err != nil {
return err
}
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(gui.g, list)
menuView, _ := gui.g.SetView("menu", x0, y0, x1, y1, 0)
menuView.Title = strings.Title(gui.Tr.SLocalize("menu"))
menuView.FgColor = gocui.ColorWhite
menuView.Clear()
fmt.Fprint(menuView, list)
if err := gui.renderMenuOptions(gui.g); err != nil {
return err
}
wrappedHandlePress := func(g *gocui.Gui, v *gocui.View) error {
lineNumber := gui.getItemPosition(v)
return handlePress(lineNumber)
}
if err := gui.g.SetKeybinding("menu", gocui.KeySpace, gocui.ModNone, wrappedHandlePress); err != nil {
return err
}
gui.g.Update(func(g *gocui.Gui) error {
if _, err := g.SetViewOnTop("menu"); err != nil {
return err
}
currentView := gui.g.CurrentView()
return gui.switchFocus(gui.g, currentView, menuView)
})
return nil
}
+263
View File
@@ -0,0 +1,263 @@
// though this panel is called the merge panel, it's really going to use the main panel. This may change in the future
package gui
import (
"bufio"
"bytes"
"io/ioutil"
"math"
"os"
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) findConflicts(content string) ([]commands.Conflict, error) {
conflicts := make([]commands.Conflict, 0)
var newConflict commands.Conflict
for i, line := range utils.SplitLines(content) {
if line == "<<<<<<< HEAD" || line == "<<<<<<< MERGE_HEAD" || line == "<<<<<<< Updated upstream" {
newConflict = commands.Conflict{Start: i}
} else if line == "=======" {
newConflict.Middle = i
} else if strings.HasPrefix(line, ">>>>>>> ") {
newConflict.End = i
conflicts = append(conflicts, newConflict)
}
}
return conflicts, nil
}
func (gui *Gui) shiftConflict(conflicts []commands.Conflict) (commands.Conflict, []commands.Conflict) {
return conflicts[0], conflicts[1:]
}
func (gui *Gui) shouldHighlightLine(index int, conflict commands.Conflict, top bool) bool {
return (index >= conflict.Start && index <= conflict.Middle && top) || (index >= conflict.Middle && index <= conflict.End && !top)
}
func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflict, conflictIndex int, conflictTop, hasFocus bool) (string, error) {
if len(conflicts) == 0 {
return content, nil
}
conflict, remainingConflicts := gui.shiftConflict(conflicts)
var outputBuffer bytes.Buffer
for i, line := range utils.SplitLines(content) {
colourAttr := color.FgWhite
if i == conflict.Start || i == conflict.Middle || i == conflict.End {
colourAttr = color.FgRed
}
colour := color.New(colourAttr)
if hasFocus && conflictIndex < len(conflicts) && conflicts[conflictIndex] == conflict && gui.shouldHighlightLine(i, conflict, conflictTop) {
colour.Add(color.Bold)
}
if i == conflict.End && len(remainingConflicts) > 0 {
conflict, remainingConflicts = gui.shiftConflict(remainingConflicts)
}
outputBuffer.WriteString(utils.ColoredStringDirect(line, colour) + "\n")
}
return outputBuffer.String(), nil
}
func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error {
gui.State.ConflictTop = true
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error {
gui.State.ConflictTop = false
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error {
if gui.State.ConflictIndex >= len(gui.State.Conflicts)-1 {
return nil
}
gui.State.ConflictIndex++
return gui.refreshMergePanel(g)
}
func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error {
if gui.State.ConflictIndex <= 0 {
return nil
}
gui.State.ConflictIndex--
return gui.refreshMergePanel(g)
}
func (gui *Gui) isIndexToDelete(i int, conflict commands.Conflict, pick string) bool {
return i == conflict.Middle ||
i == conflict.Start ||
i == conflict.End ||
pick != "both" &&
(pick == "bottom" && i > conflict.Start && i < conflict.Middle) ||
(pick == "top" && i > conflict.Middle && i < conflict.End)
}
func (gui *Gui) resolveConflict(g *gocui.Gui, conflict commands.Conflict, pick string) error {
gitFile, err := gui.getSelectedFile(g)
if err != nil {
return err
}
file, err := os.Open(gitFile.Name)
if err != nil {
return err
}
defer file.Close()
reader := bufio.NewReader(file)
output := ""
for i := 0; true; i++ {
line, err := reader.ReadString('\n')
if err != nil {
break
}
if !gui.isIndexToDelete(i, conflict, pick) {
output += line
}
}
gui.Log.Info(output)
return ioutil.WriteFile(gitFile.Name, []byte(output), 0644)
}
func (gui *Gui) pushFileSnapshot(g *gocui.Gui) error {
gitFile, err := gui.getSelectedFile(g)
if err != nil {
return err
}
content, err := gui.GitCommand.CatFile(gitFile.Name)
if err != nil {
return err
}
gui.State.EditHistory.Push(content)
return nil
}
func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error {
if gui.State.EditHistory.Len() == 0 {
return nil
}
prevContent := gui.State.EditHistory.Pop().(string)
gitFile, err := gui.getSelectedFile(g)
if err != nil {
return err
}
ioutil.WriteFile(gitFile.Name, []byte(prevContent), 0644)
return gui.refreshMergePanel(g)
}
func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error {
conflict := gui.State.Conflicts[gui.State.ConflictIndex]
gui.pushFileSnapshot(g)
pick := "bottom"
if gui.State.ConflictTop {
pick = "top"
}
err := gui.resolveConflict(g, conflict, pick)
if err != nil {
panic(err)
}
gui.refreshMergePanel(g)
return nil
}
func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error {
conflict := gui.State.Conflicts[gui.State.ConflictIndex]
gui.pushFileSnapshot(g)
err := gui.resolveConflict(g, conflict, "both")
if err != nil {
panic(err)
}
return gui.refreshMergePanel(g)
}
func (gui *Gui) refreshMergePanel(g *gocui.Gui) error {
cat, err := gui.catSelectedFile(g)
if err != nil {
return err
}
if cat == "" {
return nil
}
gui.State.Conflicts, err = gui.findConflicts(cat)
if err != nil {
return err
}
if len(gui.State.Conflicts) == 0 {
return gui.handleCompleteMerge(g)
} else if gui.State.ConflictIndex > len(gui.State.Conflicts)-1 {
gui.State.ConflictIndex = len(gui.State.Conflicts) - 1
}
hasFocus := gui.currentViewName(g) == "main"
if hasFocus {
gui.renderMergeOptions(g)
}
content, err := gui.coloredConflictFile(cat, gui.State.Conflicts, gui.State.ConflictIndex, gui.State.ConflictTop, hasFocus)
if err != nil {
return err
}
if err := gui.scrollToConflict(g); err != nil {
return err
}
return gui.renderString(g, "main", content)
}
func (gui *Gui) scrollToConflict(g *gocui.Gui) error {
mainView, err := g.View("main")
if err != nil {
return err
}
if len(gui.State.Conflicts) == 0 {
return nil
}
conflict := gui.State.Conflicts[gui.State.ConflictIndex]
ox, _ := mainView.Origin()
_, height := mainView.Size()
conflictMiddle := (conflict.End + conflict.Start) / 2
newOriginY := int(math.Max(0, float64(conflictMiddle-(height/2))))
return mainView.SetOrigin(ox, newOriginY)
}
func (gui *Gui) switchToMerging(g *gocui.Gui) error {
gui.State.ConflictIndex = 0
gui.State.ConflictTop = true
_, err := g.SetCurrentView("main")
if err != nil {
return err
}
return gui.refreshMergePanel(g)
}
func (gui *Gui) renderMergeOptions(g *gocui.Gui) error {
return gui.renderOptionsMap(g, map[string]string{
"↑ ↓": gui.Tr.SLocalize("selectHunk"),
"← →": gui.Tr.SLocalize("navigateConflicts"),
"space": gui.Tr.SLocalize("pickHunk"),
"b": gui.Tr.SLocalize("pickBothHunks"),
"z": gui.Tr.SLocalize("undo"),
})
}
func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error {
filesView, err := g.View("files")
if err != nil {
return err
}
gui.refreshFiles(g)
return gui.switchFocus(g, v, filesView)
}
func (gui *Gui) handleCompleteMerge(g *gocui.Gui) error {
filesView, err := g.View("files")
if err != nil {
return err
}
gui.stageSelectedFile(g)
gui.refreshFiles(g)
return gui.switchFocus(g, nil, filesView)
}
+51
View File
@@ -0,0 +1,51 @@
package gui
import (
"errors"
"github.com/jesseduffield/gocui"
)
func (gui *Gui) getBindings(v *gocui.View) []*Binding {
var (
bindingsGlobal, bindingsPanel []*Binding
)
bindings := gui.GetKeybindings()
for _, binding := range bindings {
if binding.GetKey() != "" && binding.Description != "" {
switch binding.ViewName {
case "":
bindingsGlobal = append(bindingsGlobal, binding)
case v.Name():
bindingsPanel = append(bindingsPanel, binding)
}
}
}
// append dummy element to have a separator between
// panel and global keybindings
bindingsPanel = append(bindingsPanel, &Binding{})
return append(bindingsPanel, bindingsGlobal...)
}
func (gui *Gui) handleCreateOptionsMenu(g *gocui.Gui, v *gocui.View) error {
bindings := gui.getBindings(v)
handleMenuPress := func(index int) error {
if bindings[index].Key == nil {
return nil
}
if index >= len(bindings) {
return errors.New("Index is greater than size of bindings")
}
err := gui.handleMenuClose(g, v)
if err != nil {
return err
}
return bindings[index].Handler(g, v)
}
return gui.createMenu(bindings, handleMenuPress)
}
+69
View File
@@ -0,0 +1,69 @@
package gui
import (
"os"
"path/filepath"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type recentRepo struct {
path string
}
func (r *recentRepo) GetDisplayStrings() []string {
yellow := color.New(color.FgMagenta)
base := filepath.Base(r.path)
path := yellow.Sprint(r.path)
return []string{base, path}
}
func (gui *Gui) handleCreateRecentReposMenu(g *gocui.Gui, v *gocui.View) error {
recentRepoPaths := gui.Config.GetAppState().RecentRepos
reposCount := utils.Min(len(recentRepoPaths), 20)
// we won't show the current repo hence the -1
recentRepos := make([]*recentRepo, reposCount-1)
for i, path := range recentRepoPaths[1:reposCount] {
recentRepos[i] = &recentRepo{path: path}
}
handleMenuPress := func(index int) error {
repo := recentRepos[index]
if err := os.Chdir(repo.path); err != nil {
return err
}
newGitCommand, err := commands.NewGitCommand(gui.Log, gui.OSCommand, gui.Tr)
if err != nil {
return err
}
gui.GitCommand = newGitCommand
return gui.Errors.ErrSwitchRepo
}
return gui.createMenu(recentRepos, handleMenuPress)
}
// updateRecentRepoList registers the fact that we opened lazygit in this repo,
// so that we can open the same repo via the 'recent repos' menu
func (gui *Gui) updateRecentRepoList() error {
recentRepos := gui.Config.GetAppState().RecentRepos
currentRepo, err := os.Getwd()
if err != nil {
return err
}
gui.Config.GetAppState().RecentRepos = newRecentReposList(recentRepos, currentRepo)
return gui.Config.SaveAppState()
}
func newRecentReposList(recentRepos []string, currentRepo string) []string {
newRepos := []string{currentRepo}
for _, repo := range recentRepos {
if repo != currentRepo {
newRepos = append(newRepos, repo)
}
}
return newRepos
}
+106
View File
@@ -0,0 +1,106 @@
package gui
import (
"fmt"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) refreshStashEntries(g *gocui.Gui) error {
g.Update(func(g *gocui.Gui) error {
v, err := g.View("stash")
if err != nil {
panic(err)
}
gui.State.StashEntries = gui.GitCommand.GetStashEntries()
v.Clear()
list, err := utils.RenderList(gui.State.StashEntries)
if err != nil {
return err
}
fmt.Fprint(v, list)
return gui.resetOrigin(v)
})
return nil
}
func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry {
if len(gui.State.StashEntries) == 0 {
return nil
}
stashView, _ := gui.g.View("stash")
lineNumber := gui.getItemPosition(stashView)
return gui.State.StashEntries[lineNumber]
}
func (gui *Gui) renderStashOptions(g *gocui.Gui) error {
return gui.renderGlobalOptions(g)
}
func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error {
if err := gui.renderStashOptions(g); err != nil {
return err
}
go func() {
stashEntry := gui.getSelectedStashEntry(v)
if stashEntry == nil {
gui.renderString(g, "main", gui.Tr.SLocalize("NoStashEntries"))
return
}
diff, _ := gui.GitCommand.GetStashEntryDiff(stashEntry.Index)
gui.renderString(g, "main", diff)
}()
return nil
}
func (gui *Gui) handleStashApply(g *gocui.Gui, v *gocui.View) error {
return gui.stashDo(g, v, "apply")
}
func (gui *Gui) handleStashPop(g *gocui.Gui, v *gocui.View) error {
return gui.stashDo(g, v, "pop")
}
func (gui *Gui) handleStashDrop(g *gocui.Gui, v *gocui.View) error {
title := gui.Tr.SLocalize("StashDrop")
message := gui.Tr.SLocalize("SureDropStashEntry")
return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error {
return gui.stashDo(g, v, "drop")
}, nil)
}
func (gui *Gui) stashDo(g *gocui.Gui, v *gocui.View, method string) error {
stashEntry := gui.getSelectedStashEntry(v)
if stashEntry == nil {
errorMessage := gui.Tr.TemplateLocalize(
"NoStashTo",
Teml{
"method": method,
},
)
return gui.createErrorPanel(g, errorMessage)
}
if err := gui.GitCommand.StashDo(stashEntry.Index, method); err != nil {
gui.createErrorPanel(g, err.Error())
}
gui.refreshStashEntries(g)
return gui.refreshFiles(g)
}
func (gui *Gui) handleStashSave(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.trackedFiles()) == 0 && len(gui.stagedFiles()) == 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoTrackedStagedFilesStash"))
}
gui.createPromptPanel(g, filesView, gui.Tr.SLocalize("StashChanges"), func(g *gocui.Gui, v *gocui.View) error {
if err := gui.GitCommand.StashSave(gui.trimmedContent(v)); err != nil {
gui.createErrorPanel(g, err.Error())
}
gui.refreshStashEntries(g)
return gui.refreshFiles(g)
})
return nil
}

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