Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --pants-use-gitignore option #9310

Merged
merged 9 commits into from
Apr 10, 2020
Merged

Conversation

gshuflin
Copy link
Contributor

@gshuflin gshuflin commented Mar 16, 2020

Problem

Cf. issue #5682, we would like pants to pay attention to a top-level .gitignore filee in a pants-controlled repository if the user passes in a --pants-gitignore flag.

Solution

Pants already uses the Rust ignore crate to handle explicit ignore strings passed in the command line, so we can modify this code to also read .gitignore files when we try to do a file access, read the lines contained therein, and use that to decide whether a path should be ignored or not.

Copy link
Sponsor Member

@stuhood stuhood left a comment

Choose a reason for hiding this comment

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

Thanks Greg! As discussed offline, this would be significantly simplified by only supporting gitignore files at the root of the repository, and I think that that would be a reasonable restriction for the near future.

.into_iter()
.map(|(file_text, path)| {
let mut builder = GitignoreBuilder::new(&root);
for line in file_text.lines() {
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Can use the GitignoreBuilder::add method, which adds the entire content of a .gitignore file: https://docs.rs/ignore/0.4.12/ignore/gitignore/struct.GitignoreBuilder.html#method.add

@gshuflin gshuflin marked this pull request as ready for review March 17, 2020 08:52
@gshuflin
Copy link
Contributor Author

Thanks Greg! As discussed offline, this would be significantly simplified by only supporting gitignore files at the root of the repository, and I think that that would be a reasonable restriction for the near future.

Yup, that probably would've been simpler :) That said, toolchain cares about supporting more complicated .gitignore setups than just a single .gitignore in the root, and as of this update to the PR I believe I have a commit that does the right things with nested .gitignore files.

Copy link
Contributor

@Eric-Arellano Eric-Arellano left a comment

Choose a reason for hiding this comment

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

Neat!

We don't yet have a way to override a gitignore, do we? I wonder if there's a use case for "I want to use 99% of my gitignore files, except for this one thing." Probably premature optimization to handle that now, so long as we have a path forward to add this in the future.

Comment on lines 234 to 269
// TODO: Errors in initialization should definitely be exposed as python
// exceptions, rather than as panics.
Copy link
Contributor

Choose a reason for hiding this comment

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

I imagine we want to preserve this comment by moving it up to the let vfs clause.

@@ -538,9 +538,11 @@ impl Snapshot {
future::result(digest_hint.ok_or_else(|| "No digest hint provided.".to_string()))
.and_then(move |digest| Snapshot::from_digest(store, digest, workunit_store))
.or_else(|_| {
let use_gitignore = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Iirc, this is only used by V1 code? V2 code that uses Snapshots will use Gitignore?

@@ -687,7 +736,40 @@ impl PosixFS {
}

pub fn is_ignored(&self, stat: &Stat) -> bool {
self.ignore.is_ignored(stat)
println!("Are we actually invoking is_ignored? Stat: {:?}", stat);
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover, I think.

@@ -495,6 +536,7 @@ impl PathGlobs {
}
}
let include = PathGlob::spread_filespecs(include_globs.as_slice())?;
//TODO edited here
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover

@@ -433,6 +433,14 @@ def register_bootstrap_options(cls, register):
"Patterns use the gitignore syntax (https://git-scm.com/docs/gitignore). "
"The `--pants-distdir` and `--pants-workdir` locations are inherently ignored.",
)
register(
"--pants-gitignore",
Copy link
Contributor

Choose a reason for hiding this comment

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

I recommend --pants-use-gitignore or even --pants-use-gitignores. --pants-gitignore made me think that this would be a list of file paths to the gitignores you want to use.

Copy link
Member

Choose a reason for hiding this comment

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

in that vein prefixing with --pants seems redundant. why not just --use-gitignore

Copy link
Member

Choose a reason for hiding this comment

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

I guess to be consistent with --pants-ignore makes sense...we don't want to add more mental load remembering option scopes than we have to.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, Henry's comment makes me think we should use --pants-ignore-use-gitignore. It's horribly verbose, but very explicitly expresses how the two options relate.

I'm not concerned about verbosity because this only gets set one time in a pants.toml and will usually never be thought of again. I think we want to optimize for clarity over verbosity here.

"--pants-gitignore",
advanced=True,
type=bool,
default=False,
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the rationale for defaulting to False?

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

+1 .. should default to on, assuming it works in the absence of a .gitignore file.

@@ -254,7 +254,7 @@ python_library(

python_library(
name='console',
sources=['console.py'],
sources=['console.py', 'console2.py'],
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover?

/native_engine.so
console.py
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover?

.gitignore Outdated
@@ -1,3 +1,4 @@
console2.py
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover?

@stuhood
Copy link
Sponsor Member

stuhood commented Mar 18, 2020

We don't yet have a way to override a gitignore, do we? I wonder if there's a use case for "I want to use 99% of my gitignore files, except for this one thing." Probably premature optimization to handle that now, so long as we have a path forward to add this in the future.

We do support that: see the linked ticket, assuming that the gitignore is applied "before" the literals passed to --pants-ignore.

Copy link
Sponsor Member

@stuhood stuhood left a comment

Choose a reason for hiding this comment

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

I'm about 98% sure that the recursive upward parsing of .gitignore files will be a performance bottleneck: assuming so, I see two options:

  1. do the simpler thing, and only support the root .gitignore (for now)
  2. incorporate looking for .gitignore files directly into scandir_sync calls, and propagate ignore information down the tree of calls

@@ -687,7 +736,40 @@ impl PosixFS {
}

pub fn is_ignored(&self, stat: &Stat) -> bool {
self.ignore.is_ignored(stat)
println!("Are we actually invoking is_ignored? Stat: {:?}", stat);
if self.heed_gitignore_files {
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

This method is going to be called for every path that is matched or walked, so I don't think that re-parsing the git-ignore in each case is going to be viable from a performance perspective.

src/rust/engine/fs/src/lib.rs Outdated Show resolved Hide resolved
@gshuflin gshuflin changed the title Add --pants-gitignore option Add --pants-use-gitignore option Mar 30, 2020
@gshuflin gshuflin force-pushed the gitignore2 branch 2 times, most recently from 2f71c6b to 71a107f Compare March 31, 2020 23:09
Copy link
Sponsor Member

@stuhood stuhood left a comment

Choose a reason for hiding this comment

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

Thanks! Just nits.

"--pants-gitignore",
advanced=True,
type=bool,
default=False,
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

+1 .. should default to on, assuming it works in the absence of a .gitignore file.

type=bool,
default=False,
help="Make use of .gitignore files when determining whether to ignore filesystem "
"operations performed by pants. This may be used together with `--pants-ignore`.",
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

This should indicate that the gitignore is prepended to --pants-ignore. The other option should possibly also reference this one, and explain how you can exclude things (see the comments on the ticket).

Also, it looks like this will only respect the root .gitignore file (which I think is totally reasonable for now). Should mention that here and/or link to a followup ticket.

@gshuflin gshuflin force-pushed the gitignore2 branch 7 times, most recently from f0ff089 to 13c1a56 Compare April 8, 2020 00:40
"specified here apply after rules specified in a .gitignore file.",
)
register(
"--pants-use-gitignore",
Copy link
Contributor

Choose a reason for hiding this comment

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

Bump that I recommend --pants-ignore-use-gitignore for a consistent namespace with --pants-ignore. It's verbose, but this is an advanced option that will almost never actually be changed, and when it is, only by one Pants admin.

I think the namespace consistency is worth the verbosity.

@gshuflin gshuflin force-pushed the gitignore2 branch 5 times, most recently from 5a55877 to ee8abe6 Compare April 10, 2020 00:24
@gshuflin gshuflin force-pushed the gitignore2 branch 4 times, most recently from 7d87b16 to 21b06f1 Compare April 10, 2020 04:03
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
and start threading option through to the engine

[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
[ci skip-jvm-tests]  # No JVM changes made.

[ci skip-jvm-tests]  # No JVM changes made.

[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.

# Delete this line to force CI to run the JVM tests.
[ci skip-jvm-tests]  # No JVM changes made.
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.

None yet

4 participants