Skip to content

Commit

Permalink
feat: allow list of files in exclude option (#772)
Browse files Browse the repository at this point in the history
* feat: allow list of files in exclude option

* chore: add integrity test

* docs: update docs
  • Loading branch information
mrexox authored Jul 18, 2024
1 parent 2da0ca0 commit e1caf3c
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 12 deletions.
21 changes: 20 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,9 @@ pre-commit:

### `exclude`

You can provide a regular expression to exclude some files from being passed to [`run`](#run) command.
You can provide a list of filenames or a regular expression to exclude some files from being passed to [`run`](#run) command.

If you pass a list of filenames, they must contain the full path of the file from the project root.

The regular expression is matched against full paths to files in the repo,
relative to the repo root, using `/` as the directory separator on all platforms.
Expand All @@ -1280,6 +1282,23 @@ pre-commit:
run: bundle exec rubocop --force-exclusion {staged_files}
```

The same example using a list of filenames.

```yml
# lefthook.yml
pre-commit:
commands:
lint:
glob: "*.rb"
exclude:
- config/routes.rb
- config/application.rb
- spec/rails_helper.rb
run: bundle exec rubocop --force-exclusion {staged_files}
```


**Notes**

Be careful with the config file format's string quoting and escaping rules when writing regexps in it. For YAML, single quotes are often the simplest choice.
Expand Down
6 changes: 3 additions & 3 deletions internal/config/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ type Command struct {

FileTypes []string `json:"file_types,omitempty" mapstructure:"file_types" toml:"file_types,omitempty" yaml:"file_types,omitempty"`

Glob string `json:"glob,omitempty" mapstructure:"glob" toml:"glob,omitempty" yaml:",omitempty"`
Root string `json:"root,omitempty" mapstructure:"root" toml:"root,omitempty" yaml:",omitempty"`
Exclude string `json:"exclude,omitempty" mapstructure:"exclude" toml:"exclude,omitempty" yaml:",omitempty"`
Glob string `json:"glob,omitempty" mapstructure:"glob" toml:"glob,omitempty" yaml:",omitempty"`
Root string `json:"root,omitempty" mapstructure:"root" toml:"root,omitempty" yaml:",omitempty"`
Exclude interface{} `json:"exclude,omitempty" mapstructure:"exclude" toml:"exclude,omitempty" yaml:",omitempty"`

Priority int `json:"priority,omitempty" mapstructure:"priority" toml:"priority,omitempty" yaml:",omitempty"`
FailText string `json:"fail_text,omitempty" mapstructure:"fail_text" toml:"fail_text,omitempty" yaml:"fail_text,omitempty"`
Expand Down
40 changes: 32 additions & 8 deletions internal/lefthook/runner/filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,42 @@ func byGlob(vs []string, matcher string) []string {
return vsf
}

func byExclude(vs []string, matcher string) []string {
if matcher == "" {
func byExclude(vs []string, matcher interface{}) []string {
switch exclude := matcher.(type) {
case nil:
return vs
}
case string:
if len(exclude) == 0 {
return vs
}

vsf := make([]string, 0)
for _, v := range vs {
if res, _ := regexp.MatchString(matcher, v); !res {
vsf = append(vsf, v)
vsf := make([]string, 0)
for _, v := range vs {
if res, _ := regexp.MatchString(exclude, v); !res {
vsf = append(vsf, v)
}
}

return vsf
case []interface{}:
excludeNames := make(map[string]struct{}, len(exclude))
for _, name := range exclude {
excludeNames[name.(string)] = struct{}{}
}

vsf := make([]string, 0)
for _, v := range vs {
if _, excluded := excludeNames[v]; !excluded {
vsf = append(vsf, v)
}
}

return vsf
}
return vsf

log.Warn("invalid value for exclude option")

return vs
}

func byRoot(vs []string, matcher string) []string {
Expand Down
42 changes: 42 additions & 0 deletions testdata/exclude.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
exec git init
exec lefthook install
exec git config user.email "you@example.com"
exec git config user.name "Your Name"
exec git add -A
exec lefthook run -f all
stdout 'excluded.txt lefthook.yml not-excluded.txt'
exec lefthook run -f regexp
stdout 'lefthook.yml not-excluded.txt'
exec lefthook run -f array
stdout 'lefthook.yml not-excluded.txt'

-- lefthook.yml --
skip_output:
- skips
- meta
- summary
- execution_info
all:
commands:
echo:
run: echo {staged_files}

regexp:
commands:
echo:
run: echo {staged_files}
exclude: '^excluded.txt'

array:
commands:
echo:
run: echo {staged_files}
exclude:
- exclude.txt

-- not-excluded.txt --
sometext

-- excluded.txt --
somecode

0 comments on commit e1caf3c

Please sign in to comment.