Skip to content

Conversation

@torarvid
Copy link

Type of Change

Motivation and Context

As the included test demonstrates, when a folder contains a .dockerignore file with pattern to-be-ignored.txt, the file to-be-ignored.txt is still included in the build context. Check out the first commit to see this test failing.

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

@wlan0
Copy link
Contributor

wlan0 commented Nov 14, 2025

Thanks for the PR!

High‑level, I like the approach:
• read .dockerignore once per walk call
• filter the followPathsWalked entries up front
• reuse the same filtered set both for the JSON response and for the tar writer

A few details I’d like us to tighten up:

  • We don’t currently support ! negation patterns. In Docker’s .dockerignore, !foo will re‑include paths that were previously excluded. Right now a line starting with ! is treated as a literal pattern, so this will behave differently from Docker.
  • Handling of ** and leading / isn’t quite the same as Docker’s pattern matcher. In particular, patterns like **/foo are treated as two * globs rather than the “any number of directories” semantics that Docker uses, and leading / on a pattern won’t match a relative path under the context root.

It would be good to extend the matcher now so it lines up more closely with Docker’s docs or atleast call it out in the docs

Copy link
Contributor

@jglogan jglogan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you extract the two private functions you added to a dedicated type?

  • Keeps BuildFSSync more concise and easier to comprehend
  • Improves testability and reusablity.

EDIT: The specific comments I made in my review might not apply exactly after you rework for the changes Sid mentioned above, but it'd still be better to keep the ignore testing separate from the BuildFSSync implementation.

let followPaths: [String] = packet.followPaths() ?? []

// Parse .dockerignore if present
let ignorePatterns = try parseDockerignore()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve the path to the ignore file here and load the file into Data, and then create an IgnoreSpec(data)

let relPath = try url.relativeChildPath(to: contextDir)

// Check if the file should be ignored
if try shouldIgnore(relPath, patterns: ignorePatterns, isDirectory: url.hasDirectoryPath) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can become ignoreSpec.shouldIgnore(relPath:isDirectory:)?

return Array(globber.results)
}

/// Parse .dockerignore file and return list of ignore patterns
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract these two methods into IgnoreSpec.swift.

@@ -0,0 +1,209 @@
//===----------------------------------------------------------------------===//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to IgnoreSpecTests.swift

torarvid pushed a commit to torarvid/container that referenced this pull request Nov 17, 2025
Extract the .dockerignore parsing and pattern matching logic from
BuildFSSync into a dedicated IgnoreSpec type. This improves code
organization, testability, and reusability.

Changes:
- Create new IgnoreSpec.swift with IgnoreSpec type that takes Data in
  its initializer and provides shouldIgnore(relPath:isDirectory:) method
- Update BuildFSSync to load .dockerignore file data and create an
  IgnoreSpec instance
- Rename DockerignoreTests to IgnoreSpecTests
- Add unit tests for IgnoreSpec type

This addresses feedback from jglogan in PR apple#879.
@torarvid
Copy link
Author

@wlan0 @jglogan Hello 👋 I have made an attempt now at improving the PR based on your comments. I decided to just go a regex route and move away from the Globber (didn't quite understand whether that's used for other stuff and so don't understand if it's fine to just change how it works).

Also added more tests for ** and ! patterns.

Let me know what you think. (Sorry if my response time is a bit slow, I don't have that much free time these days😊)

@torarvid
Copy link
Author

Hmmm. I'm trying this on a real project, and the problem now is that it's very slow (my project has some big-but-supposed-to-be-ignored-folders, like node_modules, .mypy_cache etc.

I guess this problem might be a bit bigger? Like, the way it is now it will still walk over all files inside of node_modules/**/* and test for ignoring, which makes little sense unless you were to have !node_modules/important.txt further down in .dockerignore 🤔

@jglogan
Copy link
Contributor

jglogan commented Nov 18, 2025

Have you considered looking at how it works in moby/patternmatcher and the underlying filepath.Match() implementation in the Go library?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants