func streamPathToBuild(repo git.Repository, in io.Reader, out io.Writer, client osclient.BuildConfigInterface, fromDir, fromFile, fromRepo string, options *buildapi.BinaryBuildRequestOptions) (*buildapi.Build, error) { count := 0 asDir, asFile, asRepo := len(fromDir) > 0, len(fromFile) > 0, len(fromRepo) > 0 if asDir { count++ } if asFile { count++ } if asRepo { count++ } if count > 1 { return nil, fmt.Errorf("only one of --from-file, --from-repo, or --from-dir may be specified") } if asRepo && !git.IsGitInstalled() { return nil, fmt.Errorf("cannot find git. Git is required to start a build from a repository. If git is not available, use --from-dir instead.") } var r io.Reader switch { case fromFile == "-": return nil, fmt.Errorf("--from-file=- is not supported") case fromDir == "-": br := bufio.NewReaderSize(in, 4096) r = br if !isArchive(br) { fmt.Fprintf(out, "WARNING: the provided file may not be an archive (tar, tar.gz, or zip), use --from-file=- instead\n") } fmt.Fprintf(out, "Uploading archive file from STDIN as binary input for the build ...\n") default: var fromPath string switch { case asDir: fromPath = fromDir case asFile: fromPath = fromFile case asRepo: fromPath = fromRepo } clean := filepath.Clean(fromPath) path, err := filepath.Abs(fromPath) if err != nil { return nil, err } stat, err := os.Stat(path) if err != nil { return nil, err } if stat.IsDir() { commit := "HEAD" if len(options.Commit) > 0 { commit = options.Commit } info, gitErr := gitRefInfo(repo, path, commit) if gitErr == nil { options.Commit = info.GitSourceRevision.Commit options.Message = info.GitSourceRevision.Message options.AuthorName = info.GitSourceRevision.Author.Name options.AuthorEmail = info.GitSourceRevision.Author.Email options.CommitterName = info.GitSourceRevision.Committer.Name options.CommitterEmail = info.GitSourceRevision.Committer.Email } else { glog.V(6).Infof("Unable to read Git info from %q: %v", clean, gitErr) } // NOTE: It's important that this stays false unless we change the // path to something else, otherwise we will delete whatever path the // user provided. var usedTempDir bool = false var tempDirectory string = "" if asRepo { var contextDir string = "" fmt.Fprintf(out, "Uploading %q at commit %q as binary input for the build ...\n", clean, commit) if gitErr != nil { return nil, fmt.Errorf("the directory %q is not a valid Git repository: %v", clean, gitErr) } // If the user doesn't give us the root directory of the Git repo, // we still want the command to work. However, as this may be // unintended, we warn them. if gitRootDir, err := repo.GetRootDir(path); filepath.Clean(gitRootDir) != filepath.Clean(path) && err == nil { fmt.Fprintf(out, "WARNING: Using root dir %s for Git repository\n", gitRootDir) contextDir, _ = filepath.Rel(gitRootDir, path) path = gitRootDir } // Create a temp directory to move the repo contents to tempDirectory, err := ioutil.TempDir(os.TempDir(), "oc_cloning_"+options.Commit) if err != nil { return nil, err } // We only want to grab the contents of the specified commit, with // submodules included cloneOptions := []string{"--recursive"} if verbose := glog.V(3); !verbose { cloneOptions = append(cloneOptions, "--quiet") } // Clone the repository to a temp directory for future tar-ing if err := repo.CloneWithOptions(tempDirectory, path, cloneOptions...); err != nil { return nil, err } if err := repo.Checkout(tempDirectory, commit); err != nil { return nil, err } // We'll continue to use tar on the temp directory path = filepath.Join(tempDirectory, contextDir) usedTempDir = true } else { fmt.Fprintf(out, "Uploading directory %q as binary input for the build ...\n", clean) } pr, pw := io.Pipe() go func() { w := gzip.NewWriter(pw) if err := tar.New().CreateTarStream(path, false, w); err != nil { pw.CloseWithError(err) } else { w.Close() pw.CloseWithError(io.EOF) } if usedTempDir { os.RemoveAll(tempDirectory) } }() r = pr } else { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() r = f if asFile { options.AsFile = filepath.Base(path) fmt.Fprintf(out, "Uploading file %q as binary input for the build ...\n", clean) } else { br := bufio.NewReaderSize(f, 4096) r = br if !isArchive(br) { fmt.Fprintf(out, "WARNING: the provided file may not be an archive (tar, tar.gz, or zip), use --as-file\n") } fmt.Fprintf(out, "Uploading archive file %q as binary input for the build ...\n", clean) } } } return client.InstantiateBinary(options, r) }
func streamPathToBuild(repo git.Repository, in io.Reader, out io.Writer, client osclient.BuildConfigInterface, fromDir, fromFile, fromRepo string, options *buildapi.BinaryBuildRequestOptions) (*buildapi.Build, error) { count := 0 asDir, asFile, asRepo := len(fromDir) > 0, len(fromFile) > 0, len(fromRepo) > 0 if asDir { count++ } if asFile { count++ } if asRepo { count++ } if count > 1 { return nil, fmt.Errorf("only one of --from-file, --from-repo, or --from-dir may be specified") } if asRepo && !git.IsGitInstalled() { return nil, fmt.Errorf("cannot find git. Git is required to start a build from a repository. If git is not available, use --from-dir instead.") } var r io.Reader switch { case fromFile == "-": return nil, fmt.Errorf("--from-file=- is not supported") case fromDir == "-": br := bufio.NewReaderSize(in, 4096) r = br if !isArchive(br) { fmt.Fprintf(out, "WARNING: the provided file may not be an archive (tar, tar.gz, or zip), use --from-file=- instead\n") } fmt.Fprintf(out, "Uploading archive file from STDIN as binary input for the build ...\n") default: var fromPath string switch { case asDir: fromPath = fromDir case asFile: fromPath = fromFile case asRepo: fromPath = fromRepo } clean := filepath.Clean(fromPath) path, err := filepath.Abs(fromPath) if err != nil { return nil, err } stat, err := os.Stat(path) if err != nil { return nil, err } if stat.IsDir() { commit := "HEAD" if len(options.Commit) > 0 { commit = options.Commit } info, gitErr := gitRefInfo(repo, clean, commit) if gitErr == nil { options.Commit = info.GitSourceRevision.Commit options.Message = info.GitSourceRevision.Message options.AuthorName = info.GitSourceRevision.Author.Name options.AuthorEmail = info.GitSourceRevision.Author.Email options.CommitterName = info.GitSourceRevision.Committer.Name options.CommitterEmail = info.GitSourceRevision.Committer.Email } else { glog.V(6).Infof("Unable to read Git info from %q: %v", clean, gitErr) } if asRepo { fmt.Fprintf(out, "Uploading %q at commit %q as binary input for the build ...\n", clean, commit) if gitErr != nil { return nil, fmt.Errorf("the directory %q is not a valid Git repository: %v", clean, gitErr) } pr, pw := io.Pipe() go func() { if err := repo.Archive(clean, options.Commit, "tar.gz", pw); err != nil { pw.CloseWithError(fmt.Errorf("unable to create Git archive of %q for build: %v", clean, err)) } else { pw.CloseWithError(io.EOF) } }() r = pr } else { fmt.Fprintf(out, "Uploading directory %q as binary input for the build ...\n", clean) pr, pw := io.Pipe() go func() { w := gzip.NewWriter(pw) if err := tar.New().CreateTarStream(path, false, w); err != nil { pw.CloseWithError(err) } else { w.Close() pw.CloseWithError(io.EOF) } }() r = pr } } else { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() r = f if asFile { options.AsFile = filepath.Base(path) fmt.Fprintf(out, "Uploading file %q as binary input for the build ...\n", clean) } else { br := bufio.NewReaderSize(f, 4096) r = br if !isArchive(br) { fmt.Fprintf(out, "WARNING: the provided file may not be an archive (tar, tar.gz, or zip), use --as-file\n") } fmt.Fprintf(out, "Uploading archive file %q as binary input for the build ...\n", clean) } } } return client.InstantiateBinary(options, r) }
func checkGitInstalled(w io.Writer) { if !git.IsGitInstalled() { fmt.Fprintf(w, "warning: Cannot find git. Ensure that it is installed and in your path. Git is required to work with git repositories.\n") } }