Skip to content
This repository has been archived by the owner on Jul 18, 2022. It is now read-only.

Commit

Permalink
[#3] Add --init option to dry-run for first executions
Browse files Browse the repository at this point in the history
  • Loading branch information
Florent Biville committed Oct 9, 2018
1 parent 9710700 commit 3848610
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.idea
/vendor
/header
/headache
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Golang header management

`header` manages license headers of Go files.
`headache` manages license headers of Go files.

## Example

By default, `header` looks for a file named `license.json` in the current directory:
By default, `headache` looks for a file named `license.json` in the current directory:

```json
{
Expand Down Expand Up @@ -57,25 +57,40 @@ By default, a file named `license.json` must be present in the current directory

Alternatively, the configuration file can be explicitly provided:
```shell
$ go get -u github.com/fbiville/header
$ $(GOBIN)/header --configuration /path/to/configuration.json
$ go get -u github.com/fbiville/headache
$ $(GOBIN)/headache --configuration /path/to/configuration.json
```

All the examples below support that option.

## First run

Normal dry-run/run executions detect only recent changes, based on the versioning
configuration.

When you need to run the first time, you will have to run:
```shell
$ go get -u github.com/fbiville/headache
$ $(GOBIN)/headache --dry-run --init
```

And follow the steps just below to read, possibly edit and reinject
the generated dump file.

## Dry run

All you have to do then is to simulate the run:
```shell
$ go get -u github.com/fbiville/header
$ $(GOBIN)/header --dry-run
$ go get -u github.com/fbiville/headache
$ $(GOBIN)/headache --dry-run
```

The command will output the file in which the actual updated file content are appended to.
The command will output the file in which the actual diff summary is appended to.

For instance:
```
See dry-run result in file printed below:
/path/to/header-dry-runXXX
/path/to/headache-dry-runXXX
```

The dump file follows this structure:
Expand All @@ -96,7 +111,7 @@ colored diff 2

If you want to see the dump contents, you can run:
```shell
$ less -r /path/to/header-dry-runXXX
$ less -r /path/to/headache-dry-runXXX
```


Expand All @@ -106,7 +121,7 @@ If you want to get a list of the Go files possibly* changed the future
execution, you can run something like:

```
$ ./header --dry-run | tail -n 1 | xargs cat | grep '^file:.*\.go' | sed s/file:// | sort
$ ./headache --dry-run | tail -n 1 | xargs cat | grep '^file:.*\.go' | sed s/file:// | sort
```

_\* the execution may result in no changes at all, or rather, the new written content
Expand All @@ -122,17 +137,17 @@ for more information).
To exclude files from being unnecessarily updated, locate the corresponding line, prefixed by `file:`,
followed by the file name and replace `file:` by `xfile:`.

Then, the modified dump file can be fed back to `header`, as described just below.
Then, the modified dump file can be fed back to `headache`, as described just below.

## Run

### From dry-run dump
Once you have successfully run `header --dry-run` and
Once you have successfully run `headache --dry-run` and
possibly edited the dump file (see above to see how), all you have to do then is to run:

```shell
$ go get -u github.com/fbiville/header --dump-file /path/to/header-dry-runXXX
$ $(GOBIN)/header
$ go get -u github.com/fbiville/headache --dump-file /path/to/headache-dry-runXXX
$ $(GOBIN)/headache
```

This will update only the files for which names are prefixed by `file:`.
Expand All @@ -141,14 +156,14 @@ This will update only the files for which names are prefixed by `file:`.

All you have to do then is to run:
```shell
$ go get -u github.com/fbiville/header
$ $(GOBIN)/header
$ go get -u github.com/fbiville/headache
$ $(GOBIN)/headache
```


## Unsupported

`header` currently does **not** support text changes other than:
`headache` currently does **not** support text changes other than:

* parameter value updates
* comment style changes
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ set -e
dep ensure
rm mocks/*.go || true && go get github.com/vektra/mockery/.../ && mockery -output mocks -dir versioning -name Vcs
go build ./...
go clean -testcache && go test ./...
go clean -testcache && go test -v ./...
rm header 2> /dev/null || true && go build
45 changes: 42 additions & 3 deletions core/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ package core
import (
"bufio"
"fmt"
. "github.com/fbiville/header/helper"
"github.com/fbiville/header/versioning"
. "github.com/fbiville/headache/helper"
"github.com/fbiville/headache/versioning"
"github.com/mattn/go-zglob"
tpl "html/template"
"io"
"io/ioutil"
Expand Down Expand Up @@ -53,8 +54,13 @@ const (
DryRunMode ExecutionMode = iota
RegularRunMode
RunFromFilesMode
DryRunInitMode
)

func (mode ExecutionMode) IsDryRun() bool {
return mode == DryRunInitMode || mode == DryRunMode
}

func ParseConfiguration(config Configuration, executionMode ExecutionMode, dumpFile *string) (*configuration, error) {
return parseConfiguration(config, executionMode, dumpFile, versioning.Git{}, versioning.GetVcsChanges)
}
Expand Down Expand Up @@ -89,6 +95,15 @@ func parseConfiguration(config Configuration,
if err != nil {
return nil, err
}
case DryRunInitMode:
rawChanges, err := matchFiles(config.Includes, config.Excludes)
if err != nil {
return nil, err
}
changes, err = versioning.AugmentWithMetadata(vcs, rawChanges, "")
if err != nil {
return nil, err
}
}

return &configuration{
Expand All @@ -97,6 +112,7 @@ func parseConfiguration(config Configuration,
vcsChanges: changes,
}, nil
}

func filterFiles(changes []versioning.FileChange, includes []string, excludes []string) []versioning.FileChange {
result := make([]versioning.FileChange, 0)
for _, change := range changes {
Expand All @@ -107,8 +123,31 @@ func filterFiles(changes []versioning.FileChange, includes []string, excludes []
return result
}

func matchFiles(includes []string, excludes []string) ([]versioning.FileChange, error) {
result := make([]versioning.FileChange, 0)
for _, includePattern := range includes {
matches, err := zglob.Glob(includePattern)
if err != nil {
return nil, err
}
for _, matchedPath := range matches {
if !isExcluded(matchedPath, excludes) {
result = append(result, versioning.FileChange{
Path: matchedPath,
})
}
}

}
return result, nil
}

func match(path string, includes []string, excludes []string) bool {
return IsFile(path) && Match(path, includes) && !Match(path, excludes)
return Match(path, includes) && !isExcluded(path, excludes)
}

func isExcluded(path string, excludes []string) bool {
return !IsFile(path) || Match(path, excludes)
}

type templateResult struct {
Expand Down
43 changes: 41 additions & 2 deletions core/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
package core

import (
"github.com/fbiville/header/mocks"
. "github.com/fbiville/header/versioning"
"github.com/fbiville/headache/mocks"
. "github.com/fbiville/headache/versioning"
"github.com/golang/mock/gomock"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/mock"
"testing"
)

Expand Down Expand Up @@ -153,3 +154,41 @@ func TestFailOnReservedYearParameter(t *testing.T) {
I.Expect(err).To(MatchError("Year is a reserved parameter and is automatically computed.\n" +
"Please remove it from your configuration"))
}

func TestInitDryRunMode(t *testing.T) {
I := NewGomegaWithT(t)
controller := gomock.NewController(t)
defer controller.Finish()
vcs = new(mocks.Vcs)
vcsMock := vcs.(*mocks.Vcs)
vcsMock.On("Log", mock.AnythingOfType("[]string")).Return("", nil)
inputConfig := Configuration{
HeaderFile: "../fixtures/short-license.txt",
CommentStyle: "SlashStar",
Includes: []string{"../fixtures/*world.txt"},
Excludes: []string{},
TemplateData: map[string]string{}}

configuration, err := parseConfiguration(inputConfig,
DryRunInitMode,
nil,
vcs,
func(Vcs, string, string, bool) ([]FileChange, error) { panic("nope!") })

I.Expect(err).To(BeNil())
changes := paths(configuration.vcsChanges)
I.Expect(len(changes)).To(Equal(3))
I.Expect(changes).To(ContainElement("../fixtures/hello_world.txt"))
I.Expect(changes).To(ContainElement("../fixtures/hello_ignored_world.txt"))
I.Expect(changes).To(ContainElement("../fixtures/bonjour_world.txt"))
}

func paths(changes []FileChange) []string {
result := make([]string, len(changes))
for i, change := range changes {
result[i] = change.Path
}
return result
}


4 changes: 2 additions & 2 deletions core/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package core
import (
"bufio"
"fmt"
"github.com/fbiville/header/versioning"
"github.com/fbiville/headache/versioning"
"github.com/sergi/go-diff/diffmatchpatch"
tpl "html/template"
"io"
Expand All @@ -32,7 +32,7 @@ import (
type VcsChangeGetter func(versioning.Vcs, string, string) (error, []versioning.FileChange)

func DryRun(config *configuration) (string, error) {
file, err := ioutil.TempFile("", "header-dry-run")
file, err := ioutil.TempFile("", "headache-dry-run")
if err != nil {
return "", err
}
Expand Down
2 changes: 1 addition & 1 deletion core/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package core

import (
"github.com/fbiville/header/versioning"
"github.com/fbiville/headache/versioning"
. "github.com/onsi/gomega"
"io/ioutil"
"regexp"
Expand Down
15 changes: 12 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,33 @@ import (
"encoding/json"
"flag"
"fmt"
. "github.com/fbiville/header/core"
. "github.com/fbiville/headache/core"
"io/ioutil"
"os"
)

func main() {
configFile := flag.String("configuration", "license.json", "Path to configuration file")
dryRun := flag.Bool("dry-run", false, "Dumps the execution to a file instead of altering the sources")
init := flag.Bool("init", false,
"Includes all files matching includes/excludes pattern instead of detecting VCS changes (dry-run mode only)")
dumpFile := flag.String("dump-file", "", "Path to the dry-run dump")

flag.Parse()

if *dumpFile != "" && *dryRun {
panic("cannot simultaneously use --dump-file and --dry-run")
}
if *init && !*dryRun {
panic("cannot use --init without --dry-run")
}
executionMode := RegularRunMode
if *dryRun {
executionMode = DryRunMode
if *init {
executionMode = DryRunInitMode
} else {
executionMode = DryRunMode
}
} else if *dumpFile != "" {
executionMode = RunFromFilesMode
}
Expand All @@ -47,7 +56,7 @@ func main() {
if err != nil {
panic(err)
}
if executionMode == DryRunMode {
if executionMode.IsDryRun() {
file, err := DryRun(configuration)
displayDryRunResult(file, err)
} else {
Expand Down
2 changes: 1 addition & 1 deletion versioning/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package versioning

import (
"fmt"
. "github.com/fbiville/header/helper"
. "github.com/fbiville/headache/helper"
"os/exec"
"strings"
)
Expand Down
2 changes: 1 addition & 1 deletion versioning/vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package versioning

import (
"fmt"
. "github.com/fbiville/header/helper"
. "github.com/fbiville/headache/helper"
"strconv"
. "strings"
"time"
Expand Down
2 changes: 1 addition & 1 deletion versioning/vcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package versioning

import (
"github.com/fbiville/header/mocks"
"github.com/fbiville/headache/mocks"
"github.com/golang/mock/gomock"
. "github.com/onsi/gomega"
"testing"
Expand Down

0 comments on commit 3848610

Please sign in to comment.