Skip to content

Commit

Permalink
feat: add file/should/be_gitignored expression
Browse files Browse the repository at this point in the history
  • Loading branch information
omissis committed Aug 11, 2022
1 parent 98e115e commit 34b412d
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if a file:
- [x] content matches regex
- [ ] content matches template
- [x] content contains a value
- [ ] is gitignored
- [x] is gitignored
- [ ] is gitcrypted
- [ ] has specific permissions

Expand Down
52 changes: 52 additions & 0 deletions internal/arch/file/should/be_gitignored.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package should

import (
"fmt"
"goarkitect/internal/arch/rule"
"os/exec"
"path/filepath"
)

func BeGitignored(opts ...Option) *gitIgnoredExpression {
expr := &gitIgnoredExpression{}

for _, opt := range opts {
opt.apply(&expr.options)
}

return expr
}

type gitIgnoredExpression struct {
baseExpression
}

func (e gitIgnoredExpression) Evaluate(rb rule.Builder) []rule.Violation {
return e.evaluate(rb, e.doEvaluate, e.getViolation)
}

func (e gitIgnoredExpression) doEvaluate(rb rule.Builder, filePath string) bool {
cmd := exec.Command("git", "check-ignore", "-q", filePath)
if err := cmd.Run(); err != nil {
switch err.(type) {
case *exec.ExitError:
return err.(*exec.ExitError).ExitCode() != 0
default:
panic(err)
}
}

return false
}

func (e gitIgnoredExpression) getViolation(filePath string) rule.Violation {
format := "file '%s' is not gitignored"

if e.options.negated {
format = "file '%s' is gitignored"
}

return rule.NewViolation(
fmt.Sprintf(format, filepath.Base(filePath)),
)
}
69 changes: 69 additions & 0 deletions internal/arch/file/should/be_gitignored_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package should_test

import (
"goarkitect/internal/arch/file"
"goarkitect/internal/arch/file/should"
"goarkitect/internal/arch/rule"
"os"
"path/filepath"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)

func Test_BeGitignored(t *testing.T) {
basePath, err := os.Getwd()
if err != nil {
t.Fatal(err)
}

testCases := []struct {
desc string
ruleBuilder *file.RuleBuilder
options []should.Option
want []rule.Violation
}{
{
desc: "file 'ignored.txt' should be gitignored",
ruleBuilder: file.One(filepath.Join(basePath, "test/ignored.txt")),
want: nil,
},
{
desc: "file 'not_ignored.txt' should be gitignored",
ruleBuilder: file.One(filepath.Join(basePath, "test/not_ignored.txt")),
want: []rule.Violation{
rule.NewViolation("file 'not_ignored.txt' is not gitignored"),
},
},
{
desc: "negated: file 'ignored.txt' should not be gitignored",
ruleBuilder: file.One(filepath.Join(basePath, "test/ignored.txt")),
options: []should.Option{
should.Negated{},
},
want: []rule.Violation{
rule.NewViolation("file 'ignored.txt' is gitignored"),
},
},
{
desc: "negated: file 'not_ignored.txt' should not be gitignored",
ruleBuilder: file.One(filepath.Join(basePath, "test/not_ignored.txt")),
options: []should.Option{
should.Negated{},
},
want: nil,
},
}

for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
hcm := should.BeGitignored(tC.options...)
got := hcm.Evaluate(tC.ruleBuilder)

if !cmp.Equal(got, tC.want, cmp.AllowUnexported(rule.Violation{}), cmpopts.EquateEmpty()) {
t.Errorf("want = %+v, got = %+v", tC.want, got)
}
})
}
}
1 change: 1 addition & 0 deletions internal/arch/file/should/test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignored.txt

0 comments on commit 34b412d

Please # to comment.