Skip to content

Commit

Permalink
core: supports .add({pattern, mark})
Browse files Browse the repository at this point in the history
test: fixes tests and coverage
  • Loading branch information
kaelzhang committed Dec 19, 2024
1 parent da6e194 commit 5d278de
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 40 deletions.
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,11 @@ ig.filter(['.abc\\a.js', '.abc\\d\\e.js'])

## .add(pattern: string | Ignore): this
## .add(patterns: Array<string | Ignore>): this
## .add({pattern: string, mark?: string}): this

- **pattern** `String | Ignore` An ignore pattern string, or the `Ignore` instance
- **patterns** `Array<String | Ignore>` Array of ignore patterns.
- **pattern** `string | Ignore` An ignore pattern string, or the `Ignore` instance
- **patterns** `Array<string | Ignore>` Array of ignore patterns.
- **mark?** `string` Pattern mark, which is used to associate the pattern with a certain marker, such as the line no of the `.gitignore` file. Actually it could be an arbitrary string and is optional.

Adds a rule or several rules to the current manager.

Expand Down Expand Up @@ -284,17 +286,50 @@ interface TestResult {
ignored: boolean
// true if the `pathname` is finally unignored by some negative pattern
unignored: boolean
// The `IgnoreRule` which ignores the pathname
rule?: IgnoreRule
}

interface IgnoreRule {
// The original pattern
pattern: string
// Whether the pattern is a negative pattern
negative: boolean
// Which is used for other packages to build things upon `node-ignore`
mark?: string
}
```

- `{ignored: true, unignored: false}`: the `pathname` is ignored
- `{ignored: false, unignored: true}`: the `pathname` is unignored
- `{ignored: false, unignored: false}`: the `pathname` is never matched by any ignore rules.

## .checkIgnore(pattern) since 6.1.0
## .checkIgnore(pattern) since 7.0.0

> new in 6.1.0
Debug gitignore / exclude files, which is equivalent to `git check-ignore -v`. Usually this method is used for other packages to implement the function of `git check-ignore -v` upon `node-ignore`

Returns `TestResult`

```js
ig.add({
pattern: 'foo/*',
mark: '60'
})

const {
ignored,
rule
} = checkIgnore('foo/')

if (ignored) {
console.log(`.gitignore:${result}:${rule.mark}:${rule.pattern} foo/`)
}

// .gitignore:60:foo/* foo/
```

Please pay attention that this method does not have a strong built-in cache mechanism.

The purpose of introducing this method is to make it possible to implement the `git check-ignore` command in JavaScript based on `node-ignore`.
Expand Down
38 changes: 23 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,17 +361,21 @@ const checkPattern = pattern => pattern
// > A line starting with # serves as a comment.
&& pattern.indexOf('#') !== 0

const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF)
const splitPattern = pattern => pattern
.split(REGEX_SPLITALL_CRLF)
.filter(Boolean)

class IgnoreRule {
constructor (
pattern,
mark,
body,
ignoreCase,
negative,
prefix
) {
this.pattern = pattern
this.mark = mark
this.negative = negative

define(this, 'body', body)
Expand Down Expand Up @@ -415,7 +419,10 @@ class IgnoreRule {
}
}

const createRule = (pattern, ignoreCase) => {
const createRule = ({
pattern,
mark
}, ignoreCase) => {
let negative = false
let body = pattern

Expand All @@ -437,6 +444,7 @@ const createRule = (pattern, ignoreCase) => {

return new IgnoreRule(
pattern,
mark,
body,
ignoreCase,
negative,
Expand All @@ -453,18 +461,18 @@ class RuleManager {
_add (pattern) {
// #32
if (pattern && pattern[KEY_IGNORE]) {
this._rules = this._rules.concat(
pattern._rules._rules
||
// Compatible with the old version
/* istanbul ignore next */
pattern._rules
)
this._rules = this._rules.concat(pattern._rules._rules)
this._added = true
return
}

if (checkPattern(pattern)) {
if (isString(pattern)) {
pattern = {
pattern
}
}

if (checkPattern(pattern.pattern)) {
const rule = createRule(pattern, this._ignoreCase)
this._added = true
this._rules.push(rule)
Expand Down Expand Up @@ -638,7 +646,7 @@ class Ignore {
// If the path doest not end with a slash, `.ignores()` is much equivalent
// to `git check-ignore`
if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
return this.ignores(path)
return this.test(path)
}

const slices = path.split(SLASH).filter(Boolean)
Expand All @@ -647,17 +655,17 @@ class Ignore {
if (slices.length) {
const parent = this._t(
slices.join(SLASH) + SLASH,
this._ignoreCache,
false,
this._testCache,
true,
slices
)

if (parent.ignored) {
return true
return parent
}
}

return this._rules.test(path, false, MODE_CHECK_IGNORE).ignored
return this._rules.test(path, false, MODE_CHECK_IGNORE)
}

_t (
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/cases.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const cases = [
'#77: directory ending with / not always correctly ignored',
[
'c/*',
'foo/bar/*'
{pattern: 'foo/bar/*'}
],
{
'c/': 1,
Expand Down
7 changes: 6 additions & 1 deletion test/git-check-ignore.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@ const debugSpawn = (...args) => {
debug(out.output.toString())
}

const mapObjectRule = rule =>
typeof rule === 'string'
? rule
: rule.pattern

const getNativeGitIgnoreResults = (rules, paths) => {
const dir = createUniqueTmp()

const gitignore = typeof rules === 'string'
? rules
: rules.join('\n')
: rules.map(mapObjectRule).join('\n')

touch(dir, '.gitignore', gitignore)

Expand Down
51 changes: 31 additions & 20 deletions test/ignore.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,40 @@ cases(({
t.end()
})

const run_ignores = name => {
tt(`.${name}(path): ${description}`, t => {
const ig = ignore().addPattern(patterns)

Object.keys(paths_object).forEach(path => {
const should_ignore = !!paths_object[path]
const not = should_ignore ? '' : 'not '

t.equal(
ig[name](path),
should_ignore,
`path: "${path}" should ${not}be ignored`
)
})
t.end()
})
}

check('IGNORE_ONLY_IGNORES', 'ignores')
&& run_ignores('ignores')
&& tt(`.ignores(path): ${description}`, t => {
const ig = ignore().addPattern(patterns)

Object.keys(paths_object).forEach(path => {
const should_ignore = !!paths_object[path]
const not = should_ignore ? '' : 'not '

t.equal(
ig.ignores(path),
should_ignore,
`path: "${path}" should ${not}be ignored`
)
})
t.end()
})

check('IGNORE_ONLY_CHECK_IGNORE', 'checkIgnore')
&& run_ignores('checkIgnore')
&& tt(`.checkIgnore(path): ${description}`, t => {
const ig = ignore().addPattern(patterns)

Object.keys(paths_object).forEach(path => {
const should_ignore = !!paths_object[path]
const not = should_ignore ? '' : 'not '
const {ignored} = ig.checkIgnore(path)

t.equal(
ignored,
should_ignore,
`path: "${path}" should ${not}be ignored`
)
})
t.end()
})

if (!SHOULD_TEST_WINDOWS) {
return
Expand Down

0 comments on commit 5d278de

Please sign in to comment.