.zpackignore
A .zpackignore at the root of the directory being packed lists what to leave
out. The ignore file itself is never packed - it describes how to build the
archive, not what the archive holds.
# vcs and dependencies.git/node_modules/
# build output, at the root only/build/
# art sources, not shipped*.psd
# os junk, at any depth.DS_StoreThumbs.dbPattern syntax
Section titled “Pattern syntax”| Pattern | Matches |
|---|---|
Thumbs.db |
That basename, at any depth |
/build |
build at the archive root only |
src/gen |
Anchored, because the pattern contains a / |
build/ |
Directories only, never a file of the same name |
*.psd |
Any run of characters within one path segment |
level-?.json |
Exactly one character |
a/**/tmp |
Any number of path segments |
!keep.png |
Un-ignores, undoing rules written above it |
# note |
A comment. Blank lines are skipped too |
Trailing whitespace is trimmed, so a stray space after a pattern does not change what it matches.
Anchoring
Section titled “Anchoring”A pattern is anchored - matched against the whole path - if it contains a
/ anywhere. Otherwise it is matched against the basename only, at any depth.
A leading / anchors without being part of the pattern:
/build/ # excludes build/ at the rootbuild/ # excludes any directory named build, at any depthGiven this tree:
Directorybuild/
- out.o
Directorysrc/
Directorybuild/
- gen.c
- Thumbs.db
- Thumbs.db
/build/ excludes build/out.o but keeps src/build/gen.c. Unanchored
Thumbs.db excludes both copies.
Wildcards
Section titled “Wildcards”* and ? stop at a /, so they never cross a directory boundary. **
crosses segments, but only when it stands as a whole segment of its own -
a**b behaves as a*b, matching git.
*.psd # art/hero.psd, excluded. art/hero.png, kept.level-?.json # level-1.json, excluded. level-22.json, kept.a/**/tmp/ # a/x/y/tmp/, excluded at any depthNegation
Section titled “Negation”Rules apply in order and the last one to match a path decides. A ! rule
therefore only undoes rules written above it:
keep/*.png!keep/keep.png # keep/drop.png excluded, keep/keep.png keptReversing those two lines keeps nothing: the broader rule would match last.
Directories are pruned, not filtered
Section titled “Directories are pruned, not filtered”A directory that matches is never descended into. .git/ costs nothing to skip
regardless of how large it is.
The consequence is worth stating plainly, because it surprises people:
Differences from .gitignore
Section titled “Differences from .gitignore”.gitignore |
zpack |
|---|---|
Character classes, [a-z] |
Not supported - a literal [ matches a literal [ |
| Nested ignore files in subdirectories | Not read - only the one at the root of the packed directory |
.gitignore files inside subdirectories are additive |
zpack has exactly one ignore file per archive |
| Unlimited rules | Capped at 1024; beyond that, pack fails with TooManyRules |
The rule cap bounds how much work matching one path can cost. If you are near it, the patterns are almost certainly collapsible.
What is always excluded
Section titled “What is always excluded”Three things never appear in an archive, no ignore file required:
.zpackignoreitself- A file whose relative path equals the output archive path, which is what
makes
zpack pack . out.zpakrepeatable - The temporary file
packbuilds into, created after the scan so it cannot appear in its own archive
Using the matcher directly
Section titled “Using the matcher directly”The pattern engine is public API, so a build script can reuse the same rules:
var ignore = try zpack.Ignore.load(gpa, io, dir, ".zpackignore");defer ignore.deinit();
if (ignore.match("art/hero.psd", false)) { // excluded}See the Ignore reference.