blob: dd97f8b85decd7360fd2ae443ed1d7a91bfd6a28 [file] [log] [blame]
package repo_manager
import (
"context"
"errors"
"net/http"
"regexp"
"go.skia.org/infra/autoroll/go/codereview"
"go.skia.org/infra/autoroll/go/config_vars"
"go.skia.org/infra/autoroll/go/repo_manager/child"
"go.skia.org/infra/autoroll/go/repo_manager/common/gitiles_common"
"go.skia.org/infra/autoroll/go/repo_manager/common/version_file_common"
"go.skia.org/infra/autoroll/go/repo_manager/parent"
"go.skia.org/infra/go/depot_tools/deps_parser"
"go.skia.org/infra/go/gerrit"
"go.skia.org/infra/go/skerr"
)
var (
getDepRegex = regexp.MustCompile("[a-f0-9]+")
)
// NoCheckoutDEPSRepoManagerConfig provides configuration for RepoManagers which
// don't use a local checkout.
type NoCheckoutDEPSRepoManagerConfig struct {
NoCheckoutRepoManagerConfig
Gerrit *codereview.GerritConfig `json:"gerrit"`
// URL of the child repo.
ChildRepo string `json:"childRepo"` // TODO(borenet): Can we just get this from DEPS?
// TransitiveDeps is an optional set of dependencies shared by the Parent
// and Child which are updated in the Parent to match the versions of the
// Child.
TransitiveDeps []*version_file_common.TransitiveDepConfig `json:"transitiveDeps"`
}
// See documentation for util.Validator interface.
func (c *NoCheckoutDEPSRepoManagerConfig) Validate() error {
if err := c.NoCheckoutRepoManagerConfig.Validate(); err != nil {
return err
}
if c.ChildRepo == "" {
return errors.New("ChildRepo is required.")
}
if c.ParentBranch == nil {
return errors.New("ParentBranch is required.")
}
if err := c.ParentBranch.Validate(); err != nil {
return err
}
if c.ParentRepo == "" {
return errors.New("ParentRepo is required.")
}
for _, s := range c.PreUploadSteps {
if _, err := parent.GetPreUploadStep(s); err != nil {
return err
}
}
for _, dep := range c.TransitiveDeps {
if err := dep.Child.Validate(); err != nil {
return skerr.Wrapf(err, "invalid TransitiveDeps Child")
}
if err := dep.Parent.Validate(); err != nil {
return skerr.Wrapf(err, "invalid TransitiveDeps Parent")
}
}
_, _, err := c.splitParentChild()
return skerr.Wrap(err)
}
// splitParentChild splits the NoCheckoutDEPSRepoManagerConfig into a
// parent.GitilesConfig and a child.GitilesConfig.
// TODO(borenet): Update the config format to directly define the parent
// and child. We shouldn't need most of the New.*RepoManager functions.
func (c NoCheckoutDEPSRepoManagerConfig) splitParentChild() (parent.GitilesConfig, child.GitilesConfig, error) {
var childDeps []*version_file_common.VersionFileConfig
if c.TransitiveDeps != nil {
childDeps = make([]*version_file_common.VersionFileConfig, 0, len(c.TransitiveDeps))
for _, dep := range c.TransitiveDeps {
childDeps = append(childDeps, dep.Child)
}
}
parentCfg := parent.GitilesConfig{
DependencyConfig: version_file_common.DependencyConfig{
VersionFileConfig: version_file_common.VersionFileConfig{
ID: c.ChildRepo,
Path: deps_parser.DepsFileName,
},
TransitiveDeps: c.TransitiveDeps,
},
GitilesConfig: gitiles_common.GitilesConfig{
Branch: c.NoCheckoutRepoManagerConfig.CommonRepoManagerConfig.ParentBranch,
RepoURL: c.NoCheckoutRepoManagerConfig.CommonRepoManagerConfig.ParentRepo,
},
Gerrit: c.Gerrit,
}
if err := parentCfg.Validate(); err != nil {
return parent.GitilesConfig{}, child.GitilesConfig{}, skerr.Wrapf(err, "generated parent config is invalid")
}
childCfg := child.GitilesConfig{
GitilesConfig: gitiles_common.GitilesConfig{
Branch: c.ChildBranch,
RepoURL: c.ChildRepo,
Dependencies: childDeps,
},
}
if err := childCfg.Validate(); err != nil {
return parent.GitilesConfig{}, child.GitilesConfig{}, skerr.Wrapf(err, "generated child config is invalid")
}
return parentCfg, childCfg, nil
}
// NewNoCheckoutDEPSRepoManager returns a RepoManager instance which does not
// use a local checkout.
func NewNoCheckoutDEPSRepoManager(ctx context.Context, c *NoCheckoutDEPSRepoManagerConfig, reg *config_vars.Registry, workdir string, g gerrit.GerritInterface, recipeCfgFile, serverURL string, client *http.Client, cr codereview.CodeReview, local bool) (*parentChildRepoManager, error) {
if err := c.Validate(); err != nil {
return nil, skerr.Wrap(err)
}
parentCfg, childCfg, err := c.splitParentChild()
if err != nil {
return nil, skerr.Wrap(err)
}
parentRM, err := parent.NewGitilesFile(ctx, parentCfg, reg, client, serverURL)
if err != nil {
return nil, skerr.Wrap(err)
}
childRM, err := child.NewGitiles(ctx, childCfg, reg, client)
if err != nil {
return nil, skerr.Wrap(err)
}
return newParentChildRepoManager(ctx, parentRM, childRM)
}