remotes: support cross-repo-push

With distribution source label in content store, select the longest
common prefix components as condidate mount blob source and try to push
with mount blob.

Fix #2964

Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
Wei Fu
2019-04-17 17:31:03 +08:00
parent 545e79ae11
commit dd7c0aabcc
6 changed files with 398 additions and 88 deletions

View File

@@ -110,3 +110,45 @@ func appendDistributionSourceLabel(originLabel, repo string) string {
func distributionSourceLabelKey(source string) string {
return fmt.Sprintf("%s.%s", labelDistributionSource, source)
}
// selectRepositoryMountCandidate will select the repo which has longest
// common prefix components as the candidate.
func selectRepositoryMountCandidate(refspec reference.Spec, sources map[string]string) string {
u, err := url.Parse("dummy://" + refspec.Locator)
if err != nil {
// NOTE: basically, it won't be error here
return ""
}
source, target := u.Hostname(), strings.TrimPrefix(u.Path, "/")
repoLabel, ok := sources[distributionSourceLabelKey(source)]
if !ok || repoLabel == "" {
return ""
}
n, match := 0, ""
components := strings.Split(target, "/")
for _, repo := range strings.Split(repoLabel, ",") {
// the target repo is not a candidate
if repo == target {
continue
}
if l := commonPrefixComponents(components, repo); l >= n {
n, match = l, repo
}
}
return match
}
func commonPrefixComponents(components []string, target string) int {
targetComponents := strings.Split(target, "/")
i := 0
for ; i < len(components) && i < len(targetComponents); i++ {
if components[i] != targetComponents[i] {
break
}
}
return i
}