Change handling of submodules at upgrade

Start with doing "submodule absorbgitdirs" as otherwise "submodule
deinit" will fail if a module has been cloned first and later added as
a submodule (as it will then contain the .git dir instead of it being
under the superprojects .git dir).

Then try to deinit the submodules before moving the repo and abort the
upgrade if it fails for any submodule. Then do the move and finally
initialize the submodules that were initialized before the upgrade.

See #285
This commit is contained in:
Erik Flodin 2021-01-04 00:33:38 +01:00
parent 0675bc9240
commit 5818eeb9dd
No known key found for this signature in database
GPG Key ID: 420A7C865EE3F85F
2 changed files with 37 additions and 17 deletions

View File

@ -59,12 +59,16 @@ def test_upgrade(tmpdir, runner, yadm, condition):
yadm_legacy.join(path).write(path, ensure=True)
mock_git = ""
if condition in ['tracked', 'submodules']:
if condition != 'no-paths':
mock_git = f'''
function git() {{
echo "$@"
if [[ "$*" == *.gitmodules* ]]; then
return { '0' if condition == 'submodules' else '1' }
if [[ "$*" = *"submodule status" ]]; then
{ 'echo " 1234567 mymodule (1.0)"'
if condition == 'submodules' else ':' }
fi
if [[ "$*" = *ls-files* ]]; then
return { 1 if condition == 'untracked' else 0 }
fi
return 0
}}
@ -111,8 +115,9 @@ def test_upgrade(tmpdir, runner, yadm, condition):
assert expected in run.out
assert 'files tracked by yadm have been renamed' in run.out
if condition == 'submodules':
assert 'submodule deinit -f .' in run.out
assert 'submodule update --init --recursive' in run.out
assert 'submodule deinit -- mymodule' in run.out
assert 'submodule update --init --recursive -- mymodule' \
in run.out
else:
assert 'submodule deinit -f .' not in run.out
assert 'submodule deinit' not in run.out
assert 'submodule update --init --recursive' not in run.out

37
yadm
View File

@ -122,7 +122,7 @@ function main() {
-d) # used by all commands
DEBUG="YES"
;;
-f) # used by init() and clone()
-f) # used by init(), clone() and upgrade()
FORCE="YES"
;;
-l) # used by decrypt()
@ -1296,7 +1296,7 @@ function perms() {
function upgrade() {
local actions_performed=0
local repo_moved=0
local -a submodules
local repo_updates=0
[[ -n "${YADM_OVERRIDE_REPO}${YADM_OVERRIDE_ARCHIVE}" || "$YADM_DATA" = "$YADM_DIR" ]] && \
@ -1315,8 +1315,27 @@ function upgrade() {
error_out "Unable to upgrade. '$YADM_REPO' already exists. Refusing to overwrite it."
else
actions_performed=1
repo_moved=1
echo "Moving $LEGACY_REPO to $YADM_REPO"
export GIT_DIR="$LEGACY_REPO"
# Must absorb git dirs, otherwise deinit below will fail for modules that have
# been cloned first and then added as a submodule.
"$GIT_PROGRAM" submodule absorbgitdirs
while read -r sha submodule rest; do
if [[ "$sha" = -* ]]; then
continue
fi
"$GIT_PROGRAM" -C "$YADM_WORK" submodule deinit ${FORCE:+-f} -- "$submodule" || {
for other in "${submodules[@]}"; do
"$GIT_PROGRAM" -C "$YADM_WORK" submodule update --init --recursive -- "$other"
done
error_out "Unable to upgrade. Could not deinit submodule $submodule"
}
submodules+=("$submodule")
done < <("$GIT_PROGRAM" -C "$YADM_WORK" submodule status)
assert_parent "$YADM_REPO"
mv "$LEGACY_REPO" "$YADM_REPO"
fi
@ -1366,13 +1385,9 @@ function upgrade() {
done
# handle submodules, which need to be reinitialized
if [ "$repo_moved" -ne 0 ]; then
cd_work "Upgrade submodules"
if "$GIT_PROGRAM" ls-files --error-unmatch .gitmodules &> /dev/null; then
"$GIT_PROGRAM" submodule deinit -f .
"$GIT_PROGRAM" submodule update --init --recursive
fi
fi
for submodule in "${submodules[@]}"; do
"$GIT_PROGRAM" -C "$YADM_WORK" submodule update --init --recursive -- "$submodule"
done
[ "$actions_performed" -eq 0 ] && \
echo "No legacy paths found. Upgrade is not necessary"
@ -1610,7 +1625,7 @@ function issue_legacy_path_warning() {
To remove this warning do one of the following:
* Run "yadm upgrade" to move the yadm data to the new paths. (RECOMMENDED)
* Manually move yadm data to new default paths.
* Manually move yadm data to new default paths and reinit any submodules.
* Specify your preferred paths with --yadm-data and --yadm-archive each execution.
Legacy paths detected: