...

Source file src/github.com/google/go-containerregistry/pkg/name/repository.go

Documentation: github.com/google/go-containerregistry/pkg/name

     1  // Copyright 2018 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package name
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  )
    21  
    22  const (
    23  	defaultNamespace = "library"
    24  	repositoryChars  = "abcdefghijklmnopqrstuvwxyz0123456789_-./"
    25  	regRepoDelimiter = "/"
    26  )
    27  
    28  // Repository stores a docker repository name in a structured form.
    29  type Repository struct {
    30  	Registry
    31  	repository string
    32  }
    33  
    34  // See https://docs.docker.com/docker-hub/official_repos
    35  func hasImplicitNamespace(repo string, reg Registry) bool {
    36  	return !strings.ContainsRune(repo, '/') && reg.RegistryStr() == DefaultRegistry
    37  }
    38  
    39  // RepositoryStr returns the repository component of the Repository.
    40  func (r Repository) RepositoryStr() string {
    41  	if hasImplicitNamespace(r.repository, r.Registry) {
    42  		return fmt.Sprintf("%s/%s", defaultNamespace, r.repository)
    43  	}
    44  	return r.repository
    45  }
    46  
    47  // Name returns the name from which the Repository was derived.
    48  func (r Repository) Name() string {
    49  	regName := r.Registry.Name()
    50  	if regName != "" {
    51  		return regName + regRepoDelimiter + r.RepositoryStr()
    52  	}
    53  	// TODO: As far as I can tell, this is unreachable.
    54  	return r.RepositoryStr()
    55  }
    56  
    57  func (r Repository) String() string {
    58  	return r.Name()
    59  }
    60  
    61  // Scope returns the scope required to perform the given action on the registry.
    62  // TODO(jonjohnsonjr): consider moving scopes to a separate package.
    63  func (r Repository) Scope(action string) string {
    64  	return fmt.Sprintf("repository:%s:%s", r.RepositoryStr(), action)
    65  }
    66  
    67  func checkRepository(repository string) error {
    68  	return checkElement("repository", repository, repositoryChars, 2, 255)
    69  }
    70  
    71  // NewRepository returns a new Repository representing the given name, according to the given strictness.
    72  func NewRepository(name string, opts ...Option) (Repository, error) {
    73  	opt := makeOptions(opts...)
    74  	if len(name) == 0 {
    75  		return Repository{}, newErrBadName("a repository name must be specified")
    76  	}
    77  
    78  	var registry string
    79  	repo := name
    80  	parts := strings.SplitN(name, regRepoDelimiter, 2)
    81  	if len(parts) == 2 && (strings.ContainsRune(parts[0], '.') || strings.ContainsRune(parts[0], ':')) {
    82  		// The first part of the repository is treated as the registry domain
    83  		// iff it contains a '.' or ':' character, otherwise it is all repository
    84  		// and the domain defaults to Docker Hub.
    85  		registry = parts[0]
    86  		repo = parts[1]
    87  	}
    88  
    89  	if err := checkRepository(repo); err != nil {
    90  		return Repository{}, err
    91  	}
    92  
    93  	reg, err := NewRegistry(registry, opts...)
    94  	if err != nil {
    95  		return Repository{}, err
    96  	}
    97  	if hasImplicitNamespace(repo, reg) && opt.strict {
    98  		return Repository{}, newErrBadName("strict validation requires the full repository path (missing 'library')")
    99  	}
   100  	return Repository{reg, repo}, nil
   101  }
   102  
   103  // Tag returns a Tag in this Repository.
   104  func (r Repository) Tag(identifier string) Tag {
   105  	t := Tag{
   106  		tag:        identifier,
   107  		Repository: r,
   108  	}
   109  	t.original = t.Name()
   110  	return t
   111  }
   112  
   113  // Digest returns a Digest in this Repository.
   114  func (r Repository) Digest(identifier string) Digest {
   115  	d := Digest{
   116  		digest:     identifier,
   117  		Repository: r,
   118  	}
   119  	d.original = d.Name()
   120  	return d
   121  }
   122  

View as plain text