fabacab / git-archive-all.sh

A bash shell script wrapper for git-archive that archives a git superproject and its submodules, if it has any.
214 stars 86 forks source link

Store exact submodule commit for `--treeish` #42

Open KSR-Yasuda opened 8 months ago

KSR-Yasuda commented 8 months ago

Fix for #30.

For the target main repository commit, check the bound submodule commit by git ls-tree.

KSR-Yasuda commented 8 months ago

Although, there still exist some other issues:

  1. [ ] not working if submodule structure is different between the current worktree and the target --treeish commit (e.g. submodules added, removed, or path changed)
    • Since it searches submodules by git submodule status for the current worktree. I have no idea to fix this without git checkout the target commit.
  2. [x] probably not supporting sub-submodules
KSR-Yasuda commented 8 months ago
  1. probably not supporting sub-submodules

It has failed to check sub-submodule hash by git ls-tree.

Instead, git submodule --recursive --cached may work.

KSR-Yasuda commented 8 months ago

Test repository prepare script: testinit.sh

This creates repos that has submodules recursively:

a/                                  # -> a.git
|-- a.txt
`-- b/                              # -> b.git
    |-- b.txt
    `-- c/                          # -> c.git
        |-- c.txt
        `-- d/                      # -> d.git
            `-- d.txt

Each repos are created to have commits as below:

% git -C a log --oneline
f44f622 (HEAD -> master, origin/master) a2      # Add one more line into `a.txt`
abafa99 submodule b                             # Add a submodule, that points to the one-line commit
e278ee0 a                                       # One line in `a.txt`
e513e03 Initial commit

Each repos' HEAD is on X2 (2 lines in text) commit after the script called, but pointed to X (1 line in text) commit.

So, expected archive would be as below:

% git -C a archive-all --format tar.gz --prefix a/ -t @ ../test.tar.gz
% tar -tvf test.tar.gz
drwxrwxr-x root/root         0 2024-02-08 11:04 a/
-rw-rw-r-- root/root        80 2024-02-08 11:04 a/.gitmodules
-rw-rw-r-- root/root         4 2024-02-08 11:04 a/a.txt                 # Top repo is pointing to the commit `a2`
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/
-rw-rw-r-- root/root        80 2024-02-08 11:04 a/b/.gitmodules
-rw-rw-r-- root/root         2 2024-02-08 11:04 a/b/b.txt               # The workdir is the commit `b2`, though, top repo mean it to be the commit `b`
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/c/
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/c/
-rw-rw-r-- root/root        80 2024-02-08 11:04 a/b/c/.gitmodules
-rw-rw-r-- root/root         2 2024-02-08 11:04 a/b/c/c.txt             # The workdir is the commit `c2`, though, top repo mean it to be the commit `c`
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/c/d/
drwxrwxr-x root/root         0 2024-02-08 11:04 a/b/c/d/
-rw-rw-r-- root/root         2 2024-02-08 11:04 a/b/c/d/d.txt           # The workdir is the commit `d2`, though, top repo mean it to be the commit `d`

# Text files for
# `X2` (two lines) commit are 4 bytes; and
# `X`  (one line)  commit are 2 bytes.
KSR-Yasuda commented 8 months ago

Umm..., this is still not working well.

git ls-tree TREEISH SUBMODULE_DIR can check exact submodule ref, but not supporting sub-submodules.

On the other hand, git submodule status --recursive --cached can check all descendant submodules, but it only checks for top repo's current HEAD. Not for given treeish commit.

<top>           <submodule>
                commitC (HEAD)
                 :
HEAD    ------> commitB
 :               :
TREEISH ------> commitA

git ls-tree TREEISH submodule returns commitA for submodule, not the current HEAD of the submodule.

git submodule status --recursive --cached returns commitB, since the command can't receive top repo's TREEISH id.

KSR-Yasuda commented 8 months ago

git ls-tree TREEISH submodule returns commitA for submodule, not the current HEAD of the submodule.

git submodule status --recursive --cached returns commitB, since the command can't receive top repo's TREEISH id.

So, use git ls-tree if available (i.e. for direct submodule), otherwise git submodule status --recursive --cached (i.e. for sub-submodules).

Since this is not complete, output warning messages as below:

Also, show used submodules' hash as the message below:

KSR-Yasuda commented 8 months ago

Fix submodule's git ls-tree hash finding. Now it tries to call git ls-tree for sub-submodules in direct submodules.