github.com/charypar/monobuild@v0.0.0-20211122220434-fd884ed50212/diff/diff.go (about) 1 package diff 2 3 import ( 4 "fmt" 5 "os/exec" 6 "sort" 7 "strings" 8 9 "github.com/charypar/monobuild/graph" 10 ) 11 12 // BranchMode is the diff mode based on the kind of branch, either Feature or Main 13 type BranchMode int 14 15 // Feature is a feature branch mode 16 var Feature BranchMode = 1 17 18 // Main is a main branch mode 19 var Main BranchMode = 2 20 21 // Mode holds options for the Diff command 22 type Mode struct { 23 Mode BranchMode 24 BaseBranch string 25 BaseCommit string 26 } 27 28 func diffBase(mode Mode) (string, error) { 29 if mode.Mode == Main { 30 return mode.BaseCommit, nil 31 } 32 33 gitMergeBase := exec.Command("git", "merge-base", mode.BaseBranch, "HEAD") 34 mergeBase, err := gitMergeBase.Output() 35 if err != nil { 36 if ee, ok := err.(*exec.ExitError); ok { 37 return "", fmt.Errorf("cannot find merge base with branch '%s': %s", mode.BaseBranch, ee.Stderr) 38 } else { 39 return "", fmt.Errorf("cannot find merge base with branch '%s': %s", mode.BaseBranch, err) 40 } 41 } 42 43 return strings.TrimRight(string(mergeBase), "\n"), nil 44 } 45 46 // ChangedFiles uses git to determine the list of files that changed for 47 // the current revision. 48 // It can operate in a normal (branch) mode, where it compares to a 'baseBranch' 49 // or a 'mainBranch' mode, where it compares to the previous revision or a 'baseCommit' 50 func ChangedFiles(mode Mode) ([]string, error) { 51 base, err := diffBase(mode) 52 if err != nil { 53 return []string{}, err 54 } 55 56 gitDiff := exec.Command("git", "diff", "--no-commit-id", "--name-only", "-r", base) 57 58 gitOut, err := gitDiff.Output() 59 if err != nil { 60 if ee, ok := err.(*exec.ExitError); ok { 61 return []string{}, fmt.Errorf("cannot find changed files:\n%s", ee.Stderr) 62 } else { 63 return []string{}, fmt.Errorf("cannot find changed files:\n%s", err) 64 } 65 } 66 67 changed := strings.Split(strings.TrimRight(string(gitOut), "\n"), "\n") 68 return changed, nil 69 } 70 71 // Impacted calculates the list of changes impacted by a change 72 func Impacted(changedComponents []string, dependencies graph.Graph) []string { 73 impactGraph := dependencies.Reverse() 74 impacted := impactGraph.Descendants(changedComponents) 75 76 result := append(impacted, changedComponents...) 77 sort.Strings(result) 78 79 return result 80 }