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:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user