diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-15 11:18:40 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-15 11:41:37 +1000 |
commit | 826d1660c97b7c5c55420ffed21eaa5f16118118 (patch) | |
tree | 8f2f65a3d2617aa242034273c4a41b6ec5aea659 /pkg/commands | |
parent | 291a8e4de0f5d5557cf6fbd7b5b6b9d42bcaa16e (diff) |
move patch stuff into its own package
Diffstat (limited to 'pkg/commands')
-rw-r--r-- | pkg/commands/commit_file.go | 10 | ||||
-rw-r--r-- | pkg/commands/git.go | 9 | ||||
-rw-r--r-- | pkg/commands/patch/hunk.go | 142 | ||||
-rw-r--r-- | pkg/commands/patch/patch_manager.go (renamed from pkg/commands/patch_manager.go) | 12 | ||||
-rw-r--r-- | pkg/commands/patch/patch_modifier.go (renamed from pkg/commands/patch_modifier.go) | 146 | ||||
-rw-r--r-- | pkg/commands/patch/patch_modifier_test.go (renamed from pkg/commands/patch_modifier_test.go) | 2 | ||||
-rw-r--r-- | pkg/commands/patch/patch_parser.go (renamed from pkg/commands/patch_parser.go) | 2 | ||||
-rw-r--r-- | pkg/commands/patch_rebases.go | 10 |
8 files changed, 167 insertions, 166 deletions
diff --git a/pkg/commands/commit_file.go b/pkg/commands/commit_file.go index 03614be24..aa21d77ee 100644 --- a/pkg/commands/commit_file.go +++ b/pkg/commands/commit_file.go @@ -7,13 +7,3 @@ type CommitFile struct { DisplayString string Status int // one of 'WHOLE' 'PART' 'NONE' } - -const ( - // UNSELECTED is for when the commit file has not been added to the patch in any way - UNSELECTED = iota - // WHOLE is for when you want to add the whole diff of a file to the patch, - // including e.g. if it was deleted - WHOLE = iota - // PART is for when you're only talking about specific lines that have been modified - PART -) diff --git a/pkg/commands/git.go b/pkg/commands/git.go index f4fde0e89..a98ad42d1 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -16,6 +16,7 @@ import ( "github.com/go-errors/errors" gogit "github.com/go-git/go-git/v5" + "github.com/jesseduffield/lazygit/pkg/commands/patch" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/utils" @@ -84,7 +85,7 @@ type GitCommand struct { removeFile func(string) error DotGitDir string onSuccessfulContinue func() error - PatchManager *PatchManager + PatchManager *patch.PatchManager // Push to current determines whether the user has configured to push to the remote branch of the same name as the current or not PushToCurrent bool @@ -143,7 +144,7 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer, PushToCurrent: pushToCurrent, } - gitCommand.PatchManager = NewPatchManager(log, gitCommand.ApplyPatch) + gitCommand.PatchManager = patch.NewPatchManager(log, gitCommand.ApplyPatch) return gitCommand, nil } @@ -1038,7 +1039,7 @@ func (c *GitCommand) CherryPickCommits(commits []*Commit) error { } // GetCommitFiles get the specified commit files -func (c *GitCommand) GetCommitFiles(commitSha string, patchManager *PatchManager) ([]*CommitFile, error) { +func (c *GitCommand) GetCommitFiles(commitSha string, patchManager *patch.PatchManager) ([]*CommitFile, error) { files, err := c.OSCommand.RunCommandWithOutput("git diff-tree --no-commit-id --name-only -r --no-renames %s", commitSha) if err != nil { return nil, err @@ -1047,7 +1048,7 @@ func (c *GitCommand) GetCommitFiles(commitSha string, patchManager *PatchManager commitFiles := make([]*CommitFile, 0) for _, file := range strings.Split(strings.TrimRight(files, "\n"), "\n") { - status := UNSELECTED + status := patch.UNSELECTED if patchManager != nil && patchManager.CommitSha == commitSha { status = patchManager.GetFileStatus(file) } diff --git a/pkg/commands/patch/hunk.go b/pkg/commands/patch/hunk.go new file mode 100644 index 000000000..bbb2d54ff --- /dev/null +++ b/pkg/commands/patch/hunk.go @@ -0,0 +1,142 @@ +package patch + +import ( + "fmt" + "strings" + + "github.com/jesseduffield/lazygit/pkg/utils" +) + +type PatchHunk struct { + FirstLineIdx int + oldStart int + newStart int + heading string + bodyLines []string +} + +func (hunk *PatchHunk) LastLineIdx() int { + return hunk.FirstLineIdx + len(hunk.bodyLines) +} + +func newHunk(lines []string, firstLineIdx int) *PatchHunk { + header := lines[0] + bodyLines := lines[1:] + + oldStart, newStart, heading := headerInfo(header) + + return &PatchHunk{ + oldStart: oldStart, + newStart: newStart, + heading: heading, + FirstLineIdx: firstLineIdx, + bodyLines: bodyLines, + } +} + +func headerInfo(header string) (int, int, string) { + match := hunkHeaderRegexp.FindStringSubmatch(header) + + oldStart := utils.MustConvertToInt(match[1]) + newStart := utils.MustConvertToInt(match[2]) + heading := match[3] + + return oldStart, newStart, heading +} + +func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool) []string { + skippedNewlineMessageIndex := -1 + newLines := []string{} + + lineIdx := hunk.FirstLineIdx + for _, line := range hunk.bodyLines { + lineIdx++ // incrementing at the start to skip the header line + if line == "" { + break + } + isLineSelected := utils.IncludesInt(lineIndices, lineIdx) + + firstChar, content := line[:1], line[1:] + transformedFirstChar := transformedFirstChar(firstChar, reverse, isLineSelected) + + if isLineSelected || (transformedFirstChar == "\\" && skippedNewlineMessageIndex != lineIdx) || transformedFirstChar == " " { + newLines = append(newLines, transformedFirstChar+content) + continue + } + + if transformedFirstChar == "+" { + // we don't want to include the 'newline at end of file' line if it involves an addition we're not including + skippedNewlineMessageIndex = lineIdx + 1 + } + } + + return newLines +} + +func transformedFirstChar(firstChar string, reverse bool, isLineSelected bool) string { + if reverse { + if !isLineSelected && firstChar == "+" { + return " " + } else if firstChar == "-" { + return "+" + } else if firstChar == "+" { + return "-" + } else { + return firstChar + } + } + + if !isLineSelected && firstChar == "-" { + return " " + } + + return firstChar +} + +func (hunk *PatchHunk) formatHeader(oldStart int, oldLength int, newStart int, newLength int, heading string) string { + return fmt.Sprintf("@@ -%d,%d +%d,%d @@%s\n", oldStart, oldLength, newStart, newLength, heading) +} + +func (hunk *PatchHunk) formatWithChanges(lineIndices []int, reverse bool, startOffset int) (int, string) { + bodyLines := hunk.updatedLines(lineIndices, reverse) + startOffset, header, ok := hunk.updatedHeader(bodyLines, startOffset, reverse) + if !ok { + return startOffset, "" + } + return startOffset, header + strings.Join(bodyLines, "") +} + +func (hunk *PatchHunk) updatedHeader(newBodyLines []string, startOffset int, reverse bool) (int, string, bool) { + changeCount := nLinesWithPrefix(newBodyLines, []string{"+", "-"}) + oldLength := nLinesWithPrefix(newBodyLines, []string{" ", "-"}) + newLength := nLinesWithPrefix(newBodyLines, []string{"+", " "}) + + if changeCount == 0 { + // if nothing has changed we just return nothing + return startOffset, "", false + } + + var oldStart int + if reverse { + oldStart = hunk.newStart + } else { + oldStart = hunk.oldStart + } + + var newStartOffset int + // if the hunk went from zero to positive length, we need to increment the starting point by one + // if the hunk went from positive to zero length, we need to decrement the starting point by one + if oldLength == 0 { + newStartOffset = 1 + } else if newLength == 0 { + newStartOffset = -1 + } else { + newStartOffset = 0 + } + + newStart := oldStart + startOffset + newStartOffset + + newStartOffset = startOffset + newLength - oldLength + formattedHeader := hunk.formatHeader(oldStart, oldLength, newStart, newLength, hunk.heading) + return newStartOffset, formattedHeader, true +} diff --git a/pkg/commands/patch_manager.go b/pkg/commands/patch/patch_manager.go index 6c1b9ced9..d248381f6 100644 --- a/pkg/commands/patch_manager.go +++ b/pkg/commands/patch/patch_manager.go @@ -1,4 +1,4 @@ -package commands +package patch import ( "sort" @@ -7,6 +7,16 @@ import ( "github.com/sirupsen/logrus" ) +const ( + // UNSELECTED is for when the commit file has not been added to the patch in any way + UNSELECTED = iota + // WHOLE is for when you want to add the whole diff of a file to the patch, + // including e.g. if it was deleted + WHOLE = iota + // PART is for when you're only talking about specific lines that have been modified + PART +) + type fileInfo struct { mode int // one of WHOLE/PART includedLineIndices []int diff --git a/pkg/commands/patch_modifier.go b/pkg/commands/patch/patch_modifier.go index f4a782015..c2bbc60f6 100644 --- a/pkg/commands/patch_modifier.go +++ b/pkg/commands/patch/patch_modifier.go @@ -1,160 +1,16 @@ -package commands +package patch import ( "fmt" "regexp" - "strconv" "strings" - "github.com/jesseduffield/lazygit/pkg/utils" "github.com/sirupsen/logrus" ) var hunkHeaderRegexp = regexp.MustCompile(`(?m)^@@ -(\d+)[^\+]+\+(\d+)[^@]+@@(.*)$`) var patchHeaderRegexp = regexp.MustCompile(`(?ms)(^diff.*?)^@@`) -type PatchHunk struct { - FirstLineIdx int - oldStart int - newStart int - heading string - bodyLines []string -} - -func (hunk *PatchHunk) LastLineIdx() int { - return hunk.FirstLineIdx + len(hunk.bodyLines) -} - -func newHunk(lines []string, firstLineIdx int) *PatchHunk { - header := lines[0] - bodyLines := lines[1:] - - oldStart, newStart, heading := headerInfo(header) - - return &PatchHunk{ - oldStart: oldStart, - newStart: newStart, - heading: heading, - FirstLineIdx: firstLineIdx, - bodyLines: bodyLines, - } -} - -func headerInfo(header string) (int, int, string) { - match := hunkHeaderRegexp.FindStringSubmatch(header) - - oldStart := mustConvertToInt(match[1]) - newStart := mustConvertToInt(match[2]) - heading := match[3] - - return oldStart, newStart, heading -} - -func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool) []string { - skippedNewlineMessageIndex := -1 - newLines := []string{} - - lineIdx := hunk.FirstLineIdx - for _, line := range hunk.bodyLines { - lineIdx++ // incrementing at the start to skip the header line - if line == "" { - break - } - isLineSelected := utils.IncludesInt(lineIndices, lineIdx) - - firstChar, content := line[:1], line[1:] - transformedFirstChar := transformedFirstChar(firstChar, reverse, isLineSelected) - - if isLineSelected || (transformedFirstChar == "\\" && skippedNewlineMessageIndex != lineIdx) || transformedFirstChar == " " { - newLines = append(newLines, transformedFirstChar+content) - continue - } - - if transformedFirstChar == "+" { - // we don't want to include the 'newline at end of file' line if it involves an addition we're not including - skippedNewlineMessageIndex = lineIdx + 1 - } - } - - return newLines -} - -func transformedFirstChar(firstChar string, reverse bool, isLineSelected bool) string { - if reverse { - if !isLineSelected && firstChar == "+" { - return " " - } else if firstChar == "-" { - return "+" - } else if firstChar == "+" { - return "-" - } else { - return firstChar - } - } - - if !isLineSelected && firstChar == "-" { - return " " - } - - return firstChar -} - -func (hunk *PatchHunk) formatHeader(oldStart int, oldLength int, newStart int, newLength int, heading string) string { - return fmt.Sprintf("@@ -%d,%d +%d,%d @@%s\n", oldStart, oldLength, newStart, newLength, heading) -} - -func (hunk *PatchHunk) formatWithChanges(lineIndices []int, reverse bool, startOffset int) (int, string) { - bodyLines := hunk.updatedLines(lineIndices, reverse) - startOffset, header, ok := hunk.updatedHeader(bodyLines, startOffset, reverse) - if !ok { - return startOffset, "" - } - return startOffset, header + strings.Join(bodyLines, "") -} - -func (hunk *PatchHunk) updatedHeader(newBodyLines []string, startOffset int, reverse bool) (int, string, bool) { - changeCount := nLinesWithPrefix(newBodyLines, []string{"+", "-"}) - oldLength := nLinesWithPrefix(newBodyLines, []string{" ", "-"}) - newLength := nLinesWithPrefix(newBodyLines, []string{"+", " "}) - - if changeCount == 0 { - // if nothing has changed we just return nothing - return startOffset, "", false - } - - var oldStart int - if reverse { - oldStart = hunk.newStart - } else { - oldStart = hunk.oldStart - } - - var newStartOffset int - // if the hunk went from zero to positive length, we need to increment the starting point by one - // if the hunk went from positive to zero length, we need to decrement the starting point by one - if oldLength == 0 { - newStartOffset = 1 - } else if newLength == 0 { - newStartOffset = -1 - } else { - newStartOffset = 0 - } - - newStart := oldStart + startOffset + newStartOffset - - newStartOffset = startOffset + newLength - oldLength - formattedHeader := hunk.formatHeader(oldStart, oldLength, newStart, newLength, hunk.heading) - return newStartOffset, formattedHeader, true -} - -func mustConvertToInt(s string) int { - i, err := strconv.Atoi(s) - if err != nil { - panic(err) - } - return i -} - func GetHeaderFromDiff(diff string) string { match := patchHeaderRegexp.FindStringSubmatch(diff) if len(match) <= 1 { diff --git a/pkg/commands/patch_modifier_test.go b/pkg/commands/patch/patch_modifier_test.go index 66b675923..8b866019b 100644 --- a/pkg/commands/patch_modifier_test.go +++ b/pkg/commands/patch/patch_modifier_test.go @@ -1,4 +1,4 @@ -package commands +package patch import ( "fmt" diff --git a/pkg/commands/patch_parser.go b/pkg/commands/patch/patch_parser.go index b54c57c1f..55554fec3 100644 --- a/pkg/commands/patch_parser.go +++ b/pkg/commands/patch/patch_parser.go @@ -1,4 +1,4 @@ -package commands +package patch import ( "regexp" diff --git a/pkg/commands/patch_rebases.go b/pkg/commands/patch_rebases.go index bb1ca5b98..f4d411514 100644 --- a/pkg/commands/patch_rebases.go +++ b/pkg/commands/patch_rebases.go @@ -2,11 +2,13 @@ package commands import ( "fmt" + "github.com/go-errors/errors" + "github.com/jesseduffield/lazygit/pkg/commands/patch" ) // DeletePatchesFromCommit applies a patch in reverse for a commit -func (c *GitCommand) DeletePatchesFromCommit(commits []*Commit, commitIndex int, p *PatchManager) error { +func (c *GitCommand) DeletePatchesFromCommit(commits []*Commit, commitIndex int, p *patch.PatchManager) error { if err := c.BeginInteractiveRebaseForCommit(commits, commitIndex); err != nil { return err } @@ -33,7 +35,7 @@ func (c *GitCommand) DeletePatchesFromCommit(commits []*Commit, commitIndex int, return c.GenericMerge("rebase", "continue") } -func (c *GitCommand) MovePatchToSelectedCommit(commits []*Commit, sourceCommitIdx int, destinationCommitIdx int, p *PatchManager) error { +func (c *GitCommand) MovePatchToSelectedCommit(commits []*Commit, sourceCommitIdx int, destinationCommitIdx int, p *patch.PatchManager) error { if sourceCommitIdx < destinationCommitIdx { if err := c.BeginInteractiveRebaseForCommit(commits, destinationCommitIdx); err != nil { return err @@ -134,7 +136,7 @@ func (c *GitCommand) MovePatchToSelectedCommit(commits []*Commit, sourceCommitId return c.GenericMerge("rebase", "continue") } -func (c *GitCommand) PullPatchIntoIndex(commits []*Commit, commitIdx int, p *PatchManager, stash bool) error { +func (c *GitCommand) PullPatchIntoIndex(commits []*Commit, commitIdx int, p *patch.PatchManager, stash bool) error { if stash { if err := c.StashSave(c.Tr.SLocalize("StashPrefix") + commits[commitIdx].Sha); err != nil { return err @@ -187,7 +189,7 @@ func (c *GitCommand) PullPatchIntoIndex(commits []*Commit, commitIdx int, p *Pat return c.GenericMerge("rebase", "continue") } -func (c *GitCommand) PullPatchIntoNewCommit(commits []*Commit, commitIdx int, p *PatchManager) error { +func (c *GitCommand) PullPatchIntoNewCommit(commits []*Commit, commitIdx int, p *patch.PatchManager) error { if err := c.BeginInteractiveRebaseForCommit(commits, commitIdx); err != nil { return err } |