diff --git a/cmd/wksctl/profile/constants/constants.go b/cmd/wksctl/profile/constants/constants.go index 2c544873..77b0739c 100644 --- a/cmd/wksctl/profile/constants/constants.go +++ b/cmd/wksctl/profile/constants/constants.go @@ -3,4 +3,7 @@ package constants const ( AppDevAlias = "app-dev" AppDevRepoURL = "git@github.com:weaveworks/eks-quickstart-app-dev" + + // WKSctlIgnoreFilename is the ignore file recognized by wksctl + WKSctlIgnoreFilename = ".wksctlignore" ) diff --git a/cmd/wksctl/profile/enable/enable.go b/cmd/wksctl/profile/enable/enable.go index 109226dd..1819adef 100644 --- a/cmd/wksctl/profile/enable/enable.go +++ b/cmd/wksctl/profile/enable/enable.go @@ -1,8 +1,13 @@ package enable import ( + "bufio" "errors" + "fmt" + "io" + "os" "path" + "regexp" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -69,15 +74,20 @@ func profileEnableRun(params profileEnableFlags) error { if err != nil { return err } - clonePath := path.Join(params.profileDir, hostName, repoName) + profilePath := path.Join(params.profileDir, hostName, repoName) log.Info("Adding the profile to the local repository...") - err = git.SubtreeAdd(clonePath, repoURL, params.revision) + err = git.SubtreeAdd(profilePath, repoURL, params.revision) if err != nil { return err } log.Info("Added the profile to the local repository.") + // Detect and process the ignore file if found at the top most directory of the profile + if err := doIgnoreFiles(profilePath); err != nil { + return err + } + // The default behaviour is auto-commit and push if params.push { if err := git.Push(); err != nil { @@ -87,3 +97,49 @@ func profileEnableRun(params profileEnableFlags) error { return nil } + +func doIgnoreFiles(profilePath string) error { + ignoreFilePath := path.Join(profilePath, constants.WKSctlIgnoreFilename) + if _, err := os.Stat(ignoreFilePath); err == nil { + log.Infof("Ignoring files declared in %s...", constants.WKSctlIgnoreFilename) + file, err := os.Open(ignoreFilePath) + if err != nil { + return err + } + defer file.Close() + pathsToIgnores, err := parseDotIgnorefile(profilePath, file) + if err != nil { + return err + } + if err := removePathsFromGit(pathsToIgnores...); err != nil { + return err + } + log.Info("Ignored files successfully.") + } + return nil +} + +func parseDotIgnorefile(dir string, reader io.Reader) ([]string, error) { + result := []string{} + scanner := bufio.NewScanner(reader) + re := regexp.MustCompile(`(?ms)^\s*(?P[^\s#]+).*$`) + for scanner.Scan() { + groups := re.FindStringSubmatch(scanner.Text()) + if len(groups) != 2 { + continue + } + pathToIgnore := groups[1] + result = append(result, path.Join(dir, pathToIgnore)) + } + return result, nil +} + +func removePathsFromGit(paths ...string) error { + if err := git.RmRecursive(paths...); err != nil { + return err + } + if err := git.Commit(fmt.Sprintf("Ignored files declared in %s", constants.WKSctlIgnoreFilename)); err != nil { + return err + } + return nil +} diff --git a/cmd/wksctl/profile/enable/enable_test.go b/cmd/wksctl/profile/enable/enable_test.go new file mode 100644 index 00000000..4b4a07a2 --- /dev/null +++ b/cmd/wksctl/profile/enable/enable_test.go @@ -0,0 +1,45 @@ +package enable + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +const ( + ignoreFileFixture = `a +b/ + #c +#d +e +f +../g +h.. +i # this is i + j/# this is j +` +) + +func TestParseDotIgnoreFile(t *testing.T) { + r := strings.NewReader(ignoreFileFixture) + lines, err := parseDotIgnorefile("", r) + assert.NoError(t, err, "parsing ignore file should not be error") + assert.Equal(t, 8, len(lines), "ignore file entries should be 8") + // Entry: 'b/' is resolved to 'b' by path.Join() + assert.Equal(t, []string{"a", "b", "e", "f", "../g", "h..", "i", "j"}, lines) +} + +func TestParseDotIgnoreFileWithPrefix(t *testing.T) { + r := strings.NewReader(ignoreFileFixture) + lines, err := parseDotIgnorefile("profiles", r) + assert.NoError(t, err, "parsing ignore file should not be error") + assert.Equal(t, 8, len(lines), "ignore file entries should be 8") + // Note: + // - 'profiles/b/' is resolved to 'profiles/b' + // - 'profiles/../g' is resolved to 'g' + assert.Equal(t, []string{ + "profiles/a", "profiles/b", "profiles/e", + "profiles/f", "g", "profiles/h..", + "profiles/i", "profiles/j"}, lines) +} diff --git a/pkg/git/git.go b/pkg/git/git.go index 3b4b3acc..b720e3e0 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -22,8 +22,8 @@ func HasNoStagedChanges() error { return errors.Wrap(gitExec("diff", "--staged", "--exit-code"), "repository contains staged changes") } -func RmRecursive(path string) error { - return gitExec("rm", "-r", "--", path) +func RmRecursive(paths ...string) error { + return gitExec(append([]string{"rm", "-r", "--"}, paths...)...) } func AddAll(path string) error {