Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Respect submodule update=none strategy in .gitmodules
Git lets users define the default update/checkout strategy for a submodule by setting the `submodule.<name>.update` key in `.gitmodules` file. If the update strategy is `none`, the submodule will be skipped during update. It will not be fetched and checked out: 1. *foo* is a big git repo ``` /tmp $ git init foo Initialized empty Git repository in /tmp/foo/.git/ /tmp $ dd if=/dev/zero of=foo/big bs=1000M count=1 1+0 records in 1+0 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.482087 s, 2.2 GB/s /tmp $ git -C foo add big /tmp $ git -C foo commit -m 'I am big' [main (root-commit) 84fb533] I am big 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 big ``` 2. *bar* is a repo with a big submodule with `update=none` ``` /tmp $ git init bar Initialized empty Git repository in /tmp/bar/.git/ /tmp $ git -C bar submodule add file:///tmp/foo foo Cloning into '/tmp/bar/foo'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 1 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), 995.50 KiB | 338.00 KiB/s, done. /tmp $ git -C bar config --file .gitmodules submodule.foo.update none /tmp $ cat bar/.gitmodules [submodule "foo"] path = foo url = file:///tmp/foo update = none /tmp $ git -C bar commit --all -m 'I have a big submodule with update=none' [main (root-commit) 6c355ea] I have a big submodule not updated by default 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 foo ``` 3. *baz* is a clone of *bar*, notice *foo* submodule gets skipped ``` /tmp $ git clone --recurse-submodules file:///tmp/bar baz Cloning into 'baz'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), done. Submodule 'foo' (file:///tmp/foo) registered for path 'foo' Skipping submodule 'foo' /tmp $ git -C baz submodule update --init Skipping submodule 'foo' /tmp $ ``` Cargo, on the other hand, ignores the submodule update strategy set in `.gitmodules` properties when updating dependencies. Such behavior can be considered against the wish of the crate publisher. 4. *bar* is now a lib with a big submodule with update disabled ``` /tmp $ cargo init --lib bar Created library package /tmp $ git -C bar add . /tmp $ git -C bar commit -m 'I am a lib with a big submodule but update=none' [main eb07cf7] I am a lib with a big submodule but update=none 3 files changed, 18 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs /tmp $ ``` 5. *qux* depends on *bar*, notice *bar*'s submodules are fetched ``` /tmp $ cargo init qux && cd qux Created binary (application) package /tmp/qux $ echo -e '[dependencies.bar]\ngit = "file:///tmp/bar"' >> Cargo.toml /tmp/qux $ time cargo update Updating git repository `file:///tmp/bar` Updating git submodule `file:///tmp/foo` real 0m22.182s user 0m20.402s sys 0m1.714s /tmp/qux $ ``` Fix it by checking if a Git repository submodule should be updated when cargo processes dependencies. 6. With the change applied, submodules with `update=none` are skipped ``` /tmp/qux $ cargo cache -a > /dev/null /tmp/qux $ time ~/src/cargo/target/debug/cargo update Updating git repository `file:///tmp/bar` Skipping git submodule `file:///tmp/foo` real 0m0.029s user 0m0.021s sys 0m0.008s /tmp/qux $ ``` Fixes rust-lang#4247. Signed-off-by: Jakub Sitnicki <[email protected]>
- Loading branch information