Browse code

move git clone from daemon to client

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)

add a little doc

Victor Vieux authored on 2014/02/27 08:20:58
Showing 3 changed files
... ...
@@ -24,6 +24,7 @@ import (
24 24
 	"net/http/httputil"
25 25
 	"net/url"
26 26
 	"os"
27
+	"os/exec"
27 28
 	gosignal "os/signal"
28 29
 	"path"
29 30
 	"reflect"
... ...
@@ -168,17 +169,34 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
168 168
 			return err
169 169
 		}
170 170
 		context, err = archive.Generate("Dockerfile", string(dockerfile))
171
-	} else if utils.IsURL(cmd.Arg(0)) || utils.IsGIT(cmd.Arg(0)) {
171
+	} else if utils.IsURL(cmd.Arg(0)) && !utils.IsGIT(cmd.Arg(0)) {
172 172
 		isRemote = true
173 173
 	} else {
174
-		if _, err := os.Stat(cmd.Arg(0)); err != nil {
174
+		root := cmd.Arg(0)
175
+		if utils.IsGIT(root) {
176
+			remoteURL := cmd.Arg(0)
177
+			if !strings.HasPrefix(remoteURL, "git://") && !strings.HasPrefix(remoteURL, "git@") && !utils.IsURL(remoteURL) {
178
+				remoteURL = "https://" + remoteURL
179
+			}
180
+
181
+			root, err = ioutil.TempDir("", "docker-build-git")
182
+			if err != nil {
183
+				return err
184
+			}
185
+			defer os.RemoveAll(root)
186
+
187
+			if output, err := exec.Command("git", "clone", "--recursive", remoteURL, root).CombinedOutput(); err != nil {
188
+				return fmt.Errorf("Error trying to use git: %s (%s)", err, output)
189
+			}
190
+		}
191
+		if _, err := os.Stat(root); err != nil {
175 192
 			return err
176 193
 		}
177
-		filename := path.Join(cmd.Arg(0), "Dockerfile")
194
+		filename := path.Join(root, "Dockerfile")
178 195
 		if _, err = os.Stat(filename); os.IsNotExist(err) {
179 196
 			return fmt.Errorf("no Dockerfile found in %s", cmd.Arg(0))
180 197
 		}
181
-		context, err = archive.Tar(cmd.Arg(0), archive.Uncompressed)
198
+		context, err = archive.Tar(root, archive.Uncompressed)
182 199
 	}
183 200
 	var body io.Reader
184 201
 	// Setup an upload progress bar
... ...
@@ -202,12 +202,16 @@ Examples:
202 202
       --no-cache: Do not use the cache when building the image.
203 203
       --rm=true: Remove intermediate containers after a successful build
204 204
 
205
-The files at ``PATH`` or ``URL`` are called the "context" of the build. The
206
-build process may refer to any of the files in the context, for example when
207
-using an :ref:`ADD <dockerfile_add>` instruction.  When a single ``Dockerfile``
208
-is given as ``URL``, then no context is set.  When a Git repository is set as
209
-``URL``, then the repository is used as the context. Git repositories are
210
-cloned with their submodules (`git clone --recursive`).
205
+The files at ``PATH`` or ``URL`` are called the "context" of the build.
206
+The build process may refer to any of the files in the context, for example when
207
+using an :ref:`ADD <dockerfile_add>` instruction.
208
+When a single ``Dockerfile`` is given as ``URL``, then no context is set.
209
+
210
+When a Git repository is set as ``URL``, then the repository is used as the context. 
211
+The Git repository is cloned with its submodules (`git clone --recursive`).
212
+A fresh git clone occurs in a temporary directory on your local host, and then this 
213
+is sent to the Docker daemon as the context. 
214
+This way, your local user credentials and vpn's etc can be used to access private repositories
211 215
 
212 216
 .. _cli_build_examples:
213 217
 
... ...
@@ -714,7 +714,7 @@ func IsURL(str string) bool {
714 714
 }
715 715
 
716 716
 func IsGIT(str string) bool {
717
-	return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/")
717
+	return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/") || strings.HasPrefix(str, "git@github.com:") || (strings.HasSuffix(str, ".git") && IsURL(str))
718 718
 }
719 719
 
720 720
 // GetResolvConf opens and read the content of /etc/resolv.conf.