1package git23import (4 "bytes"5 "context"6)78// BlameOptions contains optional arguments for blaming a file.9// Docs: https://git-scm.com/docs/git-blame10type BlameOptions struct {11 CommandOptions12}1314// Blame returns blame results of the file with the given revision of the15// repository.16func (r *Repository) Blame(ctx context.Context, rev, file string, opts ...BlameOptions) (*Blame, error) {17 var opt BlameOptions18 if len(opts) > 0 {19 opt = opts[0]20 }2122 args := []string{"blame", "-l", "-s", rev, "--", file}23 stdout, err := exec(ctx, r.path, args, opt.Envs)24 if err != nil {25 return nil, err26 }2728 lines := bytes.Split(stdout, []byte{'\n'})29 blame := &Blame{30 lines: make([]*Commit, 0, len(lines)),31 }32 for _, line := range lines {33 if len(line) < 40 {34 break35 }36 id := line[:40]3738 // Earliest commit is indicated by a leading "^"39 if id[0] == '^' {40 id = id[1:]41 }42 commit, err := r.CatFileCommit(ctx, string(id)) //nolint43 if err != nil {44 return nil, err45 }46 blame.lines = append(blame.lines, commit)47 }48 return blame, nil49}