github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/util/git/git.go (about)

     1  // Copyright 2019 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package git contains git repo cloning functions similar to Kustomize's
    16  package git
    17  
    18  import (
    19  	"fmt"
    20  	"os"
    21  	"os/exec"
    22  	"path"
    23  	"path/filepath"
    24  	"strings"
    25  
    26  	"github.com/GoogleContainerTools/kpt/internal/errors"
    27  )
    28  
    29  // RepoSpec specifies a git repository and a branch and path therein.
    30  type RepoSpec struct {
    31  	// Host, e.g. github.com
    32  	Host string
    33  
    34  	// orgRepo name (organization/repoName),
    35  	// e.g. kubernetes-sigs/kustomize
    36  	OrgRepo string
    37  
    38  	// Dir where the orgRepo is cloned to.
    39  	Dir string
    40  
    41  	// Commit is the commit for the version that was added to Dir.
    42  	Commit string
    43  
    44  	// Relative path in the repository, and in the cloneDir,
    45  	// to a Kustomization.
    46  	Path string
    47  
    48  	// Branch or tag reference.
    49  	Ref string
    50  
    51  	// e.g. .git or empty in case of _git is present
    52  	GitSuffix string
    53  }
    54  
    55  // AbsPath is the absolute path to the subdirectory
    56  func (rs RepoSpec) AbsPath() string {
    57  	return filepath.Join(rs.Dir, rs.Path)
    58  }
    59  
    60  // CloneSpec returns the string to pass to git to clone
    61  func (rs *RepoSpec) CloneSpec() string {
    62  	if isAzureHost(rs.Host) || isAWSHost(rs.Host) {
    63  		return rs.Host + rs.OrgRepo
    64  	}
    65  	return rs.Host + rs.OrgRepo + rs.GitSuffix
    66  }
    67  
    68  // isAzureHost returns true if the repo is an Azure repo
    69  // The format of Azure repo URL is documented
    70  // https://docs.microsoft.com/en-us/azure/devops/repos/git/clone?view=vsts&tabs=visual-studio#clone_url
    71  func isAzureHost(host string) bool {
    72  	return strings.Contains(host, "dev.azure.com") ||
    73  		strings.Contains(host, "visualstudio.com")
    74  }
    75  
    76  // isAWSHost returns true if the repo is an AWS repo
    77  // The format of AWS repo URL is documented
    78  // https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html
    79  func isAWSHost(host string) bool {
    80  	return strings.Contains(host, "amazonaws.com")
    81  }
    82  
    83  // lookupCommit looks up the sha of the current commit on the repo at the
    84  // provided path.
    85  func LookupCommit(repoPath string) (string, error) {
    86  	const op errors.Op = "git.LookupCommit"
    87  	cmd := exec.Command("git", "rev-parse", "--verify", "HEAD")
    88  	cmd.Dir = repoPath
    89  	cmd.Env = os.Environ()
    90  	cmd.Stderr = os.Stderr
    91  	b, err := cmd.Output()
    92  	if err != nil {
    93  		return "", errors.E(op, errors.Git, fmt.Errorf("unable to look up commit: %w", err))
    94  	}
    95  	commit := strings.TrimSpace(string(b))
    96  	return commit, nil
    97  }
    98  
    99  func (rs *RepoSpec) RepoRef() string {
   100  	repoPath := path.Join(rs.CloneSpec(), rs.Path)
   101  	if rs.Ref != "" {
   102  		return repoPath + fmt.Sprintf("@%s", rs.Ref)
   103  	}
   104  	return repoPath
   105  }