diff --git a/go.mod b/go.mod index 46ac53f..b9496ce 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,12 @@ go 1.13 require ( github.com/Luzifer/rconfig/v2 v2.2.1 + github.com/fatih/color v1.7.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/mattn/go-colorable v0.1.2 // indirect + github.com/mattn/go-isatty v0.0.9 // indirect github.com/mitchellh/go-homedir v1.1.0 + github.com/sergi/go-diff v1.0.0 github.com/sirupsen/logrus v1.4.2 golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5 // indirect gopkg.in/validator.v2 v2.0.0-20190827175613-1a84e0480e5b // indirect diff --git a/go.sum b/go.sum index c7a4618..d6dc0b3 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,36 @@ github.com/Luzifer/rconfig v2.2.0+incompatible h1:Kle3+rshPM7LxciOheaR4EfHUzibkDDGws04sefQ5m8= github.com/Luzifer/rconfig/v2 v2.2.1 h1:zcDdLQlnlzwcBJ8E0WFzOkQE1pCMn3EbX0dFYkeTczg= github.com/Luzifer/rconfig/v2 v2.2.1/go.mod h1:OKIX0/JRZrPJ/ZXXWklQEFXA6tBfWaljZbW37w+sqBw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5 h1:SW/0nsKCUaozCUtZTakri5laocGx/5bkDSSLrFUsa5s= golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index 7d33cd6..e2faa55 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,16 @@ import ( "bytes" "fmt" "io" + "io/ioutil" "os" "os/exec" "regexp" "strings" "text/template" + "github.com/fatih/color" homedir "github.com/mitchellh/go-homedir" + diff "github.com/sergi/go-diff/diffmatchpatch" log "github.com/sirupsen/logrus" "github.com/Luzifer/rconfig/v2" @@ -18,6 +21,7 @@ import ( var ( cfg = struct { + Diff bool `flag:"diff" default:"false" description:"Show a diff to existing Dockerfile"` ExposedPorts []string `flag:"expose,e" default:"" description:"Ports to expose (format '8000' or '8000/tcp')"` LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"` TemplateFile string `flag:"template-file" default:"~/.config/gen-dockerfile.tpl" description:"Template to use for generating the docker file"` @@ -89,6 +93,11 @@ func main() { } var output io.Writer = os.Stdout + if cfg.Diff { + displayDiff(buf) + output = ioutil.Discard + } + if cfg.Write { f, err := os.Create("Dockerfile") if err != nil { @@ -101,6 +110,58 @@ func main() { fmt.Fprintln(output, strings.TrimSpace(regexp.MustCompile(`\n{3,}`).ReplaceAllString(buf.String(), "\n\n"))) } +func displayDiff(buf *bytes.Buffer) { + var ( + lenOldDockerfile int + oldDockerfile []byte + oldName = "/dev/null" + ) + + if _, err := os.Stat("Dockerfile"); err == nil { + oldDockerfile, err = ioutil.ReadFile("Dockerfile") + if err != nil { + log.WithError(err).Fatal("Could not read existing Dockerfile") + } + lenOldDockerfile = len(bytes.Split(oldDockerfile, []byte{'\n'})) + oldName = "a/Dockerfile" + } + + differ := diff.New() + wSrc, wDst, warray := differ.DiffLinesToRunes(string(oldDockerfile), regexp.MustCompile(`\n{3,}`).ReplaceAllString(buf.String(), "\n\n")) + diffs := differ.DiffMainRunes(wSrc, wDst, false) + diffs = differ.DiffCharsToLines(diffs, warray) + + if len(diffs) == 1 && diffs[0].Type == diff.DiffEqual { + // No diff, everything equal: Nothing to display + return + } + + fmt.Printf("--- %s\n", oldName) + fmt.Println("+++ b/Dockerfile") + color.Cyan("@@ -0,%d +0,%d @@", + lenOldDockerfile, + len(strings.Split(differ.DiffText2(diffs), "\n")), + ) + + for _, d := range diffs { + var text = d.Text + if text[len(text)-1] == '\n' { + text = text[:len(text)-1] + } + + for _, l := range strings.Split(text, "\n") { + switch d.Type { + case diff.DiffInsert: + color.Green("+ %s\n", l) + case diff.DiffDelete: + color.Red("- %s\n", l) + case diff.DiffEqual: + fmt.Printf(" %s\n", l) + } + } + } +} + func getPackage() (string, error) { cwd, err := os.Getwd() if err != nil {