blob: ea0ee0051a2469fa6e29b12b6097f8d155f3aecc [file] [log] [blame]
package gitiles_common
import (
"context"
"fmt"
"net/http"
"go.skia.org/infra/autoroll/go/config"
"go.skia.org/infra/autoroll/go/config_vars"
"go.skia.org/infra/autoroll/go/repo_manager/common/version_file_common"
"go.skia.org/infra/autoroll/go/revision"
"go.skia.org/infra/go/gitiles"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/go/vcsinfo"
"go.skia.org/infra/go/vfs"
gitiles_vfs "go.skia.org/infra/go/vfs/gitiles"
)
// GitilesRepo provides helpers for dealing with repos which use Gitiles.
type GitilesRepo struct {
gitiles.GitilesRepo
branch *config_vars.Template
defaultBugProject string
deps []*config.VersionFileConfig
}
// NewGitilesRepo returns a GitilesRepo instance.
func NewGitilesRepo(ctx context.Context, c *config.GitilesConfig, reg *config_vars.Registry, client *http.Client) (*GitilesRepo, error) {
if err := c.Validate(); err != nil {
return nil, skerr.Wrap(err)
}
branch, err := config_vars.NewTemplate(c.Branch)
if err != nil {
return nil, skerr.Wrap(err)
}
if err := reg.Register(branch); err != nil {
return nil, skerr.Wrap(err)
}
repo := gitiles.NewRepo(c.RepoUrl, client)
return &GitilesRepo{
GitilesRepo: repo,
branch: branch,
deps: c.Dependencies,
defaultBugProject: c.DefaultBugProject,
}, nil
}
// Branch returns the resolved name of the branch tracked by this GitilesRepo.
func (r *GitilesRepo) Branch() string {
return r.branch.String()
}
// GetRevision returns a revision.Revision instance associated with the given
// revision ID, which may be a commit hash or fully-qualified ref name.
func (r *GitilesRepo) GetRevision(ctx context.Context, id string) (*revision.Revision, error) {
// Load the details for this revision.
details, err := r.GitilesRepo.Details(ctx, id)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to retrieve revision %q", id)
}
revLinkTmpl := fmt.Sprintf(gitiles.CommitURL, r.GitilesRepo.URL(), "%s")
rev := revision.FromLongCommit(revLinkTmpl, r.defaultBugProject, details)
// Optionally load any dependencies.
if len(r.deps) > 0 {
deps, err := version_file_common.GetPinnedRevs(ctx, r.deps, func(ctx context.Context, path string) (string, error) {
return r.GetFile(ctx, path, rev.Id)
})
if err != nil {
return nil, skerr.Wrap(err)
}
rev.Dependencies = deps
}
return rev, nil
}
// LogRevisions implements the child.Child interface.
func (r *GitilesRepo) LogRevisions(ctx context.Context, from, to *revision.Revision) ([]*revision.Revision, error) {
hashes, err := r.LogFirstParent(ctx, from.Id, to.Id)
if err != nil {
return nil, skerr.Wrap(err)
}
revs, err := r.ConvertRevisions(ctx, hashes)
if err != nil {
return nil, skerr.Wrap(err)
}
return revs, nil
}
// GetTipRevision returns a revision.Revision instance associated with the
// current tip of the branch tracked by this GitilesRepo.
func (r *GitilesRepo) GetTipRevision(ctx context.Context) (*revision.Revision, error) {
branch := r.branch.String()
sklog.Infof("GetTipRevision for %s, branch %q", r.GitilesRepo.URL(), branch)
return r.GetRevision(ctx, branch)
}
// ConvertRevisions converts the given slice of LongCommits to Revisions.
func (r *GitilesRepo) ConvertRevisions(ctx context.Context, commits []*vcsinfo.LongCommit) ([]*revision.Revision, error) {
revs := make([]*revision.Revision, 0, len(commits))
for _, commit := range commits {
rev, err := r.GetRevision(ctx, commit.Hash)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to retrieve revision")
}
revs = append(revs, rev)
}
return revs, nil
}
// GetFile retrieves the contents of the given file at the given ref.
func (r *GitilesRepo) GetFile(ctx context.Context, file, ref string) (string, error) {
contents, err := r.ReadFileAtRef(ctx, file, ref)
if err != nil {
return "", skerr.Wrap(err)
}
return string(contents), nil
}
// VFS implements the child.Child interface.
func (r *GitilesRepo) VFS(ctx context.Context, rev *revision.Revision) (vfs.FS, error) {
return gitiles_vfs.New(ctx, r.GitilesRepo, rev.Id)
}