commit a378724ff7c52fed47ca10ec7bb827ad4955ce57 from: Stefan Sperling date: Sun Feb 10 12:20:43 2019 UTC make 'got update' restore missing files commit - e60e7f5bf0d3d27834b9712529836b42207853c8 commit + a378724ff7c52fed47ca10ec7bb827ad4955ce57 blob - 914b39fda8d355979f18027abf6b0d7b7091aa65 blob + 1ce550db674eb7b48feb8bd5c8e48a2ed6f537c6 --- got/got.1 +++ got/got.1 @@ -105,6 +105,7 @@ Show the status of each affected file, using the follo .It D Ta file was deleted .It A Ta new file was added .It ~ Ta versioned file is obstructed by a non-regular file +.It ! Ta a missing versioned file was restored .El .Pp If the blob - 755f467c2aa1a389cc6240409b367803b91565a5 blob + 709848c071063737c6e2c461124cc38e2ec0eac9 --- got/got.c +++ got/got.c @@ -436,7 +436,8 @@ update_progress(void *arg, unsigned char status, const if (status == GOT_STATUS_EXISTS) return; - *did_something = 1; + if (status != GOT_STATUS_MISSING) + *did_something = 1; while (path[0] == '/') path++; printf("%c %s\n", status, path); blob - f8449d38ccd31e85697d762976525f415268ccb9 blob + 893ba6cf0e45a7e3252f09fe1a4bfe287009aba3 --- lib/worktree.c +++ lib/worktree.c @@ -697,7 +697,7 @@ done: static const struct got_error * install_blob(struct got_worktree *worktree, struct got_fileindex *fileindex, struct got_fileindex_entry *entry, const char *ondisk_path, const char *path, - uint16_t mode, struct got_blob_object *blob, + uint16_t mode, struct got_blob_object *blob, int restoring_missing_file, struct got_repository *repo, got_worktree_checkout_cb progress_cb, void *progress_arg) { @@ -742,8 +742,11 @@ install_blob(struct got_worktree *worktree, struct got return got_error_from_errno(); } - (*progress_cb)(progress_arg, - update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path); + if (restoring_missing_file) + (*progress_cb)(progress_arg, GOT_STATUS_MISSING, path); + else + (*progress_cb)(progress_arg, + update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path); hdrlen = got_object_blob_get_hdrlen(blob); do { @@ -826,8 +829,13 @@ get_file_status(unsigned char *status, struct got_file *status = GOT_STATUS_NO_CHANGE; - if (lstat(abspath, &sb) == -1) + if (lstat(abspath, &sb) == -1) { + if (errno == ENOENT) { + *status = GOT_STATUS_MISSING; + return NULL; + } return got_error_from_errno(); + } if (!S_ISREG(sb.st_mode)) { *status = GOT_STATUS_OBSTRUCTED; @@ -903,16 +911,6 @@ update_blob(struct got_worktree *worktree, return got_error_from_errno(); if (ie) { - if (memcmp(ie->commit_sha1, worktree->base_commit_id->sha1, - SHA1_DIGEST_LENGTH) == 0) { - (*progress_cb)(progress_arg, GOT_STATUS_EXISTS, - path); - goto done; - } - if (memcmp(ie->blob_sha1, - te->id->sha1, SHA1_DIGEST_LENGTH) == 0) - goto done; - err = get_file_status(&status, ie, ondisk_path, repo); if (err) goto done; @@ -920,6 +918,19 @@ update_blob(struct got_worktree *worktree, if (status == GOT_STATUS_OBSTRUCTED) { (*progress_cb)(progress_arg, status, path); goto done; + } + + if (status == GOT_STATUS_NO_CHANGE) { + if (memcmp(ie->commit_sha1, + worktree->base_commit_id->sha1, + SHA1_DIGEST_LENGTH) == 0) { + (*progress_cb)(progress_arg, GOT_STATUS_EXISTS, + path); + goto done; + } + if (memcmp(ie->blob_sha1, + te->id->sha1, SHA1_DIGEST_LENGTH) == 0) + goto done; } } @@ -932,7 +943,8 @@ update_blob(struct got_worktree *worktree, te->mode, blob, repo, progress_cb, progress_arg); else err = install_blob(worktree, fileindex, ie, ondisk_path, path, - te->mode, blob, repo, progress_cb, progress_arg); + te->mode, blob, status == GOT_STATUS_MISSING, repo, + progress_cb, progress_arg); got_object_blob_close(blob); done: blob - e7ae6c144216594739f0afb77723057f5bf22b17 blob + 3267b8ed203708fea01289cbeae3ed1131275e5e --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -809,7 +809,43 @@ function test_update_clears_xbit { fi test_done "$testroot" "$ret" } + +function test_update_restores_missing_file { + local testroot=`test_init update_restores_missing_file` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + rm $testroot/wt/alpha + + echo "! alpha" > $testroot/stdout.expected + echo "Already up-to-date" >> $testroot/stdout.expected + (cd $testroot/wt && got update > $testroot/stdout) + + cmp $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "alpha" > $testroot/content.expected + + cat $testroot/wt/alpha > $testroot/content + + cmp $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + fi + test_done "$testroot" "$ret" +} + run_test test_update_basic run_test test_update_adds_file run_test test_update_deletes_file @@ -826,3 +862,4 @@ run_test test_update_file_in_subsubdir run_test test_update_merges_file_edits run_test test_update_keeps_xbit run_test test_update_clears_xbit +run_test test_update_restores_missing_file