rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.55k stars 2.38k forks source link

instead of writing a `.gitignore` with `/target` -- output a `.gitignore` with `*` *inside* `target/` #11548

Open asottile opened 1 year ago

asottile commented 1 year ago

Problem

currently cargo init helpfully writes out a .gitignore with the following contents:

/target

this ~generally means that any rust project now needs to have this /target entry in .gitignore

instead of needing this in .gitignore, one can create a self-ignoring directory by writing a .gitignore with the contents * inside of it. this is (for example) what virtualenv does:

$ virtualenv venv >& /dev/null
$ cat venv/.gitignore
# created by virtualenv automatically
*

this would remove the need for everyone having /target in their gitignore and instead have it be automatic!

Proposed Solution

the proposal is to create a .gitignore with * in the target directory upon creation and phase out the top-level .gitignore's /target entry

Notes

No response

weihanglo commented 1 year ago

This looks pretty interesting! Thanks for your proposal.

There are several things needs to consider. One is backward compatibility. I believe it is rare that a user commits stuff under target/ directory. It may be fine to completely ignore target dir, although I am not 120% sure there is no one what to commit target/cargo-timings for further build pipeline investigation. (Cargo should provide a better way to store such information 🤪)

Cargo supports various kinds of VCS, e.g. Git, Mecurial, Pijul, and Fossil. We don't need to do it all at once, as 99% of Rust projects choose Git. Still, we can perform more researches on how other VCS works.

Going further, “which VCS ignore file should be generated” becomes a question. Is it a good practice for Cargo to check VCS information for each run of cargo build? Could we store VCS info somewhere to avoid that cost? Or just generate 4 kinds of ignore files when every time Cargo recreates target?

The idea is cool anyway. Thank you again.

LunarLambda commented 11 months ago

Writing 4 tiny (single line) files should not be a significant cost compared to any kind of average cargo compile, even hello world.

Meson for example generates ones for git and mercurial only, but others wouldn't be difficult, assuming they provide glob support. However, it only generates them once. Cargo could do the same if cargo clean didn't delete target/ entirely, but left the VCS ignores

mathstuf commented 11 months ago

Please keep /target in the ignore as putting in the directory does not support target-as-symlink.

LunarLambda commented 11 months ago

In what case would you need target to be a symlink?

mathstuf commented 11 months ago

I keep my build artifacts on a separate partition to keep my main one from croaking when it gets too full. It also makes it easy to keep them out of backups by just ignoring where all build artifacts live.

LunarLambda commented 11 months ago

Can't the target directory be controlled via a config option or environment variable?

Alternatively, a bind mount is also possible.

I don't know how the cargo team sees it, but this seems like a fairly niche use case, it feels like the usability improvement would be greater in the general case. Besides, you can still have an additional .gitignore file in the project directory itself, it just wouldn't be there by default (just as target as a symlink isn't there by default, so I think this could be easily added to whatever setup script you may have)

mathstuf commented 11 months ago

Can't the target directory be controlled via a config option or environment variable?

Can it include variables? Say, $buildroot/$(basename ../..)/target? If not..I'm not sure how one is supposed to make sure all tools agree on this path in such a way. A symlink Just Works and everything agrees about where it goes.

Alternatively, a bind mount is also possible.

I don't think involving root into any cargo-using project I want to build is scalable.

Besides, you can still have an additional .gitignore file in the project directory itself, it just wouldn't be there by default

That doesn't help with projects I contribute to (I've made quite a few PRs removing the trailing slash in projects' .gitignore after fixing the template here).