diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/app/app.go | 2 | ||||
| -rw-r--r-- | pkg/git/branch.go | 6 | ||||
| -rw-r--r-- | pkg/git/stash.go | 11 | ||||
| -rw-r--r-- | pkg/git/status.go | 24 | ||||
| -rw-r--r-- | pkg/gui/diffview.go | 149 | ||||
| -rw-r--r-- | pkg/gui/gui.go | 3 | ||||
| -rw-r--r-- | pkg/gui/keybindings.go | 43 | ||||
| -rw-r--r-- | pkg/gui/queuehandler.go | 1 | ||||
| -rw-r--r-- | pkg/gui/statusview.go | 2 | ||||
| -rw-r--r-- | pkg/gui/textstyle.go | 25 |
10 files changed, 193 insertions, 73 deletions
diff --git a/pkg/app/app.go b/pkg/app/app.go index 9082386..740e3ff 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -33,7 +33,7 @@ func Setup(setupConfig SetupConfig) (*App, error) { log.Error(err) return app, err } - directories := make([]string, 0) + var directories []string if len(app.Config.Directories) <= 0 || setupConfig.IgnoreConfig { directories = generateDirectories(setupConfig.Directories, setupConfig.Depth) diff --git a/pkg/git/branch.go b/pkg/git/branch.go index 0fbfdf0..ace5f79 100644 --- a/pkg/git/branch.go +++ b/pkg/git/branch.go @@ -130,10 +130,8 @@ func (entity *RepoEntity) Checkout(branch *Branch) error { entity.Branch = branch entity.RefreshPushPull() // make this conditional on global scale - if err := entity.Remote.SyncBranches(branch.Name); err != nil { - return err - } - return nil + err = entity.Remote.SyncBranches(branch.Name) + return err } // checking the branch if it has any changes from its head revision. Initially diff --git a/pkg/git/stash.go b/pkg/git/stash.go index 66254c8..9d813a6 100644 --- a/pkg/git/stash.go +++ b/pkg/git/stash.go @@ -93,3 +93,14 @@ func (stashedItem *StashedItem) Pop() (output string, err error) { output, err = GenericGitCommandWithErrorOutput(stashedItem.EntityPath, args) return output, err } + +// Show is the wrapper of "git stash show -p " command +func (stashedItem *StashedItem) Show() (output string, err error) { + args := make([]string, 0) + args = append(args, stashCommand) + args = append(args, "show") + args = append(args, "-p") + args = append(args, "stash@{"+strconv.Itoa(stashedItem.StashID)+"}") + output, err = GenericGitCommandWithErrorOutput(stashedItem.EntityPath, args) + return output, err +} diff --git a/pkg/git/status.go b/pkg/git/status.go index 8db2ec7..4cca604 100644 --- a/pkg/git/status.go +++ b/pkg/git/status.go @@ -25,21 +25,21 @@ var ( // StatusNotupdated says file not updated StatusNotupdated FileStatus = ' ' // StatusModified says file is modifed - StatusModified FileStatus = 'M' + StatusModified FileStatus = 'M' // StatusAdded says file is added to index - StatusAdded FileStatus = 'A' + StatusAdded FileStatus = 'A' // StatusDeleted says file is deleted - StatusDeleted FileStatus = 'D' + StatusDeleted FileStatus = 'D' // StatusRenamed says file is renamed - StatusRenamed FileStatus = 'R' + StatusRenamed FileStatus = 'R' // StatusCopied says file is copied - StatusCopied FileStatus = 'C' + StatusCopied FileStatus = 'C' // StatusUpdated says file is updated - StatusUpdated FileStatus = 'U' + StatusUpdated FileStatus = 'U' // StatusUntracked says file is untraced StatusUntracked FileStatus = '?' // StatusIgnored says file is ignored - StatusIgnored FileStatus = '!' + StatusIgnored FileStatus = '!' ) func shortStatus(entity *RepoEntity, option string) string { @@ -79,3 +79,13 @@ func (entity *RepoEntity) LoadFiles() ([]*File, error) { } return files, nil } + +// Diff is a wrapper of "git diff" command for a file to compare with HEAD rev +func (file *File) Diff() (output string, err error) { + args := make([]string, 0) + args = append(args, "diff") + args = append(args, "HEAD") + args = append(args, file.Name) + output, err = GenericGitCommandWithErrorOutput(strings.TrimSuffix(file.AbsPath, file.Name), args) + return output, err +} diff --git a/pkg/gui/diffview.go b/pkg/gui/diffview.go index b775f95..f99d7f2 100644 --- a/pkg/gui/diffview.go +++ b/pkg/gui/diffview.go @@ -2,42 +2,121 @@ package gui import ( "fmt" - "regexp" - "strings" + "github.com/isacikgoz/gitbatch/pkg/git" "github.com/jroimartin/gocui" ) -// open diff view for the selcted commit -func (gui *Gui) openCommitDiffView(g *gocui.Gui, v *gocui.View) error { +var diffReturnView string + +// renders the diff view +func (gui *Gui) prepareDiffView(g *gocui.Gui, v *gocui.View, display []string) (out *gocui.View, err error) { maxX, maxY := g.Size() - v, err := g.SetView(commitDiffViewFeature.Name, 5, 3, maxX-5, maxY-3) + diffReturnView = v.Name() + out, err = g.SetView(diffViewFeature.Name, 5, 3, maxX-5, maxY-3) + if err != nil { + if err != gocui.ErrUnknownView { + return out, err + } + } + out.Title = diffViewFeature.Title + out.Overwrite = true + out.Wrap = true + gui.updateKeyBindingsView(g, diffViewFeature.Name) + if _, err = g.SetCurrentView(diffViewFeature.Name); err != nil { + return out, err + } + for _, line := range display { + fmt.Fprintln(out, line) + } + return out, err +} + +// open diff view for the selcted commit +// called from commitview, so initial view is commitview +func (gui *Gui) openCommitDiffView(g *gocui.Gui, v *gocui.View) (err error) { + entity := gui.getSelectedRepository() + commit := entity.Commit + commitDetail := []string{("Hash: " + cyan.Sprint(commit.Hash) + "\n" + "Author: " + commit.Author + + "\n" + commit.Time + "\n" + "\n" + "\t\t" + commit.Message + "\n")} + diff, err := entity.Diff(entity.Commit.Hash) + if err != nil { + return err + } + colorized := colorizeDiff(diff) + commitDetail = append(commitDetail, colorized...) + out, err := gui.prepareDiffView(g, v, commitDetail) if err != nil { if err != gocui.ErrUnknownView { return err } - v.Title = commitDiffViewFeature.Title - v.Overwrite = true - v.Wrap = true + } + out.Title = " Commit Detail " + return nil +} - entity := gui.getSelectedRepository() - commit := entity.Commit - commitDetail := "Hash: " + cyan.Sprint(commit.Hash) + "\n" + "Author: " + commit.Author + - "\n" + commit.Time + "\n" + "\n" + "\t\t" + commit.Message + "\n" - fmt.Fprintln(v, commitDetail) - diff, err := entity.Diff(entity.Commit.Hash) - if err != nil { +// called from status, so initial view may be stagedview or unstaged view +func (gui *Gui) openFileDiffView(g *gocui.Gui, v *gocui.View) (err error) { + entity := gui.getSelectedRepository() + _, cy := v.Cursor() + _, oy := v.Origin() + var files []*git.File + switch v.Name() { + case unstageViewFeature.Name: + _, files, err = generateFileLists(entity) + case stageViewFeature.Name: + files, _, err = generateFileLists(entity) + } + if err != nil { + return err + } + if len(files) <= 0 { + return nil + } + output, err := files[cy+oy].Diff() + if err != nil || len(output) <= 0 { + return nil + } + if err != nil { + if err = gui.openErrorView(g, output, + "You should manually resolve this issue", + diffReturnView); err != nil { return err } - colorized := colorizeDiff(diff) - for _, line := range colorized { - fmt.Fprintln(v, line) + } + colorized := colorizeDiff(output) + _, err = gui.prepareDiffView(g, v, colorized) + if err != nil { + if err != gocui.ErrUnknownView { + return err } } + return nil +} - gui.updateKeyBindingsView(g, commitDiffViewFeature.Name) - if _, err := g.SetCurrentView(commitDiffViewFeature.Name); err != nil { - return err +// called from stashview, so initial view is stashview +func (gui *Gui) showStash(g *gocui.Gui, v *gocui.View) (err error) { + entity := gui.getSelectedRepository() + _, oy := v.Origin() + _, cy := v.Cursor() + if len(entity.Stasheds) <= 0 { + return nil + } + stashedItem := entity.Stasheds[oy+cy] + output, err := stashedItem.Show() + if err != nil { + if err = gui.openErrorView(g, output, + "You should manually resolve this issue", + stashViewFeature.Name); err != nil { + return err + } + } + colorized := colorizeDiff(output) + _, err = gui.prepareDiffView(g, v, colorized) + if err != nil { + if err != gocui.ErrUnknownView { + return err + } } return nil } @@ -47,33 +126,9 @@ func (gui *Gui) closeCommitDiffView(g *gocui.Gui, v *gocui.View) error { if err := g.DeleteView(v.Name()); err != nil { return nil } - if _, err := g.SetCurrentView(commitViewFeature.Name); err != nil { + if _, err := g.SetCurrentView(diffReturnView); err != nil { return err } - gui.updateKeyBindingsView(g, commitViewFeature.Name) + gui.updateKeyBindingsView(g, diffReturnView) return nil } - -// colorize the plain diff text collected from system output -// the style is near to original diff command -func colorizeDiff(original string) (colorized []string) { - colorized = strings.Split(original, "\n") - re := regexp.MustCompile(`@@ .+ @@`) - for i, line := range colorized { - if len(line) > 0 { - if line[0] == '-' { - colorized[i] = red.Sprint(line) - } else if line[0] == '+' { - colorized[i] = green.Sprint(line) - } else if re.MatchString(line) { - s := re.FindString(line) - colorized[i] = cyan.Sprint(s) + line[len(s):] - } else { - continue - } - } else { - continue - } - } - return colorized -} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 2e75b4a..290cb88 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -61,7 +61,7 @@ var ( commitViewFeature = viewFeature{Name: "commits", Title: " Commits "} scheduleViewFeature = viewFeature{Name: "schedule", Title: " Schedule "} keybindingsViewFeature = viewFeature{Name: "keybindings", Title: " Keybindings "} - commitDiffViewFeature = viewFeature{Name: "commitdiff", Title: " Commit Detail "} + diffViewFeature = viewFeature{Name: "diff", Title: " Diff Detail "} cheatSheetViewFeature = viewFeature{Name: "cheatsheet", Title: " Application Controls "} errorViewFeature = viewFeature{Name: "error", Title: " Error "} @@ -212,6 +212,7 @@ func (gui *Gui) previousMainView(g *gocui.Gui, v *gocui.View) error { err := gui.previousViewOfGroup(g, v, mainViews) return err } + // quit from the gui and end its loop func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error { return gocui.ErrQuit diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 1a6d6c9..a9cfe63 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -176,6 +176,14 @@ func (gui *Gui) generateKeybindings() error { Display: "p", Description: "Pop Item", Vital: true, + }, { + View: stashViewFeature.Name, + Key: 'd', + Modifier: gocui.ModNone, + Handler: gui.showStash, + Display: "d", + Description: "Show diff", + Vital: true, }, // staged view { @@ -194,6 +202,14 @@ func (gui *Gui) generateKeybindings() error { Display: "ctrl+r", Description: "Reset All Items", Vital: true, + }, { + View: stageViewFeature.Name, + Key: 'd', + Modifier: gocui.ModNone, + Handler: gui.openFileDiffView, + Display: "d", + Description: "Show diff", + Vital: true, }, // unstaged view { @@ -212,6 +228,14 @@ func (gui *Gui) generateKeybindings() error { Display: "ctrl+a", Description: "Add All Items", Vital: true, + }, { + View: unstageViewFeature.Name, + Key: 'd', + Modifier: gocui.ModNone, + Handler: gui.openFileDiffView, + Display: "d", + Description: "Show diff", + Vital: true, }, // Main view controls { @@ -473,7 +497,7 @@ func (gui *Gui) generateKeybindings() error { }, // Diff View Controls { - View: commitDiffViewFeature.Name, + View: diffViewFeature.Name, Key: 'c', Modifier: gocui.ModNone, Handler: gui.closeCommitDiffView, @@ -481,7 +505,7 @@ func (gui *Gui) generateKeybindings() error { Description: "close/cancel", Vital: true, }, { - View: commitDiffViewFeature.Name, + View: diffViewFeature.Name, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.fastCursorUp, @@ -489,7 +513,7 @@ func (gui *Gui) generateKeybindings() error { Description: "Page up", Vital: true, }, { - View: commitDiffViewFeature.Name, + View: diffViewFeature.Name, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.fastCursorDown, @@ -497,7 +521,7 @@ func (gui *Gui) generateKeybindings() error { Description: "Page down", Vital: true, }, { - View: commitDiffViewFeature.Name, + View: diffViewFeature.Name, Key: 'k', Modifier: gocui.ModNone, Handler: gui.fastCursorUp, @@ -505,7 +529,7 @@ func (gui *Gui) generateKeybindings() error { Description: "Page up", Vital: false, }, { - View: commitDiffViewFeature.Name, + View: diffViewFeature.Name, Key: 'j', Modifier: gocui.ModNone, Handler: gui.fastCursorDown, @@ -630,16 +654,13 @@ func (gui *Gui) updateKeyBindingsView(g *gocui.Gui, viewName string) error { switch mode := gui.State.Mode.ModeID; mode { case FetchMode: v.BgColor = gocui.ColorBlue - v.FgColor = gocui.ColorWhite - modeLabel = fetchSymbol + ws + bold.Sprint("FETCH") + modeLabel = fetchSymbol + ws + "FETCH" case PullMode: v.BgColor = gocui.ColorMagenta - v.FgColor = gocui.ColorWhite - modeLabel = pullSymbol + ws + bold.Sprint("PULL") + modeLabel = pullSymbol + ws + "PULL" case MergeMode: v.BgColor = gocui.ColorCyan - v.FgColor = gocui.ColorBlack - modeLabel = mergeSymbol + ws + black.Sprint(bold.Sprint("MERGE")) + modeLabel = mergeSymbol + ws + "MERGE" default: modeLabel = "No mode selected" } diff --git a/pkg/gui/queuehandler.go b/pkg/gui/queuehandler.go index cbbc372..3be1472 100644 --- a/pkg/gui/queuehandler.go +++ b/pkg/gui/queuehandler.go @@ -9,7 +9,6 @@ import ( func (gui *Gui) startQueue(g *gocui.Gui, v *gocui.View) error { go func(gui_go *Gui, g_go *gocui.Gui) { for { - indicateQueueStarted(g_go) job, finished, err := gui_go.State.Queue.StartNext() g_go.Update(func(gu *gocui.Gui) error { gui_go.refreshMain(gu) diff --git a/pkg/gui/statusview.go b/pkg/gui/statusview.go index 282d643..d6f0be1 100644 --- a/pkg/gui/statusview.go +++ b/pkg/gui/statusview.go @@ -11,7 +11,7 @@ var ( statusHeaderViewFeature = viewFeature{Name: "status-header", Title: " Status Header "} // statusViewFeature = viewFeature{Name: "status", Title: " Status "} stageViewFeature = viewFeature{Name: "staged", Title: " Staged "} - unstageViewFeature = viewFeature{Name: "unstaged", Title: " Unstaged "} + unstageViewFeature = viewFeature{Name: "unstaged", Title: " Not Staged "} stashViewFeature = viewFeature{Name: "stash", Title: " Stash "} statusViews = []viewFeature{stageViewFeature, unstageViewFeature, stashViewFeature} diff --git a/pkg/gui/textstyle.go b/pkg/gui/textstyle.go index 50bc945..33f172d 100644 --- a/pkg/gui/textstyle.go +++ b/pkg/gui/textstyle.go @@ -2,6 +2,7 @@ package gui import ( "regexp" + "strings" "github.com/fatih/color" "github.com/isacikgoz/gitbatch/pkg/git" @@ -118,6 +119,30 @@ func adjustTextLength(text string, maxLength int) (adjusted string) { return text } +// colorize the plain diff text collected from system output +// the style is near to original diff command +func colorizeDiff(original string) (colorized []string) { + colorized = strings.Split(original, "\n") + re := regexp.MustCompile(`@@ .+ @@`) + for i, line := range colorized { + if len(line) > 0 { + if line[0] == '-' { + colorized[i] = red.Sprint(line) + } else if line[0] == '+' { + colorized[i] = green.Sprint(line) + } else if re.MatchString(line) { + s := re.FindString(line) + colorized[i] = cyan.Sprint(s) + line[len(s):] + } else { + continue + } + } else { + continue + } + } + return colorized +} + // the remote link can be too verbose sometimes, so it is good to trim it func trimRemoteURL(url string) (urltype string, shorturl string) { // lets trim the unnecessary .git extension of the url |
