mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-07-07 18:05:40 +02:00
- Refactor arguments of the function to make more sense. - `path` can be inferred from `repo` receiver. - `line` can be `uint64`. - The two calls to this function check for specific errors, do this error checking in the function. - The ID of a object format is not 40 in the case of SHA256, get the object format and use the correct length. - Add test coverage for `LineBlame`, notably it checks for the errors that can legitimately happen. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8419 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package git
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
)
|
|
|
|
var (
|
|
ErrBlameFileDoesNotExist = errors.New("the blamed file does not exist")
|
|
ErrBlameFileNotEnoughLines = errors.New("the blamed file has not enough lines")
|
|
|
|
notEnoughLinesRe = regexp.MustCompile(`^fatal: file .+ has only \d+ lines?\n$`)
|
|
)
|
|
|
|
// LineBlame returns the latest commit at the given line
|
|
func (repo *Repository) LineBlame(revision, file string, line uint64) (*Commit, error) {
|
|
res, _, gitErr := NewCommand(repo.Ctx, "blame").
|
|
AddOptionFormat("-L %d,%d", line, line).
|
|
AddOptionValues("-p", revision).
|
|
AddDashesAndList(file).RunStdString(&RunOpts{Dir: repo.Path})
|
|
if gitErr != nil {
|
|
stdErr := gitErr.Stderr()
|
|
|
|
if stdErr == fmt.Sprintf("fatal: no such path %s in %s\n", file, revision) {
|
|
return nil, ErrBlameFileDoesNotExist
|
|
}
|
|
if notEnoughLinesRe.MatchString(stdErr) {
|
|
return nil, ErrBlameFileNotEnoughLines
|
|
}
|
|
|
|
return nil, gitErr
|
|
}
|
|
|
|
objectFormat, err := repo.GetObjectFormat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
objectIDLen := objectFormat.FullLength()
|
|
if len(res) < objectIDLen {
|
|
return nil, fmt.Errorf("output of blame is invalid, cannot contain commit ID: %s", res)
|
|
}
|
|
|
|
return repo.GetCommit(res[:objectIDLen])
|
|
}
|