diff --git a/.gitignore b/.gitignore index 3d59e16c5..304a2356f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,18 @@ -development.log -commands.log +# Please do not add personal files + +# Logs +*.log + +# Extras extra/lgit.rb + +# Notes notes/go.notes TODO.notes TODO.md + +# Tests test/repos/repo + +# Binaries +lazygit \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml index a7b2bcfdb..8f8da01ee 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -13,6 +13,7 @@ builds: - arm - arm64 - 386 + archive: replacements: darwin: Darwin @@ -33,6 +34,7 @@ changelog: exclude: - '^docs:' - '^test:' + - '^bump' brew: # Reporitory to push the tap to. github: diff --git a/README.md b/README.md index 721dc0862..6b85ffbe1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ too stubborn to use Sourcetree because you'll never forgive Atlassian for making Jira? This is the app for you! -![Gif](https://image.ibb.co/mmeXho/optimisedgif.gif) +![Gif](/docs/resources/lazygit-example.gif) * [Installation](https://github.com/jesseduffield/lazygit#installation) * [Usage](https://github.com/jesseduffield/lazygit#usage), @@ -90,7 +90,7 @@ whichever rc file you're using). * Basic video tutorial [here](https://www.youtube.com/watch?v=VDXvbHZYeKY). * List of keybindings -[here](https://github.com/jesseduffield/lazygit/blob/master/docs/Keybindings.md). +[here](/docs/Keybindings.md). ## Cool features * Adding files easily @@ -101,10 +101,10 @@ whichever rc file you're using). * Squash down and rename commits ### Resolving merge conflicts -![Gif](https://image.ibb.co/iyxUTT/shortermerging.gif) +![Gif](/docs/resources/resolving-merge-conflicts.gif) ### Viewing commit diffs -![Viewing Commit Diffs](https://image.ibb.co/gPD02o/capture.png) +![Viewing Commit Diffs](/docs/resources/viewing-commit-diffs.png) ## Milestones - [x] Easy Installation (homebrew, release binaries) @@ -119,7 +119,7 @@ whichever rc file you're using). 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](/files/slack_rgb.png)](https://join.slack.com/t/lazygit/shared_invite/enQtNDE3MjIwNTYyMDA0LTM3Yjk3NzdiYzhhNTA1YjM4Y2M4MWNmNDBkOTI0YTE4YjQ1ZmI2YWRhZTgwNjg2YzhhYjg3NDBlMmQyMTI5N2M) +[![Slack](/docs/resources/slack_rgb.png)](https://join.slack.com/t/lazygit/shared_invite/enQtNDE3MjIwNTYyMDA0LTM3Yjk3NzdiYzhhNTA1YjM4Y2M4MWNmNDBkOTI0YTE4YjQ1ZmI2YWRhZTgwNjg2YzhhYjg3NDBlMmQyMTI5N2M) ## Work in progress This is still a work in progress so there's still bugs to iron out and as this diff --git a/VERSION b/VERSION deleted file mode 100644 index 60dc34827..000000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -v0.1.66 \ No newline at end of file diff --git a/docs/resources/lazygit-example.gif b/docs/resources/lazygit-example.gif new file mode 100644 index 000000000..c169f8470 Binary files /dev/null and b/docs/resources/lazygit-example.gif differ diff --git a/docs/resources/resolving-merge-conflicts.gif b/docs/resources/resolving-merge-conflicts.gif new file mode 100644 index 000000000..0b943fd49 Binary files /dev/null and b/docs/resources/resolving-merge-conflicts.gif differ diff --git a/files/slack_rgb.png b/docs/resources/slack_rgb.png similarity index 100% rename from files/slack_rgb.png rename to docs/resources/slack_rgb.png diff --git a/docs/resources/viewing-commit-diffs.png b/docs/resources/viewing-commit-diffs.png new file mode 100644 index 000000000..6bb5c42ed Binary files /dev/null and b/docs/resources/viewing-commit-diffs.png differ diff --git a/main.go b/main.go index 85e0f36bb..e8c092da2 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,9 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" "path/filepath" + "runtime" "github.com/jesseduffield/lazygit/pkg/app" "github.com/jesseduffield/lazygit/pkg/config" @@ -25,25 +25,10 @@ func projectPath(path string) string { return filepath.FromSlash(gopath + "/src/github.com/jesseduffield/lazygit/" + path) } -// when building the binary, `version` is set as a compile-time variable, along -// with `date` and `commit`. If this program has been opened directly via go, -// we will populate the `version` with VERSION in the lazygit root directory -func fallbackVersion() string { - path := projectPath("VERSION") - byteVersion, err := ioutil.ReadFile(path) - if err != nil { - return "unversioned" - } - return string(byteVersion) -} - func main() { flag.Parse() - if version == "unversioned" { - version = fallbackVersion() - } if *versionFlag { - fmt.Printf("commit=%s, build date=%s, version=%s\n", commit, date, version) + fmt.Printf("commit=%s, build date=%s, version=%s, os=%s, arch=%s\n", commit, date, version, runtime.GOOS, runtime.GOARCH) os.Exit(0) } appConfig, err := config.NewAppConfig("lazygit", version, commit, date, debuggingFlag) @@ -52,7 +37,13 @@ func main() { } app, err := app.NewApp(appConfig) - app.Log.Info(err) + if err != nil { + // TODO: remove this call to panic after anonymous error reporting + // is setup (right now the call to panic logs nothing to the screen which + // would make debugging difficult + panic(err) + // app.Log.Panic(err.Error()) + } app.GitCommand.SetupGit() app.Gui.RunWithSubprocesses() } diff --git a/pkg/app/app.go b/pkg/app/app.go index 98da0b0fa..aaa925e53 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -48,21 +48,21 @@ func NewApp(config config.AppConfigurer) (*App, error) { app.Log = newLogger(config) app.OSCommand, err = commands.NewOSCommand(app.Log) if err != nil { - return nil, err + return app, err } app.Tr, err = i18n.NewLocalizer(app.Log) if err != nil { - return nil, err + return app, err } app.GitCommand, err = commands.NewGitCommand(app.Log, app.OSCommand) if err != nil { - return nil, err + return app, err } app.Gui, err = gui.NewGui(app.Log, app.GitCommand, app.OSCommand, app.Tr, config) if err != nil { - return nil, err + return app, err } return app, nil } diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 3349e4860..557e6a8c0 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -81,9 +81,9 @@ func (c *GitCommand) GetStatusFiles() []File { stagedChange := change[0:1] unstagedChange := statusString[1:2] filename := statusString[3:] - tracked := !includes([]string{"??", "A "}, change) + tracked := !includes([]string{"??", "A ", "AM"}, change) file := File{ - Name: filename, + Name: c.OSCommand.Unquote(filename), DisplayString: statusString, HasStagedChanges: !includes([]string{" ", "U", "?"}, stagedChange), HasUnstagedChanges: unstagedChange != " ", @@ -321,24 +321,24 @@ func (c *GitCommand) SquashFixupCommit(branchName string, shaValue string) error } // CatFile obtain the contents of a file -func (c *GitCommand) CatFile(file string) (string, error) { - return c.OSCommand.RunCommandWithOutput("cat " + file) +func (c *GitCommand) CatFile(fileName string) (string, error) { + return c.OSCommand.RunCommandWithOutput("cat " + c.OSCommand.Quote(fileName)) } // StageFile stages a file -func (c *GitCommand) StageFile(file string) error { - return c.OSCommand.RunCommand("git add " + c.OSCommand.Quote(file)) +func (c *GitCommand) StageFile(fileName string) error { + return c.OSCommand.RunCommand("git add " + c.OSCommand.Quote(fileName)) } // UnStageFile unstages a file -func (c *GitCommand) UnStageFile(file string, tracked bool) error { +func (c *GitCommand) UnStageFile(fileName string, tracked bool) error { var command string if tracked { command = "git reset HEAD " } else { command = "git rm --cached " } - return c.OSCommand.RunCommand(command + file) + return c.OSCommand.RunCommand(command + c.OSCommand.Quote(fileName)) } // GitStatus returns the plaintext short status of the repo @@ -358,11 +358,16 @@ func (c *GitCommand) IsInMergeState() (bool, error) { // 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("git reset -- " + file.Name); err != nil { + return err + } + } if !file.Tracked { return os.RemoveAll(file.Name) } // if the file is tracked, we assume you want to just check it out - return c.OSCommand.RunCommand("git checkout " + file.Name) + return c.OSCommand.RunCommand("git checkout -- " + file.Name) } // Checkout checks out a branch, with --force if you set the force arg to true @@ -456,10 +461,8 @@ func (c *GitCommand) GetLog() string { } // Ignore adds a file to the gitignore for the repo -func (c *GitCommand) Ignore(filename string) { - if _, err := c.OSCommand.RunDirectCommand("echo '" + filename + "' >> .gitignore"); err != nil { - panic(err) - } +func (c *GitCommand) Ignore(filename string) error { + return c.OSCommand.AppendLineToFile(".gitignore", filename) } // Show shows the diff of a commit @@ -474,22 +477,15 @@ func (c *GitCommand) Show(sha string) string { // Diff returns the diff of a file func (c *GitCommand) Diff(file File) string { cachedArg := "" - fileName := file.Name + fileName := c.OSCommand.Quote(file.Name) if file.HasStagedChanges && !file.HasUnstagedChanges { cachedArg = "--cached" - } else { - // if the file is staged and has spaces in it, it comes pre-quoted - fileName = c.OSCommand.Quote(fileName) } - deletedArg := "" - if file.Deleted { - deletedArg = "--" - } - trackedArg := "" + trackedArg := "--" if !file.Tracked && !file.HasStagedChanges { trackedArg = "--no-index /dev/null" } - command := fmt.Sprintf("%s %s %s %s %s", "git diff --color ", cachedArg, deletedArg, trackedArg, fileName) + 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) diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go new file mode 100644 index 000000000..9c2a64330 --- /dev/null +++ b/pkg/commands/git_test.go @@ -0,0 +1,126 @@ +package commands + +import ( + "io/ioutil" + "strings" + "testing" + + "github.com/Sirupsen/logrus" + "github.com/jesseduffield/lazygit/pkg/test" +) + +func getDummyLog() *logrus.Logger { + log := logrus.New() + log.Out = ioutil.Discard + return log +} + +func getDummyOSCommand() *OSCommand { + return &OSCommand{ + Log: getDummyLog(), + Platform: getPlatform(), + } +} + +func getDummyGitCommand() *GitCommand { + return &GitCommand{ + Log: getDummyLog(), + OSCommand: getDummyOSCommand(), + } +} + +func TestDiff(t *testing.T) { + gitCommand := getDummyGitCommand() + if err := test.GenerateRepo("lots_of_diffs.sh"); err != nil { + t.Error(err.Error()) + } + files := []File{ + { + Name: "deleted_staged", + HasStagedChanges: false, + HasUnstagedChanges: true, + Tracked: true, + Deleted: true, + HasMergeConflicts: false, + DisplayString: " D deleted_staged", + }, + { + Name: "file with space staged", + HasStagedChanges: true, + HasUnstagedChanges: false, + Tracked: false, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "A \"file with space staged\"", + }, + { + Name: "file with space unstaged", + HasStagedChanges: false, + HasUnstagedChanges: true, + Tracked: false, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "?? file with space unstaged", + }, + { + Name: "modified_unstaged", + HasStagedChanges: true, + HasUnstagedChanges: false, + Tracked: true, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "M modified_unstaged", + }, + { + Name: "modified_staged", + HasStagedChanges: false, + HasUnstagedChanges: true, + Tracked: true, + Deleted: false, + HasMergeConflicts: false, + DisplayString: " M modified_staged", + }, + { + Name: "renamed_before -> renamed_after", + HasStagedChanges: true, + HasUnstagedChanges: false, + Tracked: true, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "R renamed_before -> renamed_after", + }, + { + Name: "untracked_unstaged", + HasStagedChanges: false, + HasUnstagedChanges: true, + Tracked: false, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "?? untracked_unstaged", + }, + { + Name: "untracked_staged", + HasStagedChanges: true, + HasUnstagedChanges: false, + Tracked: false, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "A untracked_staged", + }, + { + Name: "master", + HasStagedChanges: false, + HasUnstagedChanges: true, + Tracked: false, + Deleted: false, + HasMergeConflicts: false, + DisplayString: "?? master", + }, + } + for _, file := range files { + content := gitCommand.Diff(file) + if strings.Contains(content, "error") { + t.Error("Error: diff test failed. File: " + file.Name + ", " + content) + } + } +} diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 32514a419..9756d619d 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -167,3 +167,21 @@ func (c *OSCommand) Quote(message string) string { message = strings.Replace(message, "`", "\\`", -1) return c.Platform.escapedQuote + message + c.Platform.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 { + message = strings.Replace(message, `"`, "", -1) + return message +} + +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 +} diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 417b947a2..c428e3b99 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -74,7 +74,7 @@ func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { } commit, err := gui.getSelectedCommit(g) if err != nil { - if err != errors.New(gui.Tr.SLocalize("NoCommitsThisBranch")) { + if err.Error() != gui.Tr.SLocalize("NoCommitsThisBranch") { return err } return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go index 9c3d2b263..025753d56 100644 --- a/pkg/gui/confirmation_panel.go +++ b/pkg/gui/confirmation_panel.go @@ -67,6 +67,7 @@ func (gui *Gui) createPromptPanel(g *gocui.Gui, currentView *gocui.View, title s confirmationView.Editable = true confirmationView.Title = title + confirmationView.FgColor = gocui.ColorWhite gui.switchFocus(g, currentView, confirmationView) return gui.setKeyBindings(g, handleConfirm, nil) } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 166af4108..d614cf5ef 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -128,7 +128,7 @@ func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error { ) 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 { - panic(err) + return err } return gui.refreshFiles(g) }, nil) @@ -142,7 +142,9 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { if file.Tracked { return gui.createErrorPanel(g, gui.Tr.SLocalize("CantIgnoreTrackFiles")) } - gui.GitCommand.Ignore(file.Name) + if err := gui.GitCommand.Ignore(file.Name); err != nil { + return gui.createErrorPanel(g, err.Error()) + } return gui.refreshFiles(g) } diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go index 0ba562a22..60133e662 100644 --- a/pkg/i18n/dutch.go +++ b/pkg/i18n/dutch.go @@ -6,10 +6,10 @@ import ( ) // addDutch will add all dutch translations -func addDutch(i18nObject *i18n.Bundle) { +func addDutch(i18nObject *i18n.Bundle) error { // add the translations - i18nObject.AddMessages(language.Dutch, + return i18nObject.AddMessages(language.Dutch, &i18n.Message{ ID: "NotEnoughSpace", Other: "Niet genoeg ruimte om de panelen te renderen", diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index c6d1d1379..bebe9b282 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -15,9 +15,9 @@ import ( "golang.org/x/text/language" ) -func addEnglish(i18nObject *i18n.Bundle) { +func addEnglish(i18nObject *i18n.Bundle) error { - i18nObject.AddMessages(language.English, + return i18nObject.AddMessages(language.English, &i18n.Message{ ID: "NotEnoughSpace", Other: "Not enough space to render panels", diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index 9102ff0b3..f2bd2839e 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -30,7 +30,7 @@ func NewLocalizer(log *logrus.Logger) (*Localizer, error) { // create a i18n bundle that can be used to add translations and other things i18nBundle := &i18n.Bundle{DefaultLanguage: language.English} - addBundles(i18nBundle) + addBundles(log, i18nBundle) // return the new localizer that can be used to translate text i18nLocalizer := i18n.NewLocalizer(i18nBundle, userLang) @@ -78,7 +78,18 @@ func (l *Localizer) GetLanguage() string { } // add translation file(s) -func addBundles(i18nBundle *i18n.Bundle) { - addDutch(i18nBundle) - addEnglish(i18nBundle) +func addBundles(log *logrus.Logger, i18nBundle *i18n.Bundle) { + err := addPolish(i18nBundle) + if err != nil { + log.Fatal(err) + } + err = addDutch(i18nBundle) + if err != nil { + log.Fatal(err) + } + err = addEnglish(i18nBundle) + if err != nil { + log.Fatal(err) + } + } diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go new file mode 100644 index 000000000..9b9fa19e1 --- /dev/null +++ b/pkg/i18n/polish.go @@ -0,0 +1,289 @@ +package i18n + +import ( + "github.com/nicksnyder/go-i18n/v2/i18n" + "golang.org/x/text/language" +) + +func addPolish(i18nObject *i18n.Bundle) error { + + return i18nObject.AddMessages(language.Polish, + &i18n.Message{ + ID: "NotEnoughSpace", + Other: "Za mało miejsca do wyświetlenia paneli", + }, &i18n.Message{ + ID: "DiffTitle", + Other: "Różnice", + }, &i18n.Message{ + ID: "FilesTitle", + Other: "Pliki", + }, &i18n.Message{ + ID: "BranchesTitle", + Other: "Gałęzie", + }, &i18n.Message{ + ID: "CommitsTitle", + Other: "Commity", + }, &i18n.Message{ + ID: "StashTitle", + Other: "Schowek", + }, &i18n.Message{ + ID: "CommitMessage", + Other: "Wiadomość commita", + }, &i18n.Message{ + ID: "CommitChanges", + Other: "commituj zmiany", + }, &i18n.Message{ + ID: "StatusTitle", + Other: "Status", + }, &i18n.Message{ + ID: "navigate", + Other: "nawiguj", + }, &i18n.Message{ + ID: "stashFiles", + Other: "przechowaj pliki", + }, &i18n.Message{ + ID: "open", + Other: "otwórz", + }, &i18n.Message{ + ID: "ignore", + Other: "ignoruj", + }, &i18n.Message{ + ID: "delete", + Other: "usuń", + }, &i18n.Message{ + ID: "toggleStaged", + Other: "przełącz zatwierdzenie", + }, &i18n.Message{ + ID: "refresh", + Other: "odśwież", + }, &i18n.Message{ + ID: "addPatch", + Other: "dodaj łatkę", + }, &i18n.Message{ + ID: "edit", + Other: "edytuj", + }, &i18n.Message{ + ID: "scroll", + Other: "przewiń", + }, &i18n.Message{ + ID: "abortMerge", + Other: "o scalaniu", + }, &i18n.Message{ + ID: "resolveMergeConflicts", + Other: "rozwiąż konflikty scalania", + }, &i18n.Message{ + ID: "checkout", + Other: "przełącz", + }, &i18n.Message{ + ID: "NoChangedFiles", + Other: "Brak zmienionych plików", + }, &i18n.Message{ + ID: "FileHasNoUnstagedChanges", + Other: "Plik nie zawiera żadnych nieopublikowanych zmian do dodania", + }, &i18n.Message{ + ID: "CannotGitAdd", + Other: "Nie można git add --patch nieśledzonych plików", + }, &i18n.Message{ + ID: "CantIgnoreTrackFiles", + Other: "Nie można zignorować nieśledzonych plików", + }, &i18n.Message{ + ID: "NoStagedFilesToCommit", + Other: "Brak zatwierdzonych plików do commita", + }, &i18n.Message{ + ID: "NoFilesDisplay", + Other: "Brak pliku do wyświetlenia", + }, &i18n.Message{ + ID: "PullWait", + Other: "Wciąganie zmian...", + }, &i18n.Message{ + ID: "PushWait", + Other: "Wypychanie zmian...", + }, &i18n.Message{ + ID: "FileNoMergeCons", + Other: "Ten plik nie powoduje konfliktów scalania", + }, &i18n.Message{ + ID: "SureResetHardHead", + Other: "Jesteś pewny, że chcesz wykonać `reset --hard HEAD`? Możesz stracić wprowadzone zmiany", + }, &i18n.Message{ + ID: "SureTo", + Other: "Jesteś pewny, że chcesz {{.deleteVerb}} {{.fileName}} (stracisz swoje wprowadzone zmiany)?", + }, &i18n.Message{ + ID: "AlreadyCheckedOutBranch", + Other: "Już przęłączono na tą gałąź", + }, &i18n.Message{ + ID: "SureForceCheckout", + Other: "Jesteś pewny, że chcesz wymusić przełączenie? Stracisz wszystkie lokalne zmiany", + }, &i18n.Message{ + ID: "ForceCheckoutBranch", + Other: "Wymuś przełączenie gałęzi", + }, &i18n.Message{ + ID: "BranchName", + Other: "Nazwa gałęzi", + }, &i18n.Message{ + ID: "NewBranchNameBranchOff", + Other: "Nazwa nowej gałęzi (gałąź na bazie {{.branchName}})", + }, &i18n.Message{ + ID: "CantDeleteCheckOutBranch", + Other: "Nie możesz usunąć obecnej przełączonej gałęzi!", + }, &i18n.Message{ + ID: "DeleteBranch", + Other: "Usuń gałąź", + }, &i18n.Message{ + ID: "DeleteBranchMessage", + Other: "Jesteś pewien, że chcesz usunąć gałąź {{.selectedBranchName}} ?", + }, &i18n.Message{ + ID: "CantMergeBranchIntoItself", + Other: "Nie możesz scalić gałęzi do samej siebie", + }, &i18n.Message{ + ID: "forceCheckout", + Other: "wymuś przełączenie", + }, &i18n.Message{ + ID: "merge", + Other: "scal", + }, &i18n.Message{ + ID: "checkoutByName", + Other: "przełącz używając nazwy", + }, &i18n.Message{ + ID: "newBranch", + Other: "nowa gałąź", + }, &i18n.Message{ + ID: "deleteBranch", + Other: "usuń gałąź", + }, &i18n.Message{ + ID: "NoBranchesThisRepo", + Other: "Brak gałęzi dla tego repozytorium", + }, &i18n.Message{ + ID: "NoTrackingThisBranch", + Other: "Brak śledzenia dla tej gałęzi", + }, &i18n.Message{ + ID: "CommitWithoutMessageErr", + Other: "Nie możesz commitować bez podania wiadomości", + }, &i18n.Message{ + ID: "CloseConfirm", + Other: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź", + }, &i18n.Message{ + ID: "SureResetThisCommit", + Other: "Jesteś pewny, że chcesz zresetować ten commit?", + }, &i18n.Message{ + ID: "ResetToCommit", + Other: "Zresetuj, aby commitować", + }, &i18n.Message{ + ID: "squashDown", + Other: "ściśnij w dół", + }, &i18n.Message{ + ID: "rename", + Other: "przemianuj", + }, &i18n.Message{ + ID: "resetToThisCommit", + Other: "zresetuj do tego commita", + }, &i18n.Message{ + ID: "fixupCommit", + Other: "napraw commit", + }, &i18n.Message{ + ID: "NoCommitsThisBranch", + Other: "Brak commitów dla tej gałęzi", + }, &i18n.Message{ + ID: "OnlySquashTopmostCommit", + Other: "Można tylko ścisnąć najwyższy commit", + }, &i18n.Message{ + ID: "YouNoCommitsToSquash", + Other: "Nie masz commitów do ściśnięcia", + }, &i18n.Message{ + ID: "CantFixupWhileUnstagedChanges", + Other: "Nie można wykonać naprawy, kiedy istnieją niezatwierdzone zmiany", + }, &i18n.Message{ + ID: "Fixup", + Other: "Napraw", + }, &i18n.Message{ + ID: "SureFixupThisCommit", + Other: "Jesteś pewny, ze chcesz naprawić ten commit? Commit poniżej zostanie ściśnięty w górę wraz z tym", + }, &i18n.Message{ + ID: "OnlyRenameTopCommit", + Other: "Można przmianować tylko najwyższy commit", + }, &i18n.Message{ + ID: "RenameCommit", + Other: "Przemianuj commit", + }, &i18n.Message{ + ID: "PotentialErrInGetselectedCommit", + Other: "potencjalny błąd w getSelected Commit (niedopasowane ui i stan)", + }, &i18n.Message{ + ID: "NoCommitsThisBranch", + Other: "Brak commitów dla tej gałęzi", + }, &i18n.Message{ + ID: "Error", + Other: "Błąd", + }, &i18n.Message{ + ID: "resizingPopupPanel", + Other: "skalowanie wyskakującego panelu", + }, &i18n.Message{ + ID: "RunningSubprocess", + Other: "uruchomiony podproces", + }, &i18n.Message{ + ID: "selectHunk", + Other: "wybierz kawałek", + }, &i18n.Message{ + ID: "navigateConflicts", + Other: "nawiguj konflikty", + }, &i18n.Message{ + ID: "pickHunk", + Other: "wybierz kawałek", + }, &i18n.Message{ + ID: "pickBothHunks", + Other: "wybierz oba kawałki", + }, &i18n.Message{ + ID: "undo", + Other: "cofnij", + }, &i18n.Message{ + ID: "pop", + Other: "wyciągnij", + }, &i18n.Message{ + ID: "drop", + Other: "porzuć", + }, &i18n.Message{ + ID: "apply", + Other: "zastosuj", + }, &i18n.Message{ + ID: "NoStashEntries", + Other: "Brak pozycji w schowku", + }, &i18n.Message{ + ID: "StashDrop", + Other: "Porzuć schowek", + }, &i18n.Message{ + ID: "SureDropStashEntry", + Other: "Jesteś pewny, że chcesz porzucić tę pozycję w schowku?", + }, &i18n.Message{ + ID: "NoStashTo", + Other: "Brak schowka dla {{.method}}", + }, &i18n.Message{ + ID: "NoTrackedStagedFilesStash", + Other: "Nie masz śledzonych/zatwierdzonych plików do przechowania", + }, &i18n.Message{ + ID: "StashChanges", + Other: "Przechowaj zmiany", + }, &i18n.Message{ + ID: "IssntListOfViews", + Other: "{{.name}} nie jest na liście widoków", + }, &i18n.Message{ + ID: "NoViewMachingNewLineFocusedSwitchStatement", + Other: "Brak widoku pasującego do instrukcji przełączania newLineFocused", + }, &i18n.Message{ + ID: "settingPreviewsViewTo", + Other: "ustawianie poprzedniego widoku na: {{.oldViewName}}", + }, &i18n.Message{ + ID: "newFocusedViewIs", + Other: "nowy skupiony widok to {{.newFocusedView}}", + }, &i18n.Message{ + ID: "CantCloseConfirmationPrompt", + Other: "Nie można zamknąć monitu potwierdzenia: {{.error}}", + }, &i18n.Message{ + ID: "NoChangedFiles", + Other: "Brak zmienionych plików", + }, &i18n.Message{ + ID: "ClearFilePanel", + Other: "Wyczyść panel plików", + }, &i18n.Message{ + ID: "MergeAborted", + Other: "Scalanie anulowane", + }, + ) +} diff --git a/pkg/test/test.go b/pkg/test/test.go new file mode 100644 index 000000000..7bdbd4c10 --- /dev/null +++ b/pkg/test/test.go @@ -0,0 +1,25 @@ +package test + +import ( + "errors" + "os" + "os/exec" + + "github.com/jesseduffield/lazygit/pkg/utils" +) + +// GenerateRepo generates a repo from test/repos and changes the directory to be +// inside the newly made repo +func GenerateRepo(filename string) error { + testPath := utils.GetProjectRoot() + "/test/repos/" + if err := os.Chdir(testPath); err != nil { + return err + } + if output, err := exec.Command("bash", filename).CombinedOutput(); err != nil { + return errors.New(string(output)) + } + if err := os.Chdir(testPath + "repo"); err != nil { + return err + } + return nil +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index d53ddc6dd..37e76d78a 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -69,3 +69,14 @@ func NormalizeLinefeeds(str string) string { str = strings.Replace(str, "\r", "\n", -1) return str } + +// GetProjectRoot returns the path to the root of the project. Only to be used +// in testing contexts, as with binaries it's unlikely this path will exist on +// the machine +func GetProjectRoot() string { + dir, err := os.Getwd() + if err != nil { + panic(err) + } + return strings.Split(dir, "lazygit")[0] + "lazygit" +} diff --git a/test/repos/case_insensitive_checkouts.sh b/test/repos/case_insensitive_checkouts.sh index 23997a670..1a2b83403 100755 --- a/test/repos/case_insensitive_checkouts.sh +++ b/test/repos/case_insensitive_checkouts.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + touch foo git add foo diff --git a/test/repos/gpg.sh b/test/repos/gpg.sh index 719c6467b..646f785b1 100755 --- a/test/repos/gpg.sh +++ b/test/repos/gpg.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + git config gpg.program $(which gpg) git config user.signingkey E304229F # test key diff --git a/test/repos/lots_of_commits.sh b/test/repos/lots_of_commits.sh index 7c271f751..ad55864c3 100755 --- a/test/repos/lots_of_commits.sh +++ b/test/repos/lots_of_commits.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + i=2 end=100 diff --git a/test/repos/lots_of_diffs.sh b/test/repos/lots_of_diffs.sh new file mode 100755 index 000000000..08c743f35 --- /dev/null +++ b/test/repos/lots_of_diffs.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -ex; rm -rf repo; mkdir repo; cd repo + +git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + + +echo "deleted" > deleted_staged +echo "deleted_unstaged" > deleted_unstaged +echo "modified_staged" > modified_staged +echo "modified_unstaged" > modified_unstaged +echo "renamed" > renamed_before + +git add . +git commit -m "files to delete" +rm deleted_staged +rm deleted_unstaged + +rm renamed_before +echo "renamed" > renamed_after +echo "more" >> modified_staged +echo "more" >> modified_unstaged +echo "untracked_staged" > untracked_staged +echo "untracked_unstaged" > untracked_unstaged +echo "blah" > "file with space staged" +echo "blah" > "file with space unstaged" +echo "same name as branch" > master + +git add deleted_staged +git add modified_staged +git add untracked_staged +git add "file with space staged" +git add renamed_before +git add renamed_after \ No newline at end of file diff --git a/test/repos/merge_conflict.sh b/test/repos/merge_conflict.sh index 8ba234203..51e4c1ce6 100755 --- a/test/repos/merge_conflict.sh +++ b/test/repos/merge_conflict.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + function add_spacing { for i in {1..60} diff --git a/test/repos/pre_commit_hook.sh b/test/repos/pre_commit_hook.sh index 1c24bf19f..f1b76b56a 100755 --- a/test/repos/pre_commit_hook.sh +++ b/test/repos/pre_commit_hook.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + cp ../extras/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit diff --git a/test/repos/unicode_characters.sh b/test/repos/unicode_characters.sh index 69ac5e622..fc4cddf1b 100755 --- a/test/repos/unicode_characters.sh +++ b/test/repos/unicode_characters.sh @@ -2,6 +2,9 @@ set -ex; rm -rf repo; mkdir repo; cd repo git init +git config user.email "test@example.com" +git config user.name "Lazygit Tester" + # Add some ansi, unicode, zero width joiner caracters cat <> charstest.txt