| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package checkout |
| |
| import ( |
| "context" |
| "fmt" |
| "io" |
| "net/url" |
| "os" |
| "strings" |
| |
| buildbucketpb "go.chromium.org/luci/buildbucket/proto" |
| "go.fuchsia.dev/infra/execution" |
| ) |
| |
| const gitFatalLogPrefix = "fatal: " |
| |
| // Checkout checks out the git repo at repoURL according to the given build |
| // input. |
| // |
| // defaultRevision specifies the revision to check out if the build was |
| // triggered by a commit or change on a *different* repository, in which case we |
| // can't use the build input to determine which revision of `repoURL` to check |
| // out. |
| func Checkout(ctx context.Context, input *buildbucketpb.Build_Input, repoURL url.URL, defaultRevision, dir string) error { |
| strat, err := newStrategy(input, repoURL, defaultRevision) |
| if err != nil { |
| return err |
| } |
| |
| var stderrBuf strings.Builder |
| stderrWriter := io.MultiWriter(os.Stderr, &stderrBuf) |
| // Write everything to stderr. luciexe expects the stdout of the |
| // recipe_bootstrap tool to be a proto. |
| executor := execution.NewExecutor(os.Stderr, stderrWriter, dir) |
| if err := strat.Checkout(ctx, executor); err != nil { |
| // When git fails it usually emits a "fatal" log in the last line of |
| // stderr. Make a best effort at parsing out that line and including it in |
| // the error message. |
| lines := strings.Split(strings.TrimSpace(stderrBuf.String()), "\n") |
| lastLine := lines[len(lines)-1] |
| if strings.HasPrefix(lastLine, gitFatalLogPrefix) { |
| return fmt.Errorf("%s. Original error: %w", strings.TrimPrefix(lastLine, gitFatalLogPrefix), err) |
| } |
| return err |
| } |
| return nil |
| } |