// Copyright 2018 jsonnet-bundler authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pkg import ( "bytes" "context" "io/ioutil" "os" "os/exec" "path" "strings" "github.com/jsonnet-bundler/jsonnet-bundler/spec" ) type GitPackage struct { Source *spec.GitSource } func NewGitPackage(source *spec.GitSource) Interface { return &GitPackage{ Source: source, } } func (p *GitPackage) Install(ctx context.Context, dir, version string) (lockVersion string, err error) { cmd := exec.CommandContext(ctx, "git", "init") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } cmd = exec.CommandContext(ctx, "git", "remote", "add", "origin", p.Source.Remote) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } // Attempt shallow fetch at specific revision cmd = exec.CommandContext(ctx, "git", "fetch", "--depth", "1", "origin", version) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { // Fall back to normal fetch (all revisions) cmd = exec.CommandContext(ctx, "git", "fetch", "origin") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } } // If a Subdir is specificied, a sparsecheckout is sufficient if p.Source.Subdir != "" { cmd = exec.CommandContext(ctx, "git", "config", "core.sparsecheckout", "true") cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } glob := []byte(p.Source.Subdir + "/*\n") ioutil.WriteFile(dir+"/.git/info/sparse-checkout", glob, 0644) } cmd = exec.CommandContext(ctx, "git", "-c", "advice.detachedHead=false", "checkout", version) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } b := bytes.NewBuffer(nil) cmd = exec.CommandContext(ctx, "git", "rev-parse", "HEAD") cmd.Stdout = b cmd.Dir = dir err = cmd.Run() if err != nil { return "", err } commitHash := strings.TrimSpace(b.String()) err = os.RemoveAll(path.Join(dir, ".git")) if err != nil { return "", err } return commitHash, nil }