github.com/tiagovtristao/plz@v13.4.0+incompatible/src/scm/scm.go (about)

     1  // Package scm abstracts operations on various tools like git
     2  // Currently, only git
     3  package scm
     4  
     5  import (
     6  	"github.com/thought-machine/please/src/core"
     7  	"os/exec"
     8  	"path"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"gopkg.in/op/go-logging.v1"
    13  )
    14  
    15  var log = logging.MustGetLogger("scm")
    16  
    17  // CurrentRevIdentifier returns the string that specifies what the current revision is.
    18  func CurrentRevIdentifier() string {
    19  	return "HEAD"
    20  }
    21  
    22  // ChangesIn returns a list of modified files in the given diffSpec.
    23  func ChangesIn(diffSpec string, relativeTo string) []string {
    24  	if relativeTo == "" {
    25  		relativeTo = core.RepoRoot
    26  	}
    27  	files := make([]string, 0)
    28  	command := []string{"diff-tree", "--no-commit-id", "--name-only", "-r", diffSpec}
    29  	out, err := exec.Command("git", command...).CombinedOutput()
    30  	if err != nil {
    31  		log.Fatalf("unable to determine changes: %s", err)
    32  	}
    33  	output := strings.Split(string(out), "\n")
    34  	for _, o := range output {
    35  		files = append(files, fixGitRelativePath(strings.TrimSpace(o), relativeTo))
    36  	}
    37  	return files
    38  }
    39  
    40  // ChangedFiles returns a list of modified files since the given commit, optionally including untracked files.
    41  func ChangedFiles(fromCommit string, includeUntracked bool, relativeTo string) []string {
    42  	if relativeTo == "" {
    43  		relativeTo = core.RepoRoot
    44  	}
    45  	relSuffix := []string{"--", relativeTo}
    46  	command := []string{"diff", "--name-only", "HEAD"}
    47  
    48  	out, err := exec.Command("git", append(command, relSuffix...)...).CombinedOutput()
    49  	if err != nil {
    50  		log.Fatalf("unable to find changes: %s", err)
    51  	}
    52  	files := strings.Split(string(out), "\n")
    53  
    54  	if fromCommit != "" {
    55  		// Grab the diff from the merge-base to HEAD using ... syntax.  This ensures we have just
    56  		// the changes that have occurred on the current branch.
    57  		command = []string{"diff", "--name-only", fromCommit + "...HEAD"}
    58  		out, err = exec.Command("git", append(command, relSuffix...)...).CombinedOutput()
    59  		if err != nil {
    60  			log.Fatalf("unable to check current branch: %s", err)
    61  		}
    62  		committedChanges := strings.Split(string(out), "\n")
    63  		files = append(files, committedChanges...)
    64  	}
    65  	if includeUntracked {
    66  		command = []string{"ls-files", "--other", "--exclude-standard"}
    67  		out, err = exec.Command("git", append(command, relSuffix...)...).CombinedOutput()
    68  		if err != nil {
    69  			log.Fatalf("unable to determine untracked files: %s", err)
    70  		}
    71  		untracked := strings.Split(string(out), "\n")
    72  		files = append(files, untracked...)
    73  	}
    74  	// git will report changed files relative to the worktree: re-relativize to relativeTo
    75  	normalized := make([]string, 0)
    76  	for _, f := range files {
    77  		normalized = append(normalized, fixGitRelativePath(strings.TrimSpace(f), relativeTo))
    78  	}
    79  	return normalized
    80  }
    81  
    82  func fixGitRelativePath(worktreePath, relativeTo string) string {
    83  	p, err := filepath.Rel(relativeTo, path.Join(core.RepoRoot, worktreePath))
    84  	if err != nil {
    85  		log.Fatalf("unable to determine relative path for %s and %s", core.RepoRoot, relativeTo)
    86  	}
    87  	return p
    88  }