don't update cached timestamps of already modified files
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
diff --git a/lib/fileindex.c b/lib/fileindex.c
index 0f460ce..69121f8 100644
--- a/lib/fileindex.c
+++ b/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,
(*entry)->flags |= len;
return got_fileindex_entry_update(*entry, ondisk_path, blob_sha1,
- commit_sha1);
+ commit_sha1, 1);
}
void
diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
index 64bfc70..bb4a77a 100644
--- a/lib/got_lib_fileindex.h
+++ b/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 *);
diff --git a/lib/worktree.c b/lib/worktree.c
index 2761439..f8449d3 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -665,8 +665,12 @@ merge_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
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_fileindex *fileindex,
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);
diff --git a/regress/cmdline/status.sh b/regress/cmdline/status.sh
index c74933d..26ddd6d 100755
--- a/regress/cmdline/status.sh
+++ b/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