Merge pull request #9034 from thaJeztah/replace_reference
replace reference/docker for github.com/distribution/reference v0.5.0
This commit is contained in:
		
							
								
								
									
										1
									
								
								vendor/github.com/distribution/reference/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/distribution/reference/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
*.go text eol=lf
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/distribution/reference/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/distribution/reference/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
# Cover profiles
 | 
			
		||||
*.out
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/distribution/reference/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/distribution/reference/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
linters:
 | 
			
		||||
  enable:
 | 
			
		||||
    - bodyclose
 | 
			
		||||
    - dupword # Checks for duplicate words in the source code
 | 
			
		||||
    - gofmt
 | 
			
		||||
    - goimports
 | 
			
		||||
    - ineffassign
 | 
			
		||||
    - misspell
 | 
			
		||||
    - revive
 | 
			
		||||
    - staticcheck
 | 
			
		||||
    - unconvert
 | 
			
		||||
    - unused
 | 
			
		||||
    - vet
 | 
			
		||||
  disable:
 | 
			
		||||
    - errcheck
 | 
			
		||||
 | 
			
		||||
run:
 | 
			
		||||
  deadline: 2m
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/distribution/reference/CODE-OF-CONDUCT.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/distribution/reference/CODE-OF-CONDUCT.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# Code of Conduct
 | 
			
		||||
 | 
			
		||||
We follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
 | 
			
		||||
 | 
			
		||||
Please contact the [CNCF Code of Conduct Committee](mailto:conduct@cncf.io) in order to report violations of the Code of Conduct.
 | 
			
		||||
							
								
								
									
										114
									
								
								vendor/github.com/distribution/reference/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								vendor/github.com/distribution/reference/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
# Contributing to the reference library
 | 
			
		||||
 | 
			
		||||
## Community help
 | 
			
		||||
 | 
			
		||||
If you need help, please ask in the [#distribution](https://cloud-native.slack.com/archives/C01GVR8SY4R) channel on CNCF community slack.
 | 
			
		||||
[Click here for an invite to the CNCF community slack](https://slack.cncf.io/)
 | 
			
		||||
 | 
			
		||||
## Reporting security issues
 | 
			
		||||
 | 
			
		||||
The maintainers take security seriously. If you discover a security
 | 
			
		||||
issue, please bring it to their attention right away!
 | 
			
		||||
 | 
			
		||||
Please **DO NOT** file a public issue, instead send your report privately to
 | 
			
		||||
[cncf-distribution-security@lists.cncf.io](mailto:cncf-distribution-security@lists.cncf.io).
 | 
			
		||||
 | 
			
		||||
## Reporting an issue properly
 | 
			
		||||
 | 
			
		||||
By following these simple rules you will get better and faster feedback on your issue.
 | 
			
		||||
 | 
			
		||||
 - search the bugtracker for an already reported issue
 | 
			
		||||
 | 
			
		||||
### If you found an issue that describes your problem:
 | 
			
		||||
 | 
			
		||||
 - please read other user comments first, and confirm this is the same issue: a given error condition might be indicative of different problems - you may also find a workaround in the comments
 | 
			
		||||
 - please refrain from adding "same thing here" or "+1" comments
 | 
			
		||||
 - you don't need to comment on an issue to get notified of updates: just hit the "subscribe" button
 | 
			
		||||
 - comment if you have some new, technical and relevant information to add to the case
 | 
			
		||||
 - __DO NOT__ comment on closed issues or merged PRs. If you think you have a related problem, open up a new issue and reference the PR or issue.
 | 
			
		||||
 | 
			
		||||
### If you have not found an existing issue that describes your problem:
 | 
			
		||||
 | 
			
		||||
 1. create a new issue, with a succinct title that describes your issue:
 | 
			
		||||
   - bad title: "It doesn't work with my docker"
 | 
			
		||||
   - good title: "Private registry push fail: 400 error with E_INVALID_DIGEST"
 | 
			
		||||
 2. copy the output of (or similar for other container tools):
 | 
			
		||||
   - `docker version`
 | 
			
		||||
   - `docker info`
 | 
			
		||||
   - `docker exec <registry-container> registry --version`
 | 
			
		||||
 3. copy the command line you used to launch your Registry
 | 
			
		||||
 4. restart your docker daemon in debug mode (add `-D` to the daemon launch arguments)
 | 
			
		||||
 5. reproduce your problem and get your docker daemon logs showing the error
 | 
			
		||||
 6. if relevant, copy your registry logs that show the error
 | 
			
		||||
 7. provide any relevant detail about your specific Registry configuration (e.g., storage backend used)
 | 
			
		||||
 8. indicate if you are using an enterprise proxy, Nginx, or anything else between you and your Registry
 | 
			
		||||
 | 
			
		||||
## Contributing Code
 | 
			
		||||
 | 
			
		||||
Contributions should be made via pull requests. Pull requests will be reviewed
 | 
			
		||||
by one or more maintainers or reviewers and merged when acceptable.
 | 
			
		||||
 | 
			
		||||
You should follow the basic GitHub workflow:
 | 
			
		||||
 | 
			
		||||
 1. Use your own [fork](https://help.github.com/en/articles/about-forks)
 | 
			
		||||
 2. Create your [change](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#successful-changes)
 | 
			
		||||
 3. Test your code
 | 
			
		||||
 4. [Commit](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#commit-messages) your work, always [sign your commits](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#commit-messages)
 | 
			
		||||
 5. Push your change to your fork and create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork)
 | 
			
		||||
 | 
			
		||||
Refer to [containerd's contribution guide](https://github.com/containerd/project/blob/master/CONTRIBUTING.md#successful-changes)
 | 
			
		||||
for tips on creating a successful contribution.
 | 
			
		||||
 | 
			
		||||
## Sign your work
 | 
			
		||||
 | 
			
		||||
The sign-off is a simple line at the end of the explanation for the patch. Your
 | 
			
		||||
signature certifies that you wrote the patch or otherwise have the right to pass
 | 
			
		||||
it on as an open-source patch. The rules are pretty simple: if you can certify
 | 
			
		||||
the below (from [developercertificate.org](http://developercertificate.org/)):
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
Developer Certificate of Origin
 | 
			
		||||
Version 1.1
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
 | 
			
		||||
660 York Street, Suite 102,
 | 
			
		||||
San Francisco, CA 94110 USA
 | 
			
		||||
 | 
			
		||||
Everyone is permitted to copy and distribute verbatim copies of this
 | 
			
		||||
license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
Developer's Certificate of Origin 1.1
 | 
			
		||||
 | 
			
		||||
By making a contribution to this project, I certify that:
 | 
			
		||||
 | 
			
		||||
(a) The contribution was created in whole or in part by me and I
 | 
			
		||||
    have the right to submit it under the open source license
 | 
			
		||||
    indicated in the file; or
 | 
			
		||||
 | 
			
		||||
(b) The contribution is based upon previous work that, to the best
 | 
			
		||||
    of my knowledge, is covered under an appropriate open source
 | 
			
		||||
    license and I have the right under that license to submit that
 | 
			
		||||
    work with modifications, whether created in whole or in part
 | 
			
		||||
    by me, under the same open source license (unless I am
 | 
			
		||||
    permitted to submit under a different license), as indicated
 | 
			
		||||
    in the file; or
 | 
			
		||||
 | 
			
		||||
(c) The contribution was provided directly to me by some other
 | 
			
		||||
    person who certified (a), (b) or (c) and I have not modified
 | 
			
		||||
    it.
 | 
			
		||||
 | 
			
		||||
(d) I understand and agree that this project and the contribution
 | 
			
		||||
    are public and that a record of the contribution (including all
 | 
			
		||||
    personal information I submit with it, including my sign-off) is
 | 
			
		||||
    maintained indefinitely and may be redistributed consistent with
 | 
			
		||||
    this project or the open source license(s) involved.
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then you just add a line to every git commit message:
 | 
			
		||||
 | 
			
		||||
    Signed-off-by: Joe Smith <joe.smith@email.com>
 | 
			
		||||
 | 
			
		||||
Use your real name (sorry, no pseudonyms or anonymous contributions.)
 | 
			
		||||
 | 
			
		||||
If you set your `user.name` and `user.email` git configs, you can sign your
 | 
			
		||||
commit automatically with `git commit -s`.
 | 
			
		||||
							
								
								
									
										144
									
								
								vendor/github.com/distribution/reference/GOVERNANCE.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/distribution/reference/GOVERNANCE.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
# distribution/reference Project Governance
 | 
			
		||||
 | 
			
		||||
Distribution [Code of Conduct](./CODE-OF-CONDUCT.md) can be found here.
 | 
			
		||||
 | 
			
		||||
For specific guidance on practical contribution steps please
 | 
			
		||||
see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide.
 | 
			
		||||
 | 
			
		||||
## Maintainership
 | 
			
		||||
 | 
			
		||||
There are different types of maintainers, with different responsibilities, but
 | 
			
		||||
all maintainers have 3 things in common:
 | 
			
		||||
 | 
			
		||||
1) They share responsibility in the project's success.
 | 
			
		||||
2) They have made a long-term, recurring time investment to improve the project.
 | 
			
		||||
3) They spend that time doing whatever needs to be done, not necessarily what
 | 
			
		||||
is the most interesting or fun.
 | 
			
		||||
 | 
			
		||||
Maintainers are often under-appreciated, because their work is harder to appreciate.
 | 
			
		||||
It's easy to appreciate a really cool and technically advanced feature. It's harder
 | 
			
		||||
to appreciate the absence of bugs, the slow but steady improvement in stability,
 | 
			
		||||
or the reliability of a release process. But those things distinguish a good
 | 
			
		||||
project from a great one.
 | 
			
		||||
 | 
			
		||||
## Reviewers
 | 
			
		||||
 | 
			
		||||
A reviewer is a core role within the project.
 | 
			
		||||
They share in reviewing issues and pull requests and their LGTM counts towards the
 | 
			
		||||
required LGTM count to merge a code change into the project.
 | 
			
		||||
 | 
			
		||||
Reviewers are part of the organization but do not have write access.
 | 
			
		||||
Becoming a reviewer is a core aspect in the journey to becoming a maintainer.
 | 
			
		||||
 | 
			
		||||
## Adding maintainers
 | 
			
		||||
 | 
			
		||||
Maintainers are first and foremost contributors that have shown they are
 | 
			
		||||
committed to the long term success of a project. Contributors wanting to become
 | 
			
		||||
maintainers are expected to be deeply involved in contributing code, pull
 | 
			
		||||
request review, and triage of issues in the project for more than three months.
 | 
			
		||||
 | 
			
		||||
Just contributing does not make you a maintainer, it is about building trust
 | 
			
		||||
with the current maintainers of the project and being a person that they can
 | 
			
		||||
depend on and trust to make decisions in the best interest of the project.
 | 
			
		||||
 | 
			
		||||
Periodically, the existing maintainers curate a list of contributors that have
 | 
			
		||||
shown regular activity on the project over the prior months. From this list,
 | 
			
		||||
maintainer candidates are selected and proposed in a pull request or a
 | 
			
		||||
maintainers communication channel.
 | 
			
		||||
 | 
			
		||||
After a candidate has been announced to the maintainers, the existing
 | 
			
		||||
maintainers are given five business days to discuss the candidate, raise
 | 
			
		||||
objections and cast their vote. Votes may take place on the communication
 | 
			
		||||
channel or via pull request comment. Candidates must be approved by at least 66%
 | 
			
		||||
of the current maintainers by adding their vote on the mailing list. The
 | 
			
		||||
reviewer role has the same process but only requires 33% of current maintainers.
 | 
			
		||||
Only maintainers of the repository that the candidate is proposed for are
 | 
			
		||||
allowed to vote.
 | 
			
		||||
 | 
			
		||||
If a candidate is approved, a maintainer will contact the candidate to invite
 | 
			
		||||
the candidate to open a pull request that adds the contributor to the
 | 
			
		||||
MAINTAINERS file. The voting process may take place inside a pull request if a
 | 
			
		||||
maintainer has already discussed the candidacy with the candidate and a
 | 
			
		||||
maintainer is willing to be a sponsor by opening the pull request. The candidate
 | 
			
		||||
becomes a maintainer once the pull request is merged.
 | 
			
		||||
 | 
			
		||||
## Stepping down policy
 | 
			
		||||
 | 
			
		||||
Life priorities, interests, and passions can change. If you're a maintainer but
 | 
			
		||||
feel you must remove yourself from the list, inform other maintainers that you
 | 
			
		||||
intend to step down, and if possible, help find someone to pick up your work.
 | 
			
		||||
At the very least, ensure your work can be continued where you left off.
 | 
			
		||||
 | 
			
		||||
After you've informed other maintainers, create a pull request to remove
 | 
			
		||||
yourself from the MAINTAINERS file.
 | 
			
		||||
 | 
			
		||||
## Removal of inactive maintainers
 | 
			
		||||
 | 
			
		||||
Similar to the procedure for adding new maintainers, existing maintainers can
 | 
			
		||||
be removed from the list if they do not show significant activity on the
 | 
			
		||||
project. Periodically, the maintainers review the list of maintainers and their
 | 
			
		||||
activity over the last three months.
 | 
			
		||||
 | 
			
		||||
If a maintainer has shown insufficient activity over this period, a neutral
 | 
			
		||||
person will contact the maintainer to ask if they want to continue being
 | 
			
		||||
a maintainer. If the maintainer decides to step down as a maintainer, they
 | 
			
		||||
open a pull request to be removed from the MAINTAINERS file.
 | 
			
		||||
 | 
			
		||||
If the maintainer wants to remain a maintainer, but is unable to perform the
 | 
			
		||||
required duties they can be removed with a vote of at least 66% of the current
 | 
			
		||||
maintainers. In this case, maintainers should first propose the change to
 | 
			
		||||
maintainers via the maintainers communication channel, then open a pull request
 | 
			
		||||
for voting. The voting period is five business days. The voting pull request
 | 
			
		||||
should not come as a surpise to any maintainer and any discussion related to
 | 
			
		||||
performance must not be discussed on the pull request.
 | 
			
		||||
 | 
			
		||||
## How are decisions made?
 | 
			
		||||
 | 
			
		||||
Docker distribution is an open-source project with an open design philosophy.
 | 
			
		||||
This means that the repository is the source of truth for EVERY aspect of the
 | 
			
		||||
project, including its philosophy, design, road map, and APIs. *If it's part of
 | 
			
		||||
the project, it's in the repo. If it's in the repo, it's part of the project.*
 | 
			
		||||
 | 
			
		||||
As a result, all decisions can be expressed as changes to the repository. An
 | 
			
		||||
implementation change is a change to the source code. An API change is a change
 | 
			
		||||
to the API specification. A philosophy change is a change to the philosophy
 | 
			
		||||
manifesto, and so on.
 | 
			
		||||
 | 
			
		||||
All decisions affecting distribution, big and small, follow the same 3 steps:
 | 
			
		||||
 | 
			
		||||
* Step 1: Open a pull request. Anyone can do this.
 | 
			
		||||
 | 
			
		||||
* Step 2: Discuss the pull request. Anyone can do this.
 | 
			
		||||
 | 
			
		||||
* Step 3: Merge or refuse the pull request. Who does this depends on the nature
 | 
			
		||||
of the pull request and which areas of the project it affects.
 | 
			
		||||
 | 
			
		||||
## Helping contributors with the DCO
 | 
			
		||||
 | 
			
		||||
The [DCO or `Sign your work`](./CONTRIBUTING.md#sign-your-work)
 | 
			
		||||
requirement is not intended as a roadblock or speed bump.
 | 
			
		||||
 | 
			
		||||
Some contributors are not as familiar with `git`, or have used a web
 | 
			
		||||
based editor, and thus asking them to `git commit --amend -s` is not the best
 | 
			
		||||
way forward.
 | 
			
		||||
 | 
			
		||||
In this case, maintainers can update the commits based on clause (c) of the DCO.
 | 
			
		||||
The most trivial way for a contributor to allow the maintainer to do this, is to
 | 
			
		||||
add a DCO signature in a pull requests's comment, or a maintainer can simply
 | 
			
		||||
note that the change is sufficiently trivial that it does not substantially
 | 
			
		||||
change the existing contribution - i.e., a spelling change.
 | 
			
		||||
 | 
			
		||||
When you add someone's DCO, please also add your own to keep a log.
 | 
			
		||||
 | 
			
		||||
## I'm a maintainer. Should I make pull requests too?
 | 
			
		||||
 | 
			
		||||
Yes. Nobody should ever push to master directly. All changes should be
 | 
			
		||||
made through a pull request.
 | 
			
		||||
 | 
			
		||||
## Conflict Resolution
 | 
			
		||||
 | 
			
		||||
If you have a technical dispute that you feel has reached an impasse with a
 | 
			
		||||
subset of the community, any contributor may open an issue, specifically
 | 
			
		||||
calling for a resolution vote of the current core maintainers to resolve the
 | 
			
		||||
dispute. The same voting quorums required (2/3) for adding and removing
 | 
			
		||||
maintainers will apply to conflict resolution.
 | 
			
		||||
							
								
								
									
										202
									
								
								vendor/github.com/distribution/reference/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								vendor/github.com/distribution/reference/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   APPENDIX: How to apply the Apache License to your work.
 | 
			
		||||
 | 
			
		||||
      To apply the Apache License to your work, attach the following
 | 
			
		||||
      boilerplate notice, with the fields enclosed by brackets "{}"
 | 
			
		||||
      replaced with your own identifying information. (Don't include
 | 
			
		||||
      the brackets!)  The text should be enclosed in the appropriate
 | 
			
		||||
      comment syntax for the file format. We also recommend that a
 | 
			
		||||
      file or class name and description of purpose be included on the
 | 
			
		||||
      same "printed page" as the copyright notice for easier
 | 
			
		||||
      identification within third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright {yyyy} {name of copyright owner}
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/distribution/reference/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/distribution/reference/MAINTAINERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
# Distribution project maintainers & reviewers
 | 
			
		||||
#
 | 
			
		||||
# See GOVERNANCE.md for maintainer versus reviewer roles
 | 
			
		||||
#
 | 
			
		||||
# MAINTAINERS (cncf-distribution-maintainers@lists.cncf.io)
 | 
			
		||||
# GitHub ID, Name, Email address
 | 
			
		||||
"chrispat","Chris Patterson","chrispat@github.com"
 | 
			
		||||
"clarkbw","Bryan Clark","clarkbw@github.com"
 | 
			
		||||
"corhere","Cory Snider","csnider@mirantis.com"
 | 
			
		||||
"deleteriousEffect","Hayley Swimelar","hswimelar@gitlab.com"
 | 
			
		||||
"heww","He Weiwei","hweiwei@vmware.com"
 | 
			
		||||
"joaodrp","João Pereira","jpereira@gitlab.com"
 | 
			
		||||
"justincormack","Justin Cormack","justin.cormack@docker.com"
 | 
			
		||||
"squizzi","Kyle Squizzato","ksquizzato@mirantis.com"
 | 
			
		||||
"milosgajdos","Milos Gajdos","milosthegajdos@gmail.com"
 | 
			
		||||
"sargun","Sargun Dhillon","sargun@sargun.me"
 | 
			
		||||
"wy65701436","Wang Yan","wangyan@vmware.com"
 | 
			
		||||
"stevelasker","Steve Lasker","steve.lasker@microsoft.com"
 | 
			
		||||
#
 | 
			
		||||
# REVIEWERS
 | 
			
		||||
# GitHub ID, Name, Email address
 | 
			
		||||
"dmcgowan","Derek McGowan","derek@mcgstyle.net"
 | 
			
		||||
"stevvooe","Stephen Day","stevvooe@gmail.com"
 | 
			
		||||
"thajeztah","Sebastiaan van Stijn","github@gone.nl"
 | 
			
		||||
"DavidSpek", "David van der Spek", "vanderspek.david@gmail.com"
 | 
			
		||||
"Jamstah", "James Hewitt", "james.hewitt@gmail.com"
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/distribution/reference/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/distribution/reference/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
# Project packages.
 | 
			
		||||
PACKAGES=$(shell go list ./...)
 | 
			
		||||
 | 
			
		||||
# Flags passed to `go test`
 | 
			
		||||
BUILDFLAGS ?= 
 | 
			
		||||
TESTFLAGS ?= 
 | 
			
		||||
 | 
			
		||||
.PHONY: all build test coverage
 | 
			
		||||
.DEFAULT: all
 | 
			
		||||
 | 
			
		||||
all: build
 | 
			
		||||
 | 
			
		||||
build: ## no binaries to build, so just check compilation suceeds
 | 
			
		||||
	go build ${BUILDFLAGS} ./...
 | 
			
		||||
 | 
			
		||||
test: ## run tests
 | 
			
		||||
	go test ${TESTFLAGS} ./...
 | 
			
		||||
 | 
			
		||||
coverage: ## generate coverprofiles from the unit tests
 | 
			
		||||
	rm -f coverage.txt
 | 
			
		||||
	go test ${TESTFLAGS} -cover -coverprofile=cover.out ./...
 | 
			
		||||
 | 
			
		||||
.PHONY: help
 | 
			
		||||
help:
 | 
			
		||||
	@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n  make \033[36m\033[0m\n"} /^[a-zA-Z_\/%-]+:.*?##/ { printf "  \033[36m%-27s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/distribution/reference/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/distribution/reference/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
# Distribution reference
 | 
			
		||||
 | 
			
		||||
Go library to handle references to container images.
 | 
			
		||||
 | 
			
		||||
<img src="/distribution-logo.svg" width="200px" />
 | 
			
		||||
 | 
			
		||||
[](https://github.com/distribution/reference/actions?query=workflow%3ACI)
 | 
			
		||||
[](https://pkg.go.dev/github.com/distribution/reference)
 | 
			
		||||
[](LICENSE)
 | 
			
		||||
[](https://codecov.io/gh/distribution/reference)
 | 
			
		||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fdistribution%2Freference?ref=badge_shield)
 | 
			
		||||
 | 
			
		||||
This repository contains a library for handling refrences to container images held in container registries. Please see [godoc](https://pkg.go.dev/github.com/distribution/reference) for details.
 | 
			
		||||
 | 
			
		||||
## Contribution
 | 
			
		||||
 | 
			
		||||
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute
 | 
			
		||||
issues, fixes, and patches to this project.
 | 
			
		||||
 | 
			
		||||
## Communication
 | 
			
		||||
 | 
			
		||||
For async communication and long running discussions please use issues and pull requests on the github repo.
 | 
			
		||||
This will be the best place to discuss design and implementation.
 | 
			
		||||
 | 
			
		||||
For sync communication we have a #distribution channel in the [CNCF Slack](https://slack.cncf.io/)
 | 
			
		||||
that everyone is welcome to join and chat about development.
 | 
			
		||||
 | 
			
		||||
## Licenses
 | 
			
		||||
 | 
			
		||||
The distribution codebase is released under the [Apache 2.0 license](LICENSE).
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/distribution/reference/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/distribution/reference/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# Security Policy
 | 
			
		||||
 | 
			
		||||
## Reporting a Vulnerability
 | 
			
		||||
 | 
			
		||||
The maintainers take security seriously. If you discover a security issue, please bring it to their attention right away!
 | 
			
		||||
 | 
			
		||||
Please DO NOT file a public issue, instead send your report privately to cncf-distribution-security@lists.cncf.io.
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/distribution/reference/distribution-logo.svg
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/distribution/reference/distribution-logo.svg
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
		 After Width: | Height: | Size: 8.6 KiB  | 
							
								
								
									
										42
									
								
								vendor/github.com/distribution/reference/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/distribution/reference/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package reference
 | 
			
		||||
 | 
			
		||||
import "path"
 | 
			
		||||
 | 
			
		||||
// IsNameOnly returns true if reference only contains a repo name.
 | 
			
		||||
func IsNameOnly(ref Named) bool {
 | 
			
		||||
	if _, ok := ref.(NamedTagged); ok {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := ref.(Canonical); ok {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FamiliarName returns the familiar name string
 | 
			
		||||
// for the given named, familiarizing if needed.
 | 
			
		||||
func FamiliarName(ref Named) string {
 | 
			
		||||
	if nn, ok := ref.(normalizedNamed); ok {
 | 
			
		||||
		return nn.Familiar().Name()
 | 
			
		||||
	}
 | 
			
		||||
	return ref.Name()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FamiliarString returns the familiar string representation
 | 
			
		||||
// for the given reference, familiarizing if needed.
 | 
			
		||||
func FamiliarString(ref Reference) string {
 | 
			
		||||
	if nn, ok := ref.(normalizedNamed); ok {
 | 
			
		||||
		return nn.Familiar().String()
 | 
			
		||||
	}
 | 
			
		||||
	return ref.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FamiliarMatch reports whether ref matches the specified pattern.
 | 
			
		||||
// See [path.Match] for supported patterns.
 | 
			
		||||
func FamiliarMatch(pattern string, ref Reference) (bool, error) {
 | 
			
		||||
	matched, err := path.Match(pattern, FamiliarString(ref))
 | 
			
		||||
	if namedRef, isNamed := ref.(Named); isNamed && !matched {
 | 
			
		||||
		matched, _ = path.Match(pattern, FamiliarName(namedRef))
 | 
			
		||||
	}
 | 
			
		||||
	return matched, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										224
									
								
								vendor/github.com/distribution/reference/normalize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								vendor/github.com/distribution/reference/normalize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,224 @@
 | 
			
		||||
package reference
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/opencontainers/go-digest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// legacyDefaultDomain is the legacy domain for Docker Hub (which was
 | 
			
		||||
	// originally named "the Docker Index"). This domain is still used for
 | 
			
		||||
	// authentication and image search, which were part of the "v1" Docker
 | 
			
		||||
	// registry specification.
 | 
			
		||||
	//
 | 
			
		||||
	// This domain will continue to be supported, but there are plans to consolidate
 | 
			
		||||
	// legacy domains to new "canonical" domains. Once those domains are decided
 | 
			
		||||
	// on, we must update the normalization functions, but preserve compatibility
 | 
			
		||||
	// with existing installs, clients, and user configuration.
 | 
			
		||||
	legacyDefaultDomain = "index.docker.io"
 | 
			
		||||
 | 
			
		||||
	// defaultDomain is the default domain used for images on Docker Hub.
 | 
			
		||||
	// It is used to normalize "familiar" names to canonical names, for example,
 | 
			
		||||
	// to convert "ubuntu" to "docker.io/library/ubuntu:latest".
 | 
			
		||||
	//
 | 
			
		||||
	// Note that actual domain of Docker Hub's registry is registry-1.docker.io.
 | 
			
		||||
	// This domain will continue to be supported, but there are plans to consolidate
 | 
			
		||||
	// legacy domains to new "canonical" domains. Once those domains are decided
 | 
			
		||||
	// on, we must update the normalization functions, but preserve compatibility
 | 
			
		||||
	// with existing installs, clients, and user configuration.
 | 
			
		||||
	defaultDomain = "docker.io"
 | 
			
		||||
 | 
			
		||||
	// officialRepoPrefix is the namespace used for official images on Docker Hub.
 | 
			
		||||
	// It is used to normalize "familiar" names to canonical names, for example,
 | 
			
		||||
	// to convert "ubuntu" to "docker.io/library/ubuntu:latest".
 | 
			
		||||
	officialRepoPrefix = "library/"
 | 
			
		||||
 | 
			
		||||
	// defaultTag is the default tag if no tag is provided.
 | 
			
		||||
	defaultTag = "latest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// normalizedNamed represents a name which has been
 | 
			
		||||
// normalized and has a familiar form. A familiar name
 | 
			
		||||
// is what is used in Docker UI. An example normalized
 | 
			
		||||
// name is "docker.io/library/ubuntu" and corresponding
 | 
			
		||||
// familiar name of "ubuntu".
 | 
			
		||||
type normalizedNamed interface {
 | 
			
		||||
	Named
 | 
			
		||||
	Familiar() Named
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseNormalizedNamed parses a string into a named reference
 | 
			
		||||
// transforming a familiar name from Docker UI to a fully
 | 
			
		||||
// qualified reference. If the value may be an identifier
 | 
			
		||||
// use ParseAnyReference.
 | 
			
		||||
func ParseNormalizedNamed(s string) (Named, error) {
 | 
			
		||||
	if ok := anchoredIdentifierRegexp.MatchString(s); ok {
 | 
			
		||||
		return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s)
 | 
			
		||||
	}
 | 
			
		||||
	domain, remainder := splitDockerDomain(s)
 | 
			
		||||
	var remote string
 | 
			
		||||
	if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 {
 | 
			
		||||
		remote = remainder[:tagSep]
 | 
			
		||||
	} else {
 | 
			
		||||
		remote = remainder
 | 
			
		||||
	}
 | 
			
		||||
	if strings.ToLower(remote) != remote {
 | 
			
		||||
		return nil, fmt.Errorf("invalid reference format: repository name (%s) must be lowercase", remote)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ref, err := Parse(domain + "/" + remainder)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	named, isNamed := ref.(Named)
 | 
			
		||||
	if !isNamed {
 | 
			
		||||
		return nil, fmt.Errorf("reference %s has no name", ref.String())
 | 
			
		||||
	}
 | 
			
		||||
	return named, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// namedTaggedDigested is a reference that has both a tag and a digest.
 | 
			
		||||
type namedTaggedDigested interface {
 | 
			
		||||
	NamedTagged
 | 
			
		||||
	Digested
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDockerRef normalizes the image reference following the docker convention,
 | 
			
		||||
// which allows for references to contain both a tag and a digest. It returns a
 | 
			
		||||
// reference that is either tagged or digested. For references containing both
 | 
			
		||||
// a tag and a digest, it returns a digested reference. For example, the following
 | 
			
		||||
// reference:
 | 
			
		||||
//
 | 
			
		||||
//	docker.io/library/busybox:latest@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa
 | 
			
		||||
//
 | 
			
		||||
// Is returned as a digested reference (with the ":latest" tag removed):
 | 
			
		||||
//
 | 
			
		||||
//	docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa
 | 
			
		||||
//
 | 
			
		||||
// References that are already "tagged" or "digested" are returned unmodified:
 | 
			
		||||
//
 | 
			
		||||
//	// Already a digested reference
 | 
			
		||||
//	docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa
 | 
			
		||||
//
 | 
			
		||||
//	// Already a named reference
 | 
			
		||||
//	docker.io/library/busybox:latest
 | 
			
		||||
func ParseDockerRef(ref string) (Named, error) {
 | 
			
		||||
	named, err := ParseNormalizedNamed(ref)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if canonical, ok := named.(namedTaggedDigested); ok {
 | 
			
		||||
		// The reference is both tagged and digested; only return digested.
 | 
			
		||||
		newNamed, err := WithName(canonical.Name())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return WithDigest(newNamed, canonical.Digest())
 | 
			
		||||
	}
 | 
			
		||||
	return TagNameOnly(named), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// splitDockerDomain splits a repository name to domain and remote-name.
 | 
			
		||||
// If no valid domain is found, the default domain is used. Repository name
 | 
			
		||||
// needs to be already validated before.
 | 
			
		||||
func splitDockerDomain(name string) (domain, remainder string) {
 | 
			
		||||
	i := strings.IndexRune(name, '/')
 | 
			
		||||
	if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != localhost && strings.ToLower(name[:i]) == name[:i]) {
 | 
			
		||||
		domain, remainder = defaultDomain, name
 | 
			
		||||
	} else {
 | 
			
		||||
		domain, remainder = name[:i], name[i+1:]
 | 
			
		||||
	}
 | 
			
		||||
	if domain == legacyDefaultDomain {
 | 
			
		||||
		domain = defaultDomain
 | 
			
		||||
	}
 | 
			
		||||
	if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {
 | 
			
		||||
		remainder = officialRepoPrefix + remainder
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// familiarizeName returns a shortened version of the name familiar
 | 
			
		||||
// to the Docker UI. Familiar names have the default domain
 | 
			
		||||
// "docker.io" and "library/" repository prefix removed.
 | 
			
		||||
// For example, "docker.io/library/redis" will have the familiar
 | 
			
		||||
// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp".
 | 
			
		||||
// Returns a familiarized named only reference.
 | 
			
		||||
func familiarizeName(named namedRepository) repository {
 | 
			
		||||
	repo := repository{
 | 
			
		||||
		domain: named.Domain(),
 | 
			
		||||
		path:   named.Path(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if repo.domain == defaultDomain {
 | 
			
		||||
		repo.domain = ""
 | 
			
		||||
		// Handle official repositories which have the pattern "library/<official repo name>"
 | 
			
		||||
		if strings.HasPrefix(repo.path, officialRepoPrefix) {
 | 
			
		||||
			// TODO(thaJeztah): this check may be too strict, as it assumes the
 | 
			
		||||
			//  "library/" namespace does not have nested namespaces. While this
 | 
			
		||||
			//  is true (currently), technically it would be possible for Docker
 | 
			
		||||
			//  Hub to use those (e.g. "library/distros/ubuntu:latest").
 | 
			
		||||
			//  See https://github.com/distribution/distribution/pull/3769#issuecomment-1302031785.
 | 
			
		||||
			if remainder := strings.TrimPrefix(repo.path, officialRepoPrefix); !strings.ContainsRune(remainder, '/') {
 | 
			
		||||
				repo.path = remainder
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return repo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r reference) Familiar() Named {
 | 
			
		||||
	return reference{
 | 
			
		||||
		namedRepository: familiarizeName(r.namedRepository),
 | 
			
		||||
		tag:             r.tag,
 | 
			
		||||
		digest:          r.digest,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r repository) Familiar() Named {
 | 
			
		||||
	return familiarizeName(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t taggedReference) Familiar() Named {
 | 
			
		||||
	return taggedReference{
 | 
			
		||||
		namedRepository: familiarizeName(t.namedRepository),
 | 
			
		||||
		tag:             t.tag,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c canonicalReference) Familiar() Named {
 | 
			
		||||
	return canonicalReference{
 | 
			
		||||
		namedRepository: familiarizeName(c.namedRepository),
 | 
			
		||||
		digest:          c.digest,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TagNameOnly adds the default tag "latest" to a reference if it only has
 | 
			
		||||
// a repo name.
 | 
			
		||||
func TagNameOnly(ref Named) Named {
 | 
			
		||||
	if IsNameOnly(ref) {
 | 
			
		||||
		namedTagged, err := WithTag(ref, defaultTag)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// Default tag must be valid, to create a NamedTagged
 | 
			
		||||
			// type with non-validated input the WithTag function
 | 
			
		||||
			// should be used instead
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		return namedTagged
 | 
			
		||||
	}
 | 
			
		||||
	return ref
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseAnyReference parses a reference string as a possible identifier,
 | 
			
		||||
// full digest, or familiar name.
 | 
			
		||||
func ParseAnyReference(ref string) (Reference, error) {
 | 
			
		||||
	if ok := anchoredIdentifierRegexp.MatchString(ref); ok {
 | 
			
		||||
		return digestReference("sha256:" + ref), nil
 | 
			
		||||
	}
 | 
			
		||||
	if dgst, err := digest.Parse(ref); err == nil {
 | 
			
		||||
		return digestReference(dgst), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ParseNormalizedNamed(ref)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										436
									
								
								vendor/github.com/distribution/reference/reference.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										436
									
								
								vendor/github.com/distribution/reference/reference.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,436 @@
 | 
			
		||||
// Package reference provides a general type to represent any way of referencing images within the registry.
 | 
			
		||||
// Its main purpose is to abstract tags and digests (content-addressable hash).
 | 
			
		||||
//
 | 
			
		||||
// Grammar
 | 
			
		||||
//
 | 
			
		||||
//	reference                       := name [ ":" tag ] [ "@" digest ]
 | 
			
		||||
//	name                            := [domain '/'] remote-name
 | 
			
		||||
//	domain                          := host [':' port-number]
 | 
			
		||||
//	host                            := domain-name | IPv4address | \[ IPv6address \]	; rfc3986 appendix-A
 | 
			
		||||
//	domain-name                     := domain-component ['.' domain-component]*
 | 
			
		||||
//	domain-component                := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
 | 
			
		||||
//	port-number                     := /[0-9]+/
 | 
			
		||||
//	path-component                  := alpha-numeric [separator alpha-numeric]*
 | 
			
		||||
//	path (or "remote-name")         := path-component ['/' path-component]*
 | 
			
		||||
//	alpha-numeric                   := /[a-z0-9]+/
 | 
			
		||||
//	separator                       := /[_.]|__|[-]*/
 | 
			
		||||
//
 | 
			
		||||
//	tag                             := /[\w][\w.-]{0,127}/
 | 
			
		||||
//
 | 
			
		||||
//	digest                          := digest-algorithm ":" digest-hex
 | 
			
		||||
//	digest-algorithm                := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
 | 
			
		||||
//	digest-algorithm-separator      := /[+.-_]/
 | 
			
		||||
//	digest-algorithm-component      := /[A-Za-z][A-Za-z0-9]*/
 | 
			
		||||
//	digest-hex                      := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
 | 
			
		||||
//
 | 
			
		||||
//	identifier                      := /[a-f0-9]{64}/
 | 
			
		||||
package reference
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/opencontainers/go-digest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// NameTotalLengthMax is the maximum total number of characters in a repository name.
 | 
			
		||||
	NameTotalLengthMax = 255
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
 | 
			
		||||
	ErrReferenceInvalidFormat = errors.New("invalid reference format")
 | 
			
		||||
 | 
			
		||||
	// ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
 | 
			
		||||
	ErrTagInvalidFormat = errors.New("invalid tag format")
 | 
			
		||||
 | 
			
		||||
	// ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
 | 
			
		||||
	ErrDigestInvalidFormat = errors.New("invalid digest format")
 | 
			
		||||
 | 
			
		||||
	// ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
 | 
			
		||||
	ErrNameContainsUppercase = errors.New("repository name must be lowercase")
 | 
			
		||||
 | 
			
		||||
	// ErrNameEmpty is returned for empty, invalid repository names.
 | 
			
		||||
	ErrNameEmpty = errors.New("repository name must have at least one component")
 | 
			
		||||
 | 
			
		||||
	// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
 | 
			
		||||
	ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
 | 
			
		||||
 | 
			
		||||
	// ErrNameNotCanonical is returned when a name is not canonical.
 | 
			
		||||
	ErrNameNotCanonical = errors.New("repository name must be canonical")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Reference is an opaque object reference identifier that may include
 | 
			
		||||
// modifiers such as a hostname, name, tag, and digest.
 | 
			
		||||
type Reference interface {
 | 
			
		||||
	// String returns the full reference
 | 
			
		||||
	String() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Field provides a wrapper type for resolving correct reference types when
 | 
			
		||||
// working with encoding.
 | 
			
		||||
type Field struct {
 | 
			
		||||
	reference Reference
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AsField wraps a reference in a Field for encoding.
 | 
			
		||||
func AsField(reference Reference) Field {
 | 
			
		||||
	return Field{reference}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reference unwraps the reference type from the field to
 | 
			
		||||
// return the Reference object. This object should be
 | 
			
		||||
// of the appropriate type to further check for different
 | 
			
		||||
// reference types.
 | 
			
		||||
func (f Field) Reference() Reference {
 | 
			
		||||
	return f.reference
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText serializes the field to byte text which
 | 
			
		||||
// is the string of the reference.
 | 
			
		||||
func (f Field) MarshalText() (p []byte, err error) {
 | 
			
		||||
	return []byte(f.reference.String()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText parses text bytes by invoking the
 | 
			
		||||
// reference parser to ensure the appropriately
 | 
			
		||||
// typed reference object is wrapped by field.
 | 
			
		||||
func (f *Field) UnmarshalText(p []byte) error {
 | 
			
		||||
	r, err := Parse(string(p))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f.reference = r
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Named is an object with a full name
 | 
			
		||||
type Named interface {
 | 
			
		||||
	Reference
 | 
			
		||||
	Name() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tagged is an object which has a tag
 | 
			
		||||
type Tagged interface {
 | 
			
		||||
	Reference
 | 
			
		||||
	Tag() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NamedTagged is an object including a name and tag.
 | 
			
		||||
type NamedTagged interface {
 | 
			
		||||
	Named
 | 
			
		||||
	Tag() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Digested is an object which has a digest
 | 
			
		||||
// in which it can be referenced by
 | 
			
		||||
type Digested interface {
 | 
			
		||||
	Reference
 | 
			
		||||
	Digest() digest.Digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Canonical reference is an object with a fully unique
 | 
			
		||||
// name including a name with domain and digest
 | 
			
		||||
type Canonical interface {
 | 
			
		||||
	Named
 | 
			
		||||
	Digest() digest.Digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// namedRepository is a reference to a repository with a name.
 | 
			
		||||
// A namedRepository has both domain and path components.
 | 
			
		||||
type namedRepository interface {
 | 
			
		||||
	Named
 | 
			
		||||
	Domain() string
 | 
			
		||||
	Path() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Domain returns the domain part of the [Named] reference.
 | 
			
		||||
func Domain(named Named) string {
 | 
			
		||||
	if r, ok := named.(namedRepository); ok {
 | 
			
		||||
		return r.Domain()
 | 
			
		||||
	}
 | 
			
		||||
	domain, _ := splitDomain(named.Name())
 | 
			
		||||
	return domain
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path returns the name without the domain part of the [Named] reference.
 | 
			
		||||
func Path(named Named) (name string) {
 | 
			
		||||
	if r, ok := named.(namedRepository); ok {
 | 
			
		||||
		return r.Path()
 | 
			
		||||
	}
 | 
			
		||||
	_, path := splitDomain(named.Name())
 | 
			
		||||
	return path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func splitDomain(name string) (string, string) {
 | 
			
		||||
	match := anchoredNameRegexp.FindStringSubmatch(name)
 | 
			
		||||
	if len(match) != 3 {
 | 
			
		||||
		return "", name
 | 
			
		||||
	}
 | 
			
		||||
	return match[1], match[2]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SplitHostname splits a named reference into a
 | 
			
		||||
// hostname and name string. If no valid hostname is
 | 
			
		||||
// found, the hostname is empty and the full value
 | 
			
		||||
// is returned as name
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: Use [Domain] or [Path].
 | 
			
		||||
func SplitHostname(named Named) (string, string) {
 | 
			
		||||
	if r, ok := named.(namedRepository); ok {
 | 
			
		||||
		return r.Domain(), r.Path()
 | 
			
		||||
	}
 | 
			
		||||
	return splitDomain(named.Name())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse parses s and returns a syntactically valid Reference.
 | 
			
		||||
// If an error was encountered it is returned, along with a nil Reference.
 | 
			
		||||
func Parse(s string) (Reference, error) {
 | 
			
		||||
	matches := ReferenceRegexp.FindStringSubmatch(s)
 | 
			
		||||
	if matches == nil {
 | 
			
		||||
		if s == "" {
 | 
			
		||||
			return nil, ErrNameEmpty
 | 
			
		||||
		}
 | 
			
		||||
		if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
 | 
			
		||||
			return nil, ErrNameContainsUppercase
 | 
			
		||||
		}
 | 
			
		||||
		return nil, ErrReferenceInvalidFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(matches[1]) > NameTotalLengthMax {
 | 
			
		||||
		return nil, ErrNameTooLong
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var repo repository
 | 
			
		||||
 | 
			
		||||
	nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
 | 
			
		||||
	if len(nameMatch) == 3 {
 | 
			
		||||
		repo.domain = nameMatch[1]
 | 
			
		||||
		repo.path = nameMatch[2]
 | 
			
		||||
	} else {
 | 
			
		||||
		repo.domain = ""
 | 
			
		||||
		repo.path = matches[1]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ref := reference{
 | 
			
		||||
		namedRepository: repo,
 | 
			
		||||
		tag:             matches[2],
 | 
			
		||||
	}
 | 
			
		||||
	if matches[3] != "" {
 | 
			
		||||
		var err error
 | 
			
		||||
		ref.digest, err = digest.Parse(matches[3])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r := getBestReferenceType(ref)
 | 
			
		||||
	if r == nil {
 | 
			
		||||
		return nil, ErrNameEmpty
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseNamed parses s and returns a syntactically valid reference implementing
 | 
			
		||||
// the Named interface. The reference must have a name and be in the canonical
 | 
			
		||||
// form, otherwise an error is returned.
 | 
			
		||||
// If an error was encountered it is returned, along with a nil Reference.
 | 
			
		||||
func ParseNamed(s string) (Named, error) {
 | 
			
		||||
	named, err := ParseNormalizedNamed(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if named.String() != s {
 | 
			
		||||
		return nil, ErrNameNotCanonical
 | 
			
		||||
	}
 | 
			
		||||
	return named, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithName returns a named object representing the given string. If the input
 | 
			
		||||
// is invalid ErrReferenceInvalidFormat will be returned.
 | 
			
		||||
func WithName(name string) (Named, error) {
 | 
			
		||||
	if len(name) > NameTotalLengthMax {
 | 
			
		||||
		return nil, ErrNameTooLong
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	match := anchoredNameRegexp.FindStringSubmatch(name)
 | 
			
		||||
	if match == nil || len(match) != 3 {
 | 
			
		||||
		return nil, ErrReferenceInvalidFormat
 | 
			
		||||
	}
 | 
			
		||||
	return repository{
 | 
			
		||||
		domain: match[1],
 | 
			
		||||
		path:   match[2],
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithTag combines the name from "name" and the tag from "tag" to form a
 | 
			
		||||
// reference incorporating both the name and the tag.
 | 
			
		||||
func WithTag(name Named, tag string) (NamedTagged, error) {
 | 
			
		||||
	if !anchoredTagRegexp.MatchString(tag) {
 | 
			
		||||
		return nil, ErrTagInvalidFormat
 | 
			
		||||
	}
 | 
			
		||||
	var repo repository
 | 
			
		||||
	if r, ok := name.(namedRepository); ok {
 | 
			
		||||
		repo.domain = r.Domain()
 | 
			
		||||
		repo.path = r.Path()
 | 
			
		||||
	} else {
 | 
			
		||||
		repo.path = name.Name()
 | 
			
		||||
	}
 | 
			
		||||
	if canonical, ok := name.(Canonical); ok {
 | 
			
		||||
		return reference{
 | 
			
		||||
			namedRepository: repo,
 | 
			
		||||
			tag:             tag,
 | 
			
		||||
			digest:          canonical.Digest(),
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return taggedReference{
 | 
			
		||||
		namedRepository: repo,
 | 
			
		||||
		tag:             tag,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithDigest combines the name from "name" and the digest from "digest" to form
 | 
			
		||||
// a reference incorporating both the name and the digest.
 | 
			
		||||
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
 | 
			
		||||
	if !anchoredDigestRegexp.MatchString(digest.String()) {
 | 
			
		||||
		return nil, ErrDigestInvalidFormat
 | 
			
		||||
	}
 | 
			
		||||
	var repo repository
 | 
			
		||||
	if r, ok := name.(namedRepository); ok {
 | 
			
		||||
		repo.domain = r.Domain()
 | 
			
		||||
		repo.path = r.Path()
 | 
			
		||||
	} else {
 | 
			
		||||
		repo.path = name.Name()
 | 
			
		||||
	}
 | 
			
		||||
	if tagged, ok := name.(Tagged); ok {
 | 
			
		||||
		return reference{
 | 
			
		||||
			namedRepository: repo,
 | 
			
		||||
			tag:             tagged.Tag(),
 | 
			
		||||
			digest:          digest,
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return canonicalReference{
 | 
			
		||||
		namedRepository: repo,
 | 
			
		||||
		digest:          digest,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TrimNamed removes any tag or digest from the named reference.
 | 
			
		||||
func TrimNamed(ref Named) Named {
 | 
			
		||||
	repo := repository{}
 | 
			
		||||
	if r, ok := ref.(namedRepository); ok {
 | 
			
		||||
		repo.domain, repo.path = r.Domain(), r.Path()
 | 
			
		||||
	} else {
 | 
			
		||||
		repo.domain, repo.path = splitDomain(ref.Name())
 | 
			
		||||
	}
 | 
			
		||||
	return repo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getBestReferenceType(ref reference) Reference {
 | 
			
		||||
	if ref.Name() == "" {
 | 
			
		||||
		// Allow digest only references
 | 
			
		||||
		if ref.digest != "" {
 | 
			
		||||
			return digestReference(ref.digest)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if ref.tag == "" {
 | 
			
		||||
		if ref.digest != "" {
 | 
			
		||||
			return canonicalReference{
 | 
			
		||||
				namedRepository: ref.namedRepository,
 | 
			
		||||
				digest:          ref.digest,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return ref.namedRepository
 | 
			
		||||
	}
 | 
			
		||||
	if ref.digest == "" {
 | 
			
		||||
		return taggedReference{
 | 
			
		||||
			namedRepository: ref.namedRepository,
 | 
			
		||||
			tag:             ref.tag,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ref
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type reference struct {
 | 
			
		||||
	namedRepository
 | 
			
		||||
	tag    string
 | 
			
		||||
	digest digest.Digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r reference) String() string {
 | 
			
		||||
	return r.Name() + ":" + r.tag + "@" + r.digest.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r reference) Tag() string {
 | 
			
		||||
	return r.tag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r reference) Digest() digest.Digest {
 | 
			
		||||
	return r.digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type repository struct {
 | 
			
		||||
	domain string
 | 
			
		||||
	path   string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r repository) String() string {
 | 
			
		||||
	return r.Name()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r repository) Name() string {
 | 
			
		||||
	if r.domain == "" {
 | 
			
		||||
		return r.path
 | 
			
		||||
	}
 | 
			
		||||
	return r.domain + "/" + r.path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r repository) Domain() string {
 | 
			
		||||
	return r.domain
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r repository) Path() string {
 | 
			
		||||
	return r.path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type digestReference digest.Digest
 | 
			
		||||
 | 
			
		||||
func (d digestReference) String() string {
 | 
			
		||||
	return digest.Digest(d).String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d digestReference) Digest() digest.Digest {
 | 
			
		||||
	return digest.Digest(d)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type taggedReference struct {
 | 
			
		||||
	namedRepository
 | 
			
		||||
	tag string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t taggedReference) String() string {
 | 
			
		||||
	return t.Name() + ":" + t.tag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t taggedReference) Tag() string {
 | 
			
		||||
	return t.tag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type canonicalReference struct {
 | 
			
		||||
	namedRepository
 | 
			
		||||
	digest digest.Digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c canonicalReference) String() string {
 | 
			
		||||
	return c.Name() + "@" + c.digest.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c canonicalReference) Digest() digest.Digest {
 | 
			
		||||
	return c.digest
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										163
									
								
								vendor/github.com/distribution/reference/regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/distribution/reference/regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
package reference
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DigestRegexp matches well-formed digests, including algorithm (e.g. "sha256:<encoded>").
 | 
			
		||||
var DigestRegexp = regexp.MustCompile(digestPat)
 | 
			
		||||
 | 
			
		||||
// DomainRegexp matches hostname or IP-addresses, optionally including a port
 | 
			
		||||
// number. It defines the structure of potential domain components that may be
 | 
			
		||||
// part of image names. This is purposely a subset of what is allowed by DNS to
 | 
			
		||||
// ensure backwards compatibility with Docker image names. It may be a subset of
 | 
			
		||||
// DNS domain name, an IPv4 address in decimal format, or an IPv6 address between
 | 
			
		||||
// square brackets (excluding zone identifiers as defined by [RFC 6874] or special
 | 
			
		||||
// addresses such as IPv4-Mapped).
 | 
			
		||||
//
 | 
			
		||||
// [RFC 6874]: https://www.rfc-editor.org/rfc/rfc6874.
 | 
			
		||||
var DomainRegexp = regexp.MustCompile(domainAndPort)
 | 
			
		||||
 | 
			
		||||
// IdentifierRegexp is the format for string identifier used as a
 | 
			
		||||
// content addressable identifier using sha256. These identifiers
 | 
			
		||||
// are like digests without the algorithm, since sha256 is used.
 | 
			
		||||
var IdentifierRegexp = regexp.MustCompile(identifier)
 | 
			
		||||
 | 
			
		||||
// NameRegexp is the format for the name component of references, including
 | 
			
		||||
// an optional domain and port, but without tag or digest suffix.
 | 
			
		||||
var NameRegexp = regexp.MustCompile(namePat)
 | 
			
		||||
 | 
			
		||||
// ReferenceRegexp is the full supported format of a reference. The regexp
 | 
			
		||||
// is anchored and has capturing groups for name, tag, and digest
 | 
			
		||||
// components.
 | 
			
		||||
var ReferenceRegexp = regexp.MustCompile(referencePat)
 | 
			
		||||
 | 
			
		||||
// TagRegexp matches valid tag names. From [docker/docker:graph/tags.go].
 | 
			
		||||
//
 | 
			
		||||
// [docker/docker:graph/tags.go]: https://github.com/moby/moby/blob/v1.6.0/graph/tags.go#L26-L28
 | 
			
		||||
var TagRegexp = regexp.MustCompile(tag)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// alphanumeric defines the alphanumeric atom, typically a
 | 
			
		||||
	// component of names. This only allows lower case characters and digits.
 | 
			
		||||
	alphanumeric = `[a-z0-9]+`
 | 
			
		||||
 | 
			
		||||
	// separator defines the separators allowed to be embedded in name
 | 
			
		||||
	// components. This allows one period, one or two underscore and multiple
 | 
			
		||||
	// dashes. Repeated dashes and underscores are intentionally treated
 | 
			
		||||
	// differently. In order to support valid hostnames as name components,
 | 
			
		||||
	// supporting repeated dash was added. Additionally double underscore is
 | 
			
		||||
	// now allowed as a separator to loosen the restriction for previously
 | 
			
		||||
	// supported names.
 | 
			
		||||
	separator = `(?:[._]|__|[-]+)`
 | 
			
		||||
 | 
			
		||||
	// localhost is treated as a special value for domain-name. Any other
 | 
			
		||||
	// domain-name without a "." or a ":port" are considered a path component.
 | 
			
		||||
	localhost = `localhost`
 | 
			
		||||
 | 
			
		||||
	// domainNameComponent restricts the registry domain component of a
 | 
			
		||||
	// repository name to start with a component as defined by DomainRegexp.
 | 
			
		||||
	domainNameComponent = `(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`
 | 
			
		||||
 | 
			
		||||
	// optionalPort matches an optional port-number including the port separator
 | 
			
		||||
	// (e.g. ":80").
 | 
			
		||||
	optionalPort = `(?::[0-9]+)?`
 | 
			
		||||
 | 
			
		||||
	// tag matches valid tag names. From docker/docker:graph/tags.go.
 | 
			
		||||
	tag = `[\w][\w.-]{0,127}`
 | 
			
		||||
 | 
			
		||||
	// digestPat matches well-formed digests, including algorithm (e.g. "sha256:<encoded>").
 | 
			
		||||
	//
 | 
			
		||||
	// TODO(thaJeztah): this should follow the same rules as https://pkg.go.dev/github.com/opencontainers/go-digest@v1.0.0#DigestRegexp
 | 
			
		||||
	// so that go-digest defines the canonical format. Note that the go-digest is
 | 
			
		||||
	// more relaxed:
 | 
			
		||||
	//   - it allows multiple algorithms (e.g. "sha256+b64:<encoded>") to allow
 | 
			
		||||
	//     future expansion of supported algorithms.
 | 
			
		||||
	//   - it allows the "<encoded>" value to use urlsafe base64 encoding as defined
 | 
			
		||||
	//     in [rfc4648, section 5].
 | 
			
		||||
	//
 | 
			
		||||
	// [rfc4648, section 5]: https://www.rfc-editor.org/rfc/rfc4648#section-5.
 | 
			
		||||
	digestPat = `[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`
 | 
			
		||||
 | 
			
		||||
	// identifier is the format for a content addressable identifier using sha256.
 | 
			
		||||
	// These identifiers are like digests without the algorithm, since sha256 is used.
 | 
			
		||||
	identifier = `([a-f0-9]{64})`
 | 
			
		||||
 | 
			
		||||
	// ipv6address are enclosed between square brackets and may be represented
 | 
			
		||||
	// in many ways, see rfc5952. Only IPv6 in compressed or uncompressed format
 | 
			
		||||
	// are allowed, IPv6 zone identifiers (rfc6874) or Special addresses such as
 | 
			
		||||
	// IPv4-Mapped are deliberately excluded.
 | 
			
		||||
	ipv6address = `\[(?:[a-fA-F0-9:]+)\]`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// domainName defines the structure of potential domain components
 | 
			
		||||
	// that may be part of image names. This is purposely a subset of what is
 | 
			
		||||
	// allowed by DNS to ensure backwards compatibility with Docker image
 | 
			
		||||
	// names. This includes IPv4 addresses on decimal format.
 | 
			
		||||
	domainName = domainNameComponent + anyTimes(`\.`+domainNameComponent)
 | 
			
		||||
 | 
			
		||||
	// host defines the structure of potential domains based on the URI
 | 
			
		||||
	// Host subcomponent on rfc3986. It may be a subset of DNS domain name,
 | 
			
		||||
	// or an IPv4 address in decimal format, or an IPv6 address between square
 | 
			
		||||
	// brackets (excluding zone identifiers as defined by rfc6874 or special
 | 
			
		||||
	// addresses such as IPv4-Mapped).
 | 
			
		||||
	host = `(?:` + domainName + `|` + ipv6address + `)`
 | 
			
		||||
 | 
			
		||||
	// allowed by the URI Host subcomponent on rfc3986 to ensure backwards
 | 
			
		||||
	// compatibility with Docker image names.
 | 
			
		||||
	domainAndPort = host + optionalPort
 | 
			
		||||
 | 
			
		||||
	// anchoredTagRegexp matches valid tag names, anchored at the start and
 | 
			
		||||
	// end of the matched string.
 | 
			
		||||
	anchoredTagRegexp = regexp.MustCompile(anchored(tag))
 | 
			
		||||
 | 
			
		||||
	// anchoredDigestRegexp matches valid digests, anchored at the start and
 | 
			
		||||
	// end of the matched string.
 | 
			
		||||
	anchoredDigestRegexp = regexp.MustCompile(anchored(digestPat))
 | 
			
		||||
 | 
			
		||||
	// pathComponent restricts path-components to start with an alphanumeric
 | 
			
		||||
	// character, with following parts able to be separated by a separator
 | 
			
		||||
	// (one period, one or two underscore and multiple dashes).
 | 
			
		||||
	pathComponent = alphanumeric + anyTimes(separator+alphanumeric)
 | 
			
		||||
 | 
			
		||||
	// remoteName matches the remote-name of a repository. It consists of one
 | 
			
		||||
	// or more forward slash (/) delimited path-components:
 | 
			
		||||
	//
 | 
			
		||||
	//	pathComponent[[/pathComponent] ...] // e.g., "library/ubuntu"
 | 
			
		||||
	remoteName = pathComponent + anyTimes(`/`+pathComponent)
 | 
			
		||||
	namePat    = optional(domainAndPort+`/`) + remoteName
 | 
			
		||||
 | 
			
		||||
	// anchoredNameRegexp is used to parse a name value, capturing the
 | 
			
		||||
	// domain and trailing components.
 | 
			
		||||
	anchoredNameRegexp = regexp.MustCompile(anchored(optional(capture(domainAndPort), `/`), capture(remoteName)))
 | 
			
		||||
 | 
			
		||||
	referencePat = anchored(capture(namePat), optional(`:`, capture(tag)), optional(`@`, capture(digestPat)))
 | 
			
		||||
 | 
			
		||||
	// anchoredIdentifierRegexp is used to check or match an
 | 
			
		||||
	// identifier value, anchored at start and end of string.
 | 
			
		||||
	anchoredIdentifierRegexp = regexp.MustCompile(anchored(identifier))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// optional wraps the expression in a non-capturing group and makes the
 | 
			
		||||
// production optional.
 | 
			
		||||
func optional(res ...string) string {
 | 
			
		||||
	return `(?:` + strings.Join(res, "") + `)?`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// anyTimes wraps the expression in a non-capturing group that can occur
 | 
			
		||||
// any number of times.
 | 
			
		||||
func anyTimes(res ...string) string {
 | 
			
		||||
	return `(?:` + strings.Join(res, "") + `)*`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// capture wraps the expression in a capturing group.
 | 
			
		||||
func capture(res ...string) string {
 | 
			
		||||
	return `(` + strings.Join(res, "") + `)`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// anchored anchors the regular expression by adding start and end delimiters.
 | 
			
		||||
func anchored(res ...string) string {
 | 
			
		||||
	return `^` + strings.Join(res, "") + `$`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/github.com/distribution/reference/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/distribution/reference/sort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
   Copyright The containerd Authors.
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package reference
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Sort sorts string references preferring higher information references.
 | 
			
		||||
//
 | 
			
		||||
// The precedence is as follows:
 | 
			
		||||
//
 | 
			
		||||
//  1. [Named] + [Tagged] + [Digested] (e.g., "docker.io/library/busybox:latest@sha256:<digest>")
 | 
			
		||||
//  2. [Named] + [Tagged]              (e.g., "docker.io/library/busybox:latest")
 | 
			
		||||
//  3. [Named] + [Digested]            (e.g., "docker.io/library/busybo@sha256:<digest>")
 | 
			
		||||
//  4. [Named]                         (e.g., "docker.io/library/busybox")
 | 
			
		||||
//  5. [Digested]                      (e.g., "docker.io@sha256:<digest>")
 | 
			
		||||
//  6. Parse error
 | 
			
		||||
func Sort(references []string) []string {
 | 
			
		||||
	var prefs []Reference
 | 
			
		||||
	var bad []string
 | 
			
		||||
 | 
			
		||||
	for _, ref := range references {
 | 
			
		||||
		pref, err := ParseAnyReference(ref)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			bad = append(bad, ref)
 | 
			
		||||
		} else {
 | 
			
		||||
			prefs = append(prefs, pref)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sort.Slice(prefs, func(a, b int) bool {
 | 
			
		||||
		ar := refRank(prefs[a])
 | 
			
		||||
		br := refRank(prefs[b])
 | 
			
		||||
		if ar == br {
 | 
			
		||||
			return prefs[a].String() < prefs[b].String()
 | 
			
		||||
		}
 | 
			
		||||
		return ar < br
 | 
			
		||||
	})
 | 
			
		||||
	sort.Strings(bad)
 | 
			
		||||
	var refs []string
 | 
			
		||||
	for _, pref := range prefs {
 | 
			
		||||
		refs = append(refs, pref.String())
 | 
			
		||||
	}
 | 
			
		||||
	return append(refs, bad...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func refRank(ref Reference) uint8 {
 | 
			
		||||
	if _, ok := ref.(Named); ok {
 | 
			
		||||
		if _, ok = ref.(Tagged); ok {
 | 
			
		||||
			if _, ok = ref.(Digested); ok {
 | 
			
		||||
				return 1
 | 
			
		||||
			}
 | 
			
		||||
			return 2
 | 
			
		||||
		}
 | 
			
		||||
		if _, ok = ref.(Digested); ok {
 | 
			
		||||
			return 3
 | 
			
		||||
		}
 | 
			
		||||
		return 4
 | 
			
		||||
	}
 | 
			
		||||
	return 5
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user