diff --git a/api.go b/api.go index 5a9bdbbe23..94dd94c404 100644 --- a/api.go +++ b/api.go @@ -7,6 +7,7 @@ import ( "github.com/dotcloud/docker/utils" "github.com/gorilla/mux" "io" + "io/ioutil" "log" "net/http" "strconv" @@ -674,31 +675,51 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ if err := r.ParseMultipartForm(4096); err != nil { return err } - remote := r.FormValue("t") + remoteURL := r.FormValue("remote") + repoName := r.FormValue("t") tag := "" - if strings.Contains(remote, ":") { - remoteParts := strings.Split(remote, ":") + if strings.Contains(repoName, ":") { + remoteParts := strings.Split(repoName, ":") tag = remoteParts[1] - remote = remoteParts[0] + repoName = remoteParts[0] } - dockerfile, _, err := r.FormFile("Dockerfile") - if err != nil { - return err - } + var dockerfile, context io.ReadCloser - context, _, err := r.FormFile("Context") - if err != nil { - if err != http.ErrMissingFile { + if remoteURL == "" { + d, _, err := r.FormFile("Dockerfile") + if err != nil { return err + } else { + dockerfile = d + } + c, _, err := r.FormFile("Context") + if err != nil { + if err != http.ErrMissingFile { + return err + } + } else { + context = c + } + } else { + if utils.IsGIT(remoteURL) { + return fmt.Errorf("Builder from git is not yet supported") + } else if utils.IsURL(remoteURL) { + f, err := utils.Download(remoteURL, ioutil.Discard) + if err != nil { + return err + } else { + dockerfile = f.Body + } + defer f.Body.Close() } } b := NewBuildFile(srv, utils.NewWriteFlusher(w)) if id, err := b.Build(dockerfile, context); err != nil { fmt.Fprintf(w, "Error build: %s\n", err) - } else if remote != "" { - srv.runtime.repositories.Set(remote, tag, id, false) + } else if repoName != "" { + srv.runtime.repositories.Set(repoName, tag, id, false) } return nil } diff --git a/commands.go b/commands.go index 50cca552c0..de0e6432f2 100644 --- a/commands.go +++ b/commands.go @@ -155,15 +155,12 @@ func (cli *DockerCli) CmdBuild(args ...string) error { compression := Bzip2 + isRemote := false + if cmd.Arg(0) == "-" { file = os.Stdin - } else if utils.IsURL(cmd.Arg(0)) { - f, err := utils.Download(cmd.Arg(0), ioutil.Discard) - if err != nil { - return err - } - defer f.Body.Close() - file = f.Body + } else if utils.IsURL(cmd.Arg(0)) || utils.IsGIT(cmd.Arg(0)) { + isRemote = true } else { // Send Dockerfile from arg/Dockerfile (deprecate later) f, err := os.Open(path.Join(cmd.Arg(0), "Dockerfile")) @@ -192,16 +189,20 @@ func (cli *DockerCli) CmdBuild(args ...string) error { io.Copy(wField, utils.ProgressReader(ioutil.NopCloser(context), -1, os.Stdout, sf.FormatProgress("Caching Context", "%v/%v (%v)"), sf)) multipartBody = io.MultiReader(multipartBody, boundary) } - // Create a FormFile multipart for the Dockerfile - wField, err := w.CreateFormFile("Dockerfile", "Dockerfile") - if err != nil { - return err + if !isRemote { + // Create a FormFile multipart for the Dockerfile + wField, err := w.CreateFormFile("Dockerfile", "Dockerfile") + if err != nil { + return err + } + io.Copy(wField, file) + multipartBody = io.MultiReader(multipartBody, boundary) } - io.Copy(wField, file) - multipartBody = io.MultiReader(multipartBody, boundary) - v := &url.Values{} v.Set("t", *tag) + if isRemote { + v.Set("remote", cmd.Arg(0)) + } // Send the multipart request with correct content-type req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s?%s", cli.host, cli.port, "/build", v.Encode()), multipartBody) if err != nil { diff --git a/utils/utils.go b/utils/utils.go index 752cc03f32..f0b0f22b46 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -624,3 +624,7 @@ func (sf *StreamFormatter) Used() bool { func IsURL(str string) bool { return strings.HasPrefix(str, "http://") || strings.HasPrefix(str, "https://") } + +func IsGIT(str string) bool { + return strings.HasPrefix(str, "git://") || strings.HasPrefix(str, "github.com/") +}