1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
package cmd
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/Azure/azure-sdk-for-go/eng/tools/internal/ioext"
"github.com/Azure/azure-sdk-for-go/eng/tools/internal/repo"
"github.com/Azure/azure-sdk-for-go/eng/tools/internal/report"
)
func printf(format string, a ...interface{}) {
if !quietFlag {
fmt.Printf(format, a...)
}
}
func println(a ...interface{}) {
if !quietFlag {
fmt.Println(a...)
}
}
func dprintf(format string, a ...interface{}) {
if debugFlag {
printf(format, a...)
}
}
func dprintln(a ...interface{}) {
if debugFlag {
println(a...)
}
}
func vprintf(format string, a ...interface{}) {
if verboseFlag {
printf(format, a...)
}
}
func vprintln(a ...interface{}) {
if verboseFlag {
println(a...)
}
}
func processArgsAndClone(args []string) (cln repo.WorkingTree, err error) {
if onlyAdditiveChangesFlag && onlyBreakingChangesFlag {
err = errors.New("flags 'additions' and 'breakingchanges' are mutually exclusive")
return
}
// there should be at minimum two args, a directory and a
// sequence of commits, i.e. "d:\foo 1,2,3". else a directory
// and two commits, i.e. "d:\foo 1 2" or "d:\foo 1 2,3"
if len(args) < 2 {
err = errors.New("not enough args were supplied")
return
}
// here args[1] should be a comma-delimited list of commits
if len(args) == 2 && strings.Index(args[1], ",") < 0 {
err = errors.New("expected a comma-delimited list of commits")
return
}
dir := args[0]
dir, err = filepath.Abs(dir)
if err != nil {
err = fmt.Errorf("failed to convert path '%s' to absolute path: %v", dir, err)
return
}
src, err := repo.Get(dir)
if err != nil {
err = fmt.Errorf("failed to get repository: %v", err)
return
}
tempRepoDir := filepath.Join(os.TempDir(), fmt.Sprintf("apidiff-%v", time.Now().Unix()))
if copyRepoFlag {
vprintf("copying '%s' into '%s'...\n", src.Root(), tempRepoDir)
err = ioext.CopyDir(src.Root(), tempRepoDir)
if err != nil {
err = fmt.Errorf("failed to copy repo: %v", err)
return
}
cln, err = repo.Get(tempRepoDir)
if err != nil {
err = fmt.Errorf("failed to get copied repo: %v", err)
return
}
} else {
vprintf("cloning '%s' into '%s'...\n", src.Root(), tempRepoDir)
cln, err = src.Clone(tempRepoDir)
if err != nil {
err = fmt.Errorf("failed to clone repository: %v", err)
return
}
}
// fix up pkgDir to the clone
args[0] = strings.Replace(dir, src.Root(), cln.Root(), 1)
return
}
type reportGenFunc func(dir string, cln repo.WorkingTree, baseCommit, targetCommit string) error
func generateReports(args []string, cln repo.WorkingTree, fn reportGenFunc) error {
defer func() {
// delete clone
vprintln("cleaning up clone")
err := os.RemoveAll(cln.Root())
if err != nil {
vprintf("failed to delete temp repo: %v\n", err)
}
}()
var commits []string
// if the commits are specified as 1 2,3,4 then it means that commit 1 is
// always the base commit and to compare it against each target commit in
// the sequence. however if it's specifed as 1,2,3,4 then the base commit
// is relative to the iteration, i.e. compare 1-2, 2-3, 3-4.
fixedBase := true
if len(args) == 3 {
commits = make([]string, 2, 2)
commits[0] = args[1]
commits[1] = args[2]
} else {
commits = strings.Split(args[1], ",")
fixedBase = false
}
for i := 0; i+1 < len(commits); i++ {
baseCommit := commits[i]
if fixedBase {
baseCommit = commits[0]
}
targetCommit := commits[i+1]
err := fn(args[0], cln, baseCommit, targetCommit)
if err != nil {
return err
}
}
return nil
}
// compares report status with the desired report options (breaking/additions)
// to determine if the program should terminate with a non-zero exit code.
func evalReportStatus(r report.Status) {
if onlyBreakingChangesFlag && r.HasBreakingChanges() {
os.Exit(1)
}
if onlyAdditiveChangesFlag && !r.HasAdditiveChanges() {
os.Exit(1)
}
}
// PrintReport prints the report to stdout
func PrintReport(r report.Status) error {
if r.IsEmpty() {
println("no changes were found")
return nil
}
if !suppressReport {
b, err := json.MarshalIndent(r, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal report: %v", err)
}
println(string(b))
}
return nil
}
|