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

Respect submodule update=none strategy in .gitmodules #10717

Merged
merged 1 commit into from
Jun 7, 2022

Commits on Jun 7, 2022

  1. 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 <jakub@cloudflare.com>
    jsitnicki committed Jun 7, 2022
    Configuration menu
    Copy the full SHA
    26031b9 View commit details
    Browse the repository at this point in the history