// CloneAndCheckoutSources clones the remote repository using either regular // git clone operation or shallow git clone, based on the "ref" provided (you // cannot shallow clone using the 'ref'). // This function will return the full path to the buildable sources, including // the context directory if specified. func CloneAndCheckoutSources(repo git.Repository, remote, ref, localDir, contextDir string) (string, error) { if len(ref) == 0 { glog.V(5).Infof("No source ref specified, using shallow git clone") if err := repo.CloneWithOptions(localDir, remote, git.Shallow, "--recursive"); err != nil { return "", fmt.Errorf("shallow cloning repository %q to %q failed: %v", remote, localDir, err) } } else { glog.V(5).Infof("Requested ref %q, performing full git clone and git checkout", ref) if err := repo.Clone(localDir, remote); err != nil { return "", fmt.Errorf("cloning repository %q to %q failed: %v", remote, localDir, err) } } if len(ref) > 0 { if err := repo.Checkout(localDir, ref); err != nil { return "", fmt.Errorf("unable to checkout ref %q in %q repository: %v", ref, remote, err) } } if len(contextDir) > 0 { glog.V(5).Infof("Using context directory %q. The full source path is %q", contextDir, filepath.Join(localDir, contextDir)) } return filepath.Join(localDir, contextDir), nil }
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) }