Repository: jesseduffield/lazygit
File: pkg/gui/controllers/helpers/fixup_helper.go (Go)

Code before:
			return err
		}
		_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
	}

	self.c.Contexts().LocalCommits.SetSelectedLineIdx(index)
	return self.c.PushContext(self.c.Contexts().LocalCommits)
}

func (self *FixupHelper) getDiff() (string, bool, error) {
	args := []string{"-U0", "--ignore-submodules=all", "HEAD", "--"}

	// Try staged changes first
	useIndex := true
	diff, err := self.c.Git().Diff.DiffIndexCmdObj(append([]string{"--cached"}, args...)...).RunWithOutput()

	if err == nil && diff == "" {
		useIndex = false
		// If there are no staged changes, try unstaged changes
		diff, err = self.c.Git().Diff.DiffIndexCmdObj(args...).RunWithOutput()
	}

	return diff, useIndex, err
}

func (self *FixupHelper) parseDiff(diff string) []*deletedLineInfo {
	lines := strings.Split(strings.TrimSuffix(diff, "\n"), "\n")

	deletedLineInfos := []*deletedLineInfo{}

	hunkHeaderRegexp := regexp.MustCompile(`@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@`)

	var filename string
	var currentLineInfo *deletedLineInfo
	finishHunk := func() {
		if currentLineInfo != nil && currentLineInfo.numLines > 0 {
			deletedLineInfos = append(deletedLineInfos, currentLineInfo)
		}
	}
	for _, line := range lines {
		if strings.HasPrefix(line, "diff --git") {
			finishHunk()
			currentLineInfo = nil
		} else if strings.HasPrefix(line, "--- ") {
			// For some reason, the line ends with a tab character if the file
			// name contains spaces
			filename = strings.TrimRight(line[6:], "\t")
		} else if strings.HasPrefix(line, "@@ ") {
			finishHunk()
			match := hunkHeaderRegexp.FindStringSubmatch(line)
			startIdx := utils.MustConvertToInt(match[1])

Review comment (suggestion):
Worth looking at `pkg/commands/patch/parse.go` to see if that patch parser does what you need, to spare us from having two separate patch parsers in the codebase. But if you think this use case is bespoke enough to justify its own, I'm cool with that.

Code after:
	doIt := func() error {
		if !hasStagedChanges {
			if err := self.c.Git().WorkingTree.StageAll(); err != nil {
				return err
			}
			_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
		}

		self.c.Contexts().LocalCommits.SetSelectedLineIdx(index)
		return self.c.PushContext(self.c.Contexts().LocalCommits)
	}

	if hasHunksWithOnlyAddedLines {
		return self.c.Confirm(types.ConfirmOpts{
			Title:  self.c.Tr.FindBaseCommitForFixup,
			Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning,
			HandleConfirm: func() error {
				return doIt()
			},
		})
	}

	return doIt()
}

func (self *FixupHelper) getDiff() (string, bool, error) {
	args := []string{"-U0", "--ignore-submodules=all", "HEAD", "--"}

	// Try staged changes first
	hasStagedChanges := true
	diff, err := self.c.Git().Diff.DiffIndexCmdObj(append([]string{"--cached"}, args...)...).RunWithOutput()

	if err == nil && diff == "" {
		hasStagedChanges = false
		// If there are no staged changes, try unstaged changes
		diff, err = self.c.Git().Diff.DiffIndexCmdObj(args...).RunWithOutput()
	}

	return diff, hasStagedChanges, err
}

func (self *FixupHelper) parseDiff(diff string) ([]*deletedLineInfo, bool) {
	lines := strings.Split(strings.TrimSuffix(diff, "\n"), "\n")

	deletedLineInfos := []*deletedLineInfo{}
	hasHunksWithOnlyAddedLines := false

	hunkHeaderRegexp := regexp.MustCompile(`@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@`)

	var filename string
	var currentLineInfo *deletedLineInfo