question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exclusion patterns work only if processed after the inclusion ones.

See original GitHub issue

It took me quite a bit of time to figure out this one: if you have an exclusion pattern before an inclusion one, it won’t work. The reason is that match_files() processes the patterns in whatever orders they are specified:

	for pattern in patterns:
		if pattern.include is not None:
			result_files = pattern.match(all_files)
			if pattern.include:
				return_files.update(result_files)
			else:
				return_files.difference_update(result_files)
	return return_files

If the exclusion pattern is processed first, the difference_update won’t have any effect since the return_files will be empty. To fix that I separated the patterns in two lists and process the inclusion ones first:

	include_patterns, exclude_patterns = partition(patterns, lambda p: p.include)

	for pattern in include_patterns:
		result_files = pattern.match(all_files)
		return_files.update(result_files)

	for pattern in exclude_patterns:
		result_files = pattern.match(all_files)
		return_files.difference_update(result_files)
	return return_files

where partition is defined as:

def partition(data, pred):
	"""Partitions the data according to the predicate. Returns a tuple of lists (yes, no) with the partitioned elements."""
	yes, no = [], []
	for d in data:
		(yes if pred(d) else no).append(d)
	return [yes, no]

Of course you may fix this differently (for example you may “sort” the patterns such that the exclusion ones come after the include ones.

HTH

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
cpburnzcommented, Jul 18, 2021

@ftrofin @ofek

I’ve now tested this and git handles the patterns as they appear in the “.gitignore” file. It does not run inclusion patterns before exclusion patterns. I’d recommend to sort the patterns after they’re compiled. I.e.,

import pathspec
spec = pathspec.PathSpec.from_lines('gitwildmatch', ...)

# This will only work if the lines passed into `.from_lines()` is a `list` or a
# non-collection iterable which will be consumed as a `list`.
spec.patterns.sort(key=lambda p: -p.include)  

# This is more reliable.
spec.patterns = sorted(spec.patterns, key=lambda p: -p.include)  

Test 1 - git

Files:

  • .gitignore
  • a.txt
  • b.txt
  • keep.txt

.gitignore:

!keep.txt
*.txt

Files matched by git:

  • .gitignore

Test 1 - pathspec

source_files = [
	".gitignore",
	"a.txt",
	"b.txt",
	"keep.txt",
]

ignore_spec = pathspec.PathSpec.from_lines('gitwildmatch', [
	"!keep.txt",
	"*.txt",
])

remove_files = list(ignore_spec.match_files(source_files))
print(remove_files)
# ['keep.txt', 'b.txt', 'a.txt']

keep_files = sorted(set(source_files).difference(remove_files))
# ['.gitignore']

Test 2 - git

Files:

  • .gitignore
  • a.txt
  • b.txt
  • keep.txt

.gitignore:

*.txt
!keep.txt

Files matched by git:

  • .gitignore
  • keep.txt

Test 2 - pathspec

source_files = [
	".gitignore",
	"a.txt",
	"b.txt",
	"keep.txt",
]

ignore_spec = pathspec.PathSpec.from_lines('gitwildmatch', [
	"*.txt",
	"!keep.txt",
])

remove_files = list(ignore_spec.match_files(source_files))
print(remove_files)
# ['b.txt', 'a.txt']

keep_files = sorted(set(source_files).difference(remove_files))
# ['.gitignore', 'keep.txt']
0reactions
ofekcommented, Jul 7, 2021

@cpburnz Any update on this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Working with Inclusion/Exclusion Patterns
Inclusion and exclusion patterns allow you include or exclude all resources which match a defined pattern when transferring data to/from a remote server....
Read more >
How to use Include/Exclude patterns? - JFrog
Include patterns are a list of patterns to include when processing artifact requests. Only artifacts matching one of the “include patterns” ...
Read more >
The Inclusion-Exclusion Principle - CP-Algorithms
The inclusion-exclusion principle is an important combinatorial way to compute the size of a set or the probability of complex events.
Read more >
Filters/Include exclude patterns - How-to - Duplicacy Forum
If a match is not found, the path will be excluded if all patterns are include patterns, but included otherwise.
Read more >
IntelliJ equivalent of "Inclusion and Exclusion Patterns"?
No, I think it works on IDEA 10 as well; however, I'd really prefer to use inclusion rather than exclusion patterns; also, I...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found