github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/cmd/swagger/commands/diff.go (about) 1 package commands 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "log" 8 "os" 9 10 "errors" 11 12 "github.com/go-openapi/loads" 13 "github.com/go-swagger/go-swagger/cmd/swagger/commands/diff" 14 ) 15 16 // JSONFormat for json 17 const JSONFormat = "json" 18 19 // DiffCommand is a command that generates the diff of two swagger specs. 20 // 21 // There are no specific options for this expansion. 22 type DiffCommand struct { 23 OnlyBreakingChanges bool `long:"break" short:"b" description:"When present, only shows incompatible changes"` 24 Format string `long:"format" short:"f" description:"When present, writes output as json" default:"txt" choice:"txt" choice:"json"` 25 IgnoreFile string `long:"ignore" short:"i" description:"Exception file of diffs to ignore (copy output from json diff format)" default:"none specified"` 26 Destination string `long:"dest" short:"d" description:"Output destination file or stdout" default:"stdout"` 27 Args struct { 28 OldSpec string `positional-arg-name:"{old spec}"` 29 NewSpec string `positional-arg-name:"{new spec}"` 30 } `required:"2" positional-args:"specs" description:"Input specs to be diff-ed"` 31 } 32 33 // Execute diffs the two specs provided 34 func (c *DiffCommand) Execute(_ []string) error { 35 if c.Args.OldSpec == "" || c.Args.NewSpec == "" { 36 return errors.New(`missing arguments for diff command (use --help for more info)`) 37 } 38 39 c.printInfo() 40 41 var ( 42 output io.WriteCloser 43 err error 44 ) 45 if c.Destination != "stdout" { 46 output, err = os.OpenFile(c.Destination, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) 47 if err != nil { 48 return fmt.Errorf("%s: %w", c.Destination, err) 49 } 50 defer func() { 51 _ = output.Close() 52 }() 53 } else { 54 output = os.Stdout 55 } 56 57 diffs, err := c.getDiffs() 58 if err != nil { 59 return err 60 } 61 62 ignores, err := c.readIgnores() 63 if err != nil { 64 return err 65 } 66 67 diffs = diffs.FilterIgnores(ignores) 68 if len(ignores) > 0 { 69 log.Printf("Diff Report Ignored Items from IgnoreFile") 70 for _, eachItem := range ignores { 71 log.Printf("%s", eachItem.String()) 72 } 73 } 74 75 var ( 76 input io.Reader 77 warn error 78 ) 79 if c.Format != JSONFormat && c.OnlyBreakingChanges { 80 input, err, warn = diffs.ReportCompatibility() 81 } else { 82 input, err, warn = diffs.ReportAllDiffs(c.Format == JSONFormat) 83 } 84 if err != nil { 85 return err 86 } 87 _, err = io.Copy(output, input) 88 if err != nil { 89 return err 90 } 91 return warn 92 } 93 94 func (c *DiffCommand) readIgnores() (diff.SpecDifferences, error) { 95 ignoreFile := c.IgnoreFile 96 ignoreDiffs := diff.SpecDifferences{} 97 98 if ignoreFile == "none specified" || ignoreFile == "" { 99 return ignoreDiffs, nil 100 } 101 // Open our jsonFile 102 jsonFile, err := os.Open(ignoreFile) 103 if err != nil { 104 return nil, fmt.Errorf("%s: %w", ignoreFile, err) 105 } 106 defer func() { 107 _ = jsonFile.Close() 108 }() 109 byteValue, err := io.ReadAll(jsonFile) 110 if err != nil { 111 return nil, fmt.Errorf("reading %s: %w", ignoreFile, err) 112 } 113 err = json.Unmarshal(byteValue, &ignoreDiffs) 114 if err != nil { 115 return nil, err 116 } 117 return ignoreDiffs, nil 118 } 119 120 func (c *DiffCommand) getDiffs() (diff.SpecDifferences, error) { 121 oldSpecPath, newSpecPath := c.Args.OldSpec, c.Args.NewSpec 122 swaggerDoc1 := oldSpecPath 123 specDoc1, err := loads.Spec(swaggerDoc1) 124 if err != nil { 125 return nil, err 126 } 127 128 swaggerDoc2 := newSpecPath 129 specDoc2, err := loads.Spec(swaggerDoc2) 130 if err != nil { 131 return nil, err 132 } 133 134 return diff.Compare(specDoc1.Spec(), specDoc2.Spec()) 135 } 136 137 func (c *DiffCommand) printInfo() { 138 log.Println("Run Config:") 139 log.Printf("Spec1: %s", c.Args.OldSpec) 140 log.Printf("Spec2: %s", c.Args.NewSpec) 141 log.Printf("ReportOnlyBreakingChanges (-c) :%v", c.OnlyBreakingChanges) 142 log.Printf("OutputFormat (-f) :%s", c.Format) 143 log.Printf("IgnoreFile (-i) :%s", c.IgnoreFile) 144 log.Printf("Diff Report Destination (-d) :%s", c.Destination) 145 }