Repository: jesseduffield/lazygit
File: pkg/commands/git_commands/commit_loader.go (Go)

Code before:
	}
	return result, nil
}

// extractCommitFromLine takes a line from a git log and extracts the hash, message, date, and tag if present
// then puts them into a commit object
// example input:
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
func (self *CommitLoader) extractCommitFromLine(hashPool *utils.StringPool, line string, showDivergence bool) *models.Commit {
	split := strings.SplitN(line, "\x00", 8)

	// Ensure we have the minimum required fields (at least 5 for basic functionality)
	if len(split) < 5 {
		self.Log.Warnf("Malformed git log line: expected at least 5 fields, got %d. Line: %s", len(split), line)
		return nil
	}

	hash := split[0]
	unixTimestamp := split[1]
	authorName := split[2]
	authorEmail := split[3]

	// Safe access to optional fields with defaults
	parentHashes := ""
	if len(split) > 4 {
		parentHashes = split[4]
	}

	divergence := models.DivergenceNone
	if showDivergence && len(split) > 5 {
		divergence = lo.Ternary(split[5] == "<", models.DivergenceLeft, models.DivergenceRight)
	}

	extraInfo := ""
	if len(split) > 6 {
		extraInfo = strings.TrimSpace(split[6])
	}

	message := ""
	if len(split) > 7 {
		message = split[7]
	}

	tags := []string{}

	if extraInfo != "" {
		extraInfoFields := strings.Split(extraInfo, ",")
		for _, extraInfoField := range extraInfoFields {
			extraInfoField = strings.TrimSpace(extraInfoField)
			re := regexp.MustCompile(`tag: (.+)`)
			tagMatch := re.FindStringSubmatch(extraInfoField)

Review comment (suggestion):
I think it would make more sense to increase the `if len(split) < 5 {` above to 7 in this commit, and access the parentHashes and divergence fields unconditionally; they will never be missing (unless you have a commit with thousands of parent commits, which is not going to happen).

Of course, the commit history would be a lot cleaner if you had swapped the first two commits, but I can understand if you don't want to go to the trouble now. (If this were my PR, I'd do it. 😉)

Code after:
	}
	return result, nil
}

// extractCommitFromLine takes a line from a git log and extracts the hash, message, date, and tag if present
// then puts them into a commit object
// example input:
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
func (self *CommitLoader) extractCommitFromLine(hashPool *utils.StringPool, line string, showDivergence bool) *models.Commit {
	split := strings.SplitN(line, "\x00", 8)

	// Ensure we have the minimum required fields (at least 7 for basic functionality)
	if len(split) < 7 {
		self.Log.Warnf("Malformed git log line: expected at least 7 fields, got %d. Line: %s", len(split), line)
		return nil
	}

	hash := split[0]
	unixTimestamp := split[1]
	authorName := split[2]
	authorEmail := split[3]
	parentHashes := split[4]
	divergence := models.DivergenceNone
	if showDivergence {
		divergence = lo.Ternary(split[5] == "<", models.DivergenceLeft, models.DivergenceRight)
	}
	extraInfo := strings.TrimSpace(split[6])

	// message (and the \x00 before it) might not be present if extraInfo is extremely long
	message := ""
	if len(split) > 7 {
		message = split[7]
	}

	var tags []string

	if extraInfo != "" {
		extraInfoFields := strings.Split(extraInfo, ",")
		for _, extraInfoField := range extraInfoFields {
			extraInfoField = strings.TrimSpace(extraInfoField)
			re := regexp.MustCompile(`tag: (.+)`)
			tagMatch := re.FindStringSubmatch(extraInfoField)
			if len(tagMatch) > 1 {
				tags = append(tags, tagMatch[1])
			}
		}

		extraInfo = "(" + extraInfo + ")"
	}

	unitTimestampInt, _ := strconv.Atoi(unixTimestamp)