commit db1d3576eb40d1c48c15fd8d531e030296874e9f from: Stefan Sperling date: Fri Oct 04 11:13:22 2019 UTC handle empty trees during 'import' and 'checkout'; spotted by sthen@ commit - 13555e04f090597ce528af657bf0da6eff0a9849 commit + db1d3576eb40d1c48c15fd8d531e030296874e9f blob - 4066dbbfd69fe6ca20e85d8ef82b5b7fe24e9833 (mode 640) blob + a037ceb7fcaca7f9358cecf93fb644ff7f35ccc9 (mode 644) --- lib/object_parse.c +++ lib/object_parse.c @@ -727,9 +727,6 @@ got_object_parse_tree(struct got_tree_object **tree, u struct got_pathlist_entry *pe; TAILQ_INIT(&pathlist); - - if (remain == 0) - return got_error(GOT_ERR_BAD_OBJ_DATA); *tree = calloc(1, sizeof(**tree)); if (*tree == NULL) @@ -737,6 +734,9 @@ got_object_parse_tree(struct got_tree_object **tree, u SIMPLEQ_INIT(&(*tree)->entries.head); + if (remain == 0) + return NULL; /* tree is empty */ + while (remain > 0) { struct got_tree_entry *te; struct got_pathlist_entry *new = NULL; blob - b32361c79015d1bc19a941fd7bc1d633bc74fc8a blob + 22355c100383c081b6562883efbb2d33574c7265 --- lib/repository.c +++ lib/repository.c @@ -1492,8 +1492,12 @@ write_tree(struct got_object_id **new_tree_id, const c if (de->d_type == DT_DIR) { err = import_subdir(&new_te, de, path_dir, ignores, repo, progress_cb, progress_arg); - if (err) - goto done; + if (err) { + if (err->code != GOT_ERR_NO_TREE_ENTRY) + goto done; + err = NULL; + continue; + } } else if (de->d_type == DT_REG) { err = import_file(&new_te, de, path_dir, repo); if (err) @@ -1506,6 +1510,11 @@ write_tree(struct got_object_id **new_tree_id, const c goto done; } + if (TAILQ_EMPTY(&paths)) { + err = got_error(GOT_ERR_NO_TREE_ENTRY); + goto done; + } + TAILQ_FOREACH(pe, &paths, entry) { struct got_tree_entry *te = pe->data; char *path; blob - ce3cb343d8747812035937497cb86cab7192b220 blob + 42ff36721b7a4349961e76289fca5eca64b2a559 --- regress/cmdline/import.sh +++ regress/cmdline/import.sh @@ -196,10 +196,52 @@ function test_import_ignores { diff -u $testroot/stdout.expected $testroot/stdout fi test_done "$testroot" "$ret" +} +function test_import_empty_dir { + local testname=import_empty_dir + local testroot=`mktemp -p /tmp -d got-test-$testname-XXXXXXXX` + got init $testroot/repo + + mkdir $testroot/tree + mkdir -p $testroot/tree/empty $testroot/tree/notempty + echo "alpha" > $testroot/tree/notempty/alpha + + got import -m 'init' -r $testroot/repo $testroot/tree > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + local head_commit=`git_show_head $testroot/repo` + echo "A $testroot/tree/notempty/alpha" >> $testroot/stdout.expected + echo "Created branch refs/heads/master with commit $head_commit" \ + >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # Verify that Got did not import the empty directory + echo "notempty/" > $testroot/stdout.expected + echo "notempty/alpha" >> $testroot/stdout.expected + + got tree -r $testroot/repo -R > $testroot/stdout + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" } run_test test_import_basic run_test test_import_requires_new_branch run_test test_import_ignores +run_test test_import_empty_dir