@@ -50,14 +50,23 @@ type GitRepository interface {
5050}
5151
5252type GitRepositoryOptions struct {
53- CredentialResolver repository.CredentialResolver
54- UserInfoProvider repository.UserInfoProvider
53+ CredentialResolver repository.CredentialResolver
54+ UserInfoProvider repository.UserInfoProvider
55+ SkipMainBranchVerification bool
5556}
5657
5758func OpenRepository (ctx context.Context , name , namespace string , spec * configapi.GitRepository , root string , opts GitRepositoryOptions ) (GitRepository , error ) {
5859 replace := strings .NewReplacer ("/" , "-" , ":" , "-" )
5960 dir := filepath .Join (root , replace .Replace (spec .Repo ))
6061
62+ // Cleanup the cache directory in case initialization fails.
63+ cleanup := dir
64+ defer func () {
65+ if cleanup != "" {
66+ os .RemoveAll (cleanup )
67+ }
68+ }()
69+
6170 var repo * git.Repository
6271
6372 if fi , err := os .Stat (dir ); err != nil {
@@ -72,9 +81,11 @@ func OpenRepository(ctx context.Context, name, namespace string, spec *configapi
7281
7382 repo = r
7483 } else if ! fi .IsDir () {
75- // Internal error - corrupted cache.
84+ // Internal error - corrupted cache. We will cleanup on the way out.
7685 return nil , fmt .Errorf ("cannot clone git repository %q: %w" , spec .Repo , err )
7786 } else {
87+ cleanup = "" // Existing directory; do not delete it.
88+
7889 r , err := openRepository (dir )
7990 if err != nil {
8091 return nil , err
@@ -90,8 +101,6 @@ func OpenRepository(ctx context.Context, name, namespace string, spec *configapi
90101
91102 branch := MainBranch
92103 if spec .Branch != "" {
93- // TODO: Validate branch name syntax (we can't check whether the branch exists;
94- // the repository may be empty).
95104 branch = BranchName (spec .Branch )
96105 }
97106
@@ -110,6 +119,12 @@ func OpenRepository(ctx context.Context, name, namespace string, spec *configapi
110119 return nil , err
111120 }
112121
122+ if err := repository .verifyRepository (& opts ); err != nil {
123+ return nil , err
124+ }
125+
126+ cleanup = "" // Success. Keep the git directory.
127+
113128 return repository , nil
114129}
115130
@@ -705,6 +720,22 @@ func (r *gitRepository) fetchRemoteRepository(ctx context.Context) error {
705720 return nil
706721}
707722
723+ // Verifies repository. Repository must be fetched already.
724+ func (r * gitRepository ) verifyRepository (opts * GitRepositoryOptions ) error {
725+ // When opening a temporary repository, such as for cloning a package
726+ // from unregistered upstream, we won't be pushing into the remote so
727+ // we don't need to verify presence of the main branch.
728+ if ! opts .SkipMainBranchVerification {
729+ // Check existence of main branch. If it doesn't exist, fail.
730+ // If the main branch doesn't exist, we could create draft or proposal branch
731+ // which could become the default branch and those are hard to delete.
732+ if _ , err := r .repo .Reference (r .branch .RefInLocal (), false ); err != nil {
733+ return fmt .Errorf ("branch %q doesn't exist: %v" , r .branch , err )
734+ }
735+ }
736+ return nil
737+ }
738+
708739// Creates a commit which deletes the package from the branch, and returns its commit hash.
709740// If the branch doesn't exist, will return zero hash and no error.
710741func (r * gitRepository ) createPackageDeleteCommit (ctx context.Context , branch plumbing.ReferenceName , pkg * gitPackageRevision ) (plumbing.Hash , error ) {
0 commit comments