commit 02c0700795c2aee56eaff4d72d82287aa84100ce from: Stefan Sperling date: Sun Feb 10 11:46:14 2019 UTC don't update cached timestamps of already modified files commit - ba8a0d4daae0952f0b83279b0ffc8ab29bcc9c6c commit + 02c0700795c2aee56eaff4d72d82287aa84100ce blob - 0f460ce47ab80f6e6fcb7ad69b0f9fbfda890647 blob + 69121f81b1441c3d7e62c37bcfe591ad6ad172c3 --- lib/fileindex.c +++ lib/fileindex.c @@ -41,17 +41,20 @@ struct got_fileindex { const struct got_error * got_fileindex_entry_update(struct got_fileindex_entry *entry, - const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1) + const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1, + int update_timestamps) { struct stat sb; if (lstat(ondisk_path, &sb) != 0) return got_error_from_errno(); - entry->ctime_sec = sb.st_ctime; - entry->ctime_nsec = sb.st_ctimensec; - entry->mtime_sec = sb.st_mtime; - entry->mtime_nsec = sb.st_mtimensec; + if (update_timestamps) { + entry->ctime_sec = sb.st_ctime; + entry->ctime_nsec = sb.st_ctimensec; + entry->mtime_sec = sb.st_mtime; + entry->mtime_nsec = sb.st_mtimensec; + } entry->uid = sb.st_uid; entry->gid = sb.st_gid; entry->size = (sb.st_size & 0xffffffff); @@ -92,7 +95,7 @@ got_fileindex_entry_alloc(struct got_fileindex_entry * (*entry)->flags |= len; return got_fileindex_entry_update(*entry, ondisk_path, blob_sha1, - commit_sha1); + commit_sha1, 1); } void blob - 64bfc70abd5e42a3ce6e3949277cf7b625f4a843 blob + bb4a77afda033364d37dcdc5dd281795429bad65 --- lib/got_lib_fileindex.h +++ lib/got_lib_fileindex.h @@ -95,7 +95,7 @@ struct got_fileindex_hdr { }; const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *, - const char *, uint8_t *, uint8_t *); + const char *, uint8_t *, uint8_t *, int); const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **, const char *, const char *, uint8_t *, uint8_t *); void got_fileindex_entry_free(struct got_fileindex_entry *); blob - 2761439155ff48f2d450858f66e6aa71aabd5014 blob + f8449d38ccd31e85697d762976525f415268ccb9 --- lib/worktree.c +++ lib/worktree.c @@ -665,8 +665,12 @@ merge_blob(struct got_worktree *worktree, struct got_f goto done; } + /* + * Do not update timestamps of already modified files. Otherwise, + * the status walk would treat them as unmodified files again. + */ err = got_fileindex_entry_update(ie, ondisk_path, - blob1->id.sha1, worktree->base_commit_id->sha1); + blob1->id.sha1, worktree->base_commit_id->sha1, 0); done: if (merged_fd != -1) close(merged_fd); @@ -792,7 +796,7 @@ install_blob(struct got_worktree *worktree, struct got entry = got_fileindex_entry_get(fileindex, path); if (entry) err = got_fileindex_entry_update(entry, ondisk_path, - blob->id.sha1, worktree->base_commit_id->sha1); + blob->id.sha1, worktree->base_commit_id->sha1, 1); else { err = got_fileindex_entry_alloc(&entry, ondisk_path, path, blob->id.sha1, worktree->base_commit_id->sha1); blob - c74933deea94f58a5325f8288e175d73fa64ee10 blob + 26ddd6de25bcabec49a91e174c0bf78866915007 --- regress/cmdline/status.sh +++ regress/cmdline/status.sh @@ -152,7 +152,65 @@ function test_status_obstructed { test_done "$testroot" "0" } +function test_status_shows_local_mods_after_update { + local testroot=`test_init status_shows_local_mods_after_update 1` + + echo "1" > $testroot/repo/numbers + echo "2" >> $testroot/repo/numbers + echo "3" >> $testroot/repo/numbers + echo "4" >> $testroot/repo/numbers + echo "5" >> $testroot/repo/numbers + echo "6" >> $testroot/repo/numbers + echo "7" >> $testroot/repo/numbers + echo "8" >> $testroot/repo/numbers + (cd $testroot/repo && git add numbers) + git_commit $testroot/repo -m "added numbers file" + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + sed -i 's/2/22/' $testroot/repo/numbers + git_commit $testroot/repo -m "modified line 2" + + # modify line 7; both changes should merge cleanly + sed -i 's/7/77/' $testroot/wt/numbers + + echo "G numbers" > $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 + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo 'M numbers' > $testroot/stdout.expected + + (cd $testroot/wt && got status > $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 + + test_done "$testroot" "0" +} + run_test test_status_basic run_test test_status_subdir_no_mods run_test test_status_subdir_no_mods2 run_test test_status_obstructed +run_test test_status_shows_local_mods_after_update