commit 21908da4c3cfc3f2d04dd511bd59c1c877f92b14 from: Stefan Sperling date: Sun Jan 13 12:59:20 2019 UTC fix bug where update got confused by sub-sub directories commit - bd4792ec812265a57f6e881d9bff1f297d325749 commit + 21908da4c3cfc3f2d04dd511bd59c1c877f92b14 blob - 70174aa3d9e1dc0477a3ceb497937b6acca741a4 blob + a1d12e6dbe2e63177e9e709a1659d4073b8db842 --- lib/fileindex.c +++ lib/fileindex.c @@ -577,8 +577,12 @@ cmp_entries(struct got_fileindex_entry *ie, const char if (!in_same_subdir(ie, parent_path, te)) { cmp = strncmp(ie->path, parent_path, parent_len); - if (cmp == 0) - cmp = strcmp(ie->path + parent_len, te->name); + if (cmp == 0) { + char *ie_name = ie->path + parent_len; + while (ie_name[0] == '/') + ie_name++; + cmp = strcmp(ie_name, te->name); + } } else { char *ie_name = ie->path + parent_len; while (ie_name[0] == '/') blob - 2438bbf344f4501b2177c6b04e1a90e016407f2f blob + 62fe285a54aaefa790d4d2c759df4e4733ec5fd0 --- lib/worktree.c +++ lib/worktree.c @@ -507,6 +507,27 @@ lock_worktree(struct got_worktree *worktree, int opera } static const struct got_error * +make_parent_dirs(const char *abspath) +{ + const struct got_error *err = NULL; + + char *parent = dirname(abspath); + if (parent == NULL) + return NULL; + + if (mkdir(parent, GOT_DEFAULT_DIR_MODE) == -1) { + if (errno == ENOENT) { + err = make_parent_dirs(parent); + if (err) + return err; + } else + return got_error_from_errno(); + } + + return NULL; +} + +static const struct got_error * add_dir_on_disk(struct got_worktree *worktree, const char *path) { const struct got_error *err = NULL; @@ -519,20 +540,30 @@ add_dir_on_disk(struct got_worktree *worktree, const c if (mkdir(abspath, GOT_DEFAULT_DIR_MODE) == -1) { struct stat sb; - if (errno != EEXIST) { - err = got_error_from_errno(); - goto done; + if (errno == EEXIST) { + if (lstat(abspath, &sb) == -1) { + err = got_error_from_errno(); + goto done; + } + + if (!S_ISDIR(sb.st_mode)) { + /* TODO directory is obstructed; do something */ + return got_error(GOT_ERR_FILE_OBSTRUCTED); + } + + return NULL; } - if (lstat(abspath, &sb) == -1) { + if (errno == ENOENT) { + err = make_parent_dirs(abspath); + if (err) + return err; + if (mkdir(abspath, GOT_DEFAULT_DIR_MODE) == 0) + return NULL; + } else { err = got_error_from_errno(); goto done; } - - if (!S_ISDIR(sb.st_mode)) { - /* TODO directory is obstructed; do something */ - return got_error(GOT_ERR_FILE_OBSTRUCTED); - } } done: @@ -560,7 +591,19 @@ 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 == EEXIST) { + 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) { struct stat sb; if (lstat(ondisk_path, &sb) == -1) { err = got_error_from_errno(); blob - b121574a4f98dd2f74a69c2a49cd1b5f6081c721 blob + 61f3c4d796ad5f9b6b1d8d33f6594411e2d40b22 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -379,9 +379,9 @@ 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 "D epsilon/psi/chi/tau" > $testroot/stdout.expected + echo "A epsilon/mu" > $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 @@ -569,7 +569,45 @@ function test_update_creates_missing_parent_with_subdi test_done "$testroot" "0" } + +function test_update_file_in_subsubdir { + local testroot=`test_init update_fle_in_subsubdir no_tree` + touch $testroot/repo/Makefile + mkdir -p $testroot/repo/altq + touch $testroot/repo/altq/if_altq.h + mkdir -p $testroot/repo/arch/alpha + touch $testroot/repo/arch/alpha/Makefile + (cd $testroot/repo && git add .) + git_commit $testroot/repo -m "adding initial tree" + + got checkout $testroot/repo $testroot/wt > /dev/null + if [ "$?" != "0" ]; then + test_done "$testroot" "$?" + return 1 + fi + + echo change > $testroot/repo/arch/alpha/Makefile + (cd $testroot/repo && git add .) + git_commit $testroot/repo -m "changed a file" + + echo "U arch/alpha/Makefile" > $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" +} + run_test test_update_basic run_test test_update_adds_file run_test test_update_deletes_file @@ -582,3 +620,4 @@ run_test test_update_moves_files_upwards 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 +run_test test_update_file_in_subsubdir