Browse Source

builder/remotecontext/urlutil: simplify and improve documentation

Simplify some of the logic, and add documentation about the package,
as well as warnings that this package should not be used as a general-
purpose utility.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 3 years ago
parent
commit
449250994f
1 changed files with 67 additions and 25 deletions
  1. 67 25
      builder/remotecontext/urlutil/urlutil.go

+ 67 - 25
builder/remotecontext/urlutil/urlutil.go

@@ -1,5 +1,8 @@
-// Package urlutil provides helper function to check urls kind.
-// It supports http and git urls.
+// Package urlutil provides helper function to check if a given build-context
+// location should be considered a URL or a remote Git repository.
+//
+// This package is specifically written for use with docker build contexts, and
+// should not be used as a general-purpose utility.
 package urlutil // import "github.com/docker/docker/builder/remotecontext/urlutil"
 package urlutil // import "github.com/docker/docker/builder/remotecontext/urlutil"
 
 
 import (
 import (
@@ -7,37 +10,76 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-var (
-	validPrefixes = map[string][]string{
-		"url": {"http://", "https://"},
+// urlPathWithFragmentSuffix matches fragments to use as Git reference and build
+// context from the Git repository. See IsGitURL for details.
+var urlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$")
 
 
-		// The github.com/ prefix is a special case used to treat context-paths
-		// starting with `github.com` as a git URL if the given path does not
-		// exist locally. The "github.com/" prefix is kept for backward compatibility,
-		// and is a legacy feature.
-		//
-		// Going forward, no additional prefixes should be added, and users should
-		// be encouraged to use explicit URLs (https://github.com/user/repo.git) instead.
-		"git": {"git://", "github.com/", "git@"},
-	}
-	urlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$")
-)
-
-// IsURL returns true if the provided str is an HTTP(S) URL.
+// IsURL returns true if the provided str is an HTTP(S) URL by checking if it
+// has a http:// or https:// scheme. No validation is performed to verify if the
+// URL is well-formed.
 func IsURL(str string) bool {
 func IsURL(str string) bool {
-	return checkURL(str, "url")
+	return strings.HasPrefix(str, "https://") || strings.HasPrefix(str, "http://")
 }
 }
 
 
-// IsGitURL returns true if the provided str is a git repository URL.
+// IsGitURL returns true if the provided str is a remote git repository "URL".
+//
+// This function only performs a rudimentary check (no validation is performed
+// to ensure the URL is well-formed), and is written specifically for use with
+// docker build, with some logic for backward compatibility with older versions
+// of docker: do not use this function as a general-purpose utility.
+//
+// The following patterns are considered to be a Git URL:
+//
+// - https://(.*).git(?:#.+)?$  git repository URL with optional fragment, as
+//                              known to be used by GitHub and GitLab.
+// - http://(.*).git(?:#.+)?$   same, but non-TLS
+// - git://(.*)                 URLs using git:// scheme
+// - git@(.*)
+// - github.com/                see description below
+//
+// The github.com/ prefix is a special case used to treat context-paths
+// starting with "github.com/" as a git URL if the given path does not
+// exist locally. The "github.com/" prefix is kept for backward compatibility,
+// and is a legacy feature.
+//
+// Going forward, no additional prefixes should be added, and users should
+// be encouraged to use explicit URLs (https://github.com/user/repo.git) instead.
+//
+// Note that IsGitURL does not check if "github.com/" prefixes exist as a local
+// path. Code using this function should check if the path exists locally before
+// using it as a URL.
+//
+// Fragments
+//
+// Git URLs accept context configuration in their fragment section, separated by
+// a colon (`:`). The first part represents the reference to check out, and can
+// be either a branch, a tag, or a remote reference. The second part represents
+// a subdirectory inside the repository to use as the build context.
+//
+// For example,the following URL uses a directory named "docker" in the branch
+// "container" in the https://github.com/myorg/my-repo.git repository:
+//
+// https://github.com/myorg/my-repo.git#container:docker
+//
+// The following table represents all the valid suffixes with their build
+// contexts:
+//
+// | Build Syntax Suffix            | Git reference used   | Build Context Used |
+// |--------------------------------|----------------------|--------------------|
+// | my-repo.git                    | refs/heads/master    | /                  |
+// | my-repo.git#mytag              | refs/tags/my-tag     | /                  |
+// | my-repo.git#mybranch           | refs/heads/my-branch | /                  |
+// | my-repo.git#pull/42/head       | refs/pull/42/head    | /                  |
+// | my-repo.git#:directory         | refs/heads/master    | /directory         |
+// | my-repo.git#master:directory   | refs/heads/master    | /directory         |
+// | my-repo.git#mytag:directory    | refs/tags/my-tag     | /directory         |
+// | my-repo.git#mybranch:directory | refs/heads/my-branch | /directory         |
+//
 func IsGitURL(str string) bool {
 func IsGitURL(str string) bool {
 	if IsURL(str) && urlPathWithFragmentSuffix.MatchString(str) {
 	if IsURL(str) && urlPathWithFragmentSuffix.MatchString(str) {
 		return true
 		return true
 	}
 	}
-	return checkURL(str, "git")
-}
-
-func checkURL(str, kind string) bool {
-	for _, prefix := range validPrefixes[kind] {
+	for _, prefix := range []string{"git://", "github.com/", "git@"} {
 		if strings.HasPrefix(str, prefix) {
 		if strings.HasPrefix(str, prefix) {
 			return true
 			return true
 		}
 		}