commit bd4792ec812265a57f6e881d9bff1f297d325749 from: Stefan Sperling date: Sun Jan 13 11:56:35 2019 UTC fix more bugs in the update walk and add more tests commit - a7f9d64ddf028029e3ef5123758712ec89840a5f commit + bd4792ec812265a57f6e881d9bff1f297d325749 blob - 257b5a5795a8fa1e54d49544a3136627fc550201 blob + 70174aa3d9e1dc0477a3ceb497937b6acca741a4 --- lib/fileindex.c +++ lib/fileindex.c @@ -564,24 +564,29 @@ in_same_subdir(struct got_fileindex_entry *ie, const c return strchr(ie_name, '/') == NULL; } +/* + * Decide whether ie or te are equivalent, and if they aren't, + * then decide which should be processed first. + */ static int cmp_entries(struct got_fileindex_entry *ie, const char *parent_path, struct got_tree_entry *te) { size_t parent_len = strlen(parent_path); - char *ie_name; + int cmp; if (!in_same_subdir(ie, parent_path, te)) { - if (parent_path[0]) - return strcmp(ie->path, parent_path); - return strcmp(ie->path, te->name); + cmp = strncmp(ie->path, parent_path, parent_len); + if (cmp == 0) + cmp = strcmp(ie->path + parent_len, te->name); + } else { + char *ie_name = ie->path + parent_len; + while (ie_name[0] == '/') + ie_name++; + cmp = strcmp(ie_name, te->name); } - - ie_name = ie->path + parent_len; - while (ie_name[0] == '/') - ie_name++; + return cmp; - return strcmp(ie_name, te->name); } static const struct got_error * @@ -611,12 +616,7 @@ walk_tree(struct got_tree_entry **next, struct got_fil { const struct got_error *err = NULL; - if (te && S_ISREG(te->mode)) { - *next = SIMPLEQ_NEXT(te, entry); - return NULL; - } - - while (te && S_ISDIR(te->mode)) { + if (S_ISDIR(te->mode)) { char *subpath; struct got_tree_object *subtree; @@ -630,22 +630,15 @@ walk_tree(struct got_tree_entry **next, struct got_fil return err; } - if (*ie == NULL || !in_same_subdir(*ie, path, te)) { - err = cb->diff_new(cb_arg, te, path); - if (err) - return err; - } - err = diff_fileindex_tree(fileindex, ie, subtree, subpath, repo, cb, cb_arg); free(subpath); got_object_tree_close(subtree); if (err) return err; - te = SIMPLEQ_NEXT(te, entry); } - *next = te; + *next = SIMPLEQ_NEXT(te, entry); return NULL; } blob - 43321ad6065fe5af9c29235580ecc1b15138c1bc blob + 2438bbf344f4501b2177c6b04e1a90e016407f2f --- lib/worktree.c +++ lib/worktree.c @@ -560,19 +560,7 @@ install_blob(struct got_worktree *worktree, struct got fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, GOT_DEFAULT_FILE_MODE); if (fd == -1) { - if (errno == ENOENT) { - char *parent = dirname(path); - if (parent == NULL) - return got_error_from_errno(); - err = add_dir_on_disk(worktree, parent); - if (err) - return err; - fd = open(ondisk_path, - O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, - GOT_DEFAULT_FILE_MODE); - if (fd == -1) - return got_error_from_errno(); - } else if (errno == EEXIST) { + if (errno == EEXIST) { struct stat sb; if (lstat(ondisk_path, &sb) == -1) { err = got_error_from_errno(); blob - b7d9d15172b1bc6145e019ed80dba37c3dea057e blob + b121574a4f98dd2f74a69c2a49cd1b5f6081c721 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -379,10 +379,10 @@ function test_update_moves_files_upwards { (cd $testroot/repo && git mv epsilon/psi/chi/tau epsilon/psi/tau) git_commit $testroot/repo -m "moving files upwards" - echo "A epsilon/mu" > $testroot/stdout.expected - echo "A epsilon/psi/tau" >> $testroot/stdout.expected - echo "D epsilon/psi/chi/tau" >> $testroot/stdout.expected + echo "D epsilon/psi/chi/tau" > $testroot/stdout.expected echo "D epsilon/psi/mu" >> $testroot/stdout.expected + echo "A epsilon/mu" >> $testroot/stdout.expected + echo "A epsilon/psi/tau" >> $testroot/stdout.expected echo -n "Updated to commit " >> $testroot/stdout.expected git_show_head $testroot/repo >> $testroot/stdout.expected echo >> $testroot/stdout.expected @@ -491,16 +491,69 @@ function test_update_creates_missing_parent { git_commit $testroot/repo -m "restructuring snake tree" echo "D Makefile" > $testroot/stdout.expected + echo "D snake.6" >> $testroot/stdout.expected + echo "D snake.c" >> $testroot/stdout.expected echo "A snake/Makefile" >> $testroot/stdout.expected echo "A snake/move.c" >> $testroot/stdout.expected echo "A snake/pathnames.h" >> $testroot/stdout.expected echo "A snake/snake.6" >> $testroot/stdout.expected echo "A snake/snake.c" >> $testroot/stdout.expected echo "A snake/snake.h" >> $testroot/stdout.expected + echo "A snscore/Makefile" >> $testroot/stdout.expected + echo "A snscore/snscore.c" >> $testroot/stdout.expected + echo -n "Updated to commit " >> $testroot/stdout.expected + git_show_head $testroot/repo >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + + (cd $testroot/wt && got update > $testroot/stdout) + + cmp $testroot/stdout.expected $testroot/stdout + if [ "$?" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$?" + return 1 + fi + + test_done "$testroot" "0" +} + +function test_update_creates_missing_parent_with_subdir { + local testroot=`test_init update_creates_missing_parent no_tree` + + touch $testroot/repo/Makefile + touch $testroot/repo/snake.6 + touch $testroot/repo/snake.c + (cd $testroot/repo && git add .) + git_commit $testroot/repo -m "adding initial snake tree" + + got checkout $testroot/repo $testroot/wt > /dev/null + if [ "$?" != "0" ]; then + test_done "$testroot" "$?" + return 1 + fi + + mkdir -p $testroot/repo/sss/snake + (cd $testroot/repo && git mv Makefile snake.6 snake.c sss/snake) + touch $testroot/repo/sss/snake/move.c + touch $testroot/repo/sss/snake/pathnames.h + touch $testroot/repo/sss/snake/snake.h + mkdir -p $testroot/repo/snscore + touch $testroot/repo/snscore/Makefile + touch $testroot/repo/snscore/snscore.c + (cd $testroot/repo && git add .) + git_commit $testroot/repo -m "restructuring snake tree" + + echo "D Makefile" > $testroot/stdout.expected echo "D snake.6" >> $testroot/stdout.expected echo "D snake.c" >> $testroot/stdout.expected echo "A snscore/Makefile" >> $testroot/stdout.expected echo "A snscore/snscore.c" >> $testroot/stdout.expected + echo "A sss/snake/Makefile" >> $testroot/stdout.expected + echo "A sss/snake/move.c" >> $testroot/stdout.expected + echo "A sss/snake/pathnames.h" >> $testroot/stdout.expected + echo "A sss/snake/snake.6" >> $testroot/stdout.expected + echo "A sss/snake/snake.c" >> $testroot/stdout.expected + echo "A sss/snake/snake.h" >> $testroot/stdout.expected echo -n "Updated to commit " >> $testroot/stdout.expected git_show_head $testroot/repo >> $testroot/stdout.expected echo >> $testroot/stdout.expected @@ -526,5 +579,6 @@ run_test test_update_deletes_dir_recursively run_test test_update_sibling_dirs_with_common_prefix run_test test_update_dir_with_dot_sibling run_test test_update_moves_files_upwards -#run_test test_update_moves_files_to_new_dir # test is failing +run_test test_update_moves_files_to_new_dir run_test test_update_creates_missing_parent +run_test test_update_creates_missing_parent_with_subdir