commit - 085d5bcf0b7635235aeaa2608540072bdc88ae99
commit + 13d9040b96f5ba9ac50c137a9909f824dd5bde20
blob - 3421739139d8ff2c8f0b5051debfd6d9755fd579
blob + 4a33abd6b06c91758f991512a2d7475a06651970
--- lib/fileindex.c
+++ lib/fileindex.c
{
struct stat sb;
- if (lstat(ondisk_path, &sb) != 0)
- return got_error_from_errno();
+ if (lstat(ondisk_path, &sb) != 0) {
+ if ((entry->flags & GOT_FILEIDX_F_NO_FILE_ON_DISK) == 0)
+ return got_error_from_errno();
+ } else
+ entry->flags &= ~GOT_FILEIDX_F_NO_FILE_ON_DISK;
- entry->flags &= ~GOT_FILEIDX_F_NO_FILE_ON_DISK;
-
- 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;
+ if ((entry->flags & GOT_FILEIDX_F_NO_FILE_ON_DISK) == 0) {
+ 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);
+ if (sb.st_mode & S_IFLNK)
+ entry->mode = GOT_FILEIDX_MODE_SYMLINK;
+ else
+ entry->mode = GOT_FILEIDX_MODE_REGULAR_FILE;
+ entry->mode |= ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) <<
+ GOT_FILEIDX_MODE_PERMS_SHIFT);
}
- entry->uid = sb.st_uid;
- entry->gid = sb.st_gid;
- entry->size = (sb.st_size & 0xffffffff);
- if (sb.st_mode & S_IFLNK)
- entry->mode = GOT_FILEIDX_MODE_SYMLINK;
- else
- entry->mode = GOT_FILEIDX_MODE_REGULAR_FILE;
- entry->mode |= ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) <<
- GOT_FILEIDX_MODE_PERMS_SHIFT);
if (blob_sha1) {
memcpy(entry->blob_sha1, blob_sha1, SHA1_DIGEST_LENGTH);
blob - 442288387b7a34120e7bba5f27c9f45dbfc31768
blob + 3f0523ffaec3bb0f816ab6a98521fbe8d543e3f6
--- lib/worktree.c
+++ lib/worktree.c
}
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 te_mode, uint16_t st_mode, struct got_blob_object *blob,
- int restoring_missing_file, struct got_repository *repo,
- got_worktree_checkout_cb progress_cb, void *progress_arg)
+update_blob_fileindex_entry(struct got_worktree *worktree,
+ struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
+ const char *ondisk_path, const char *path, struct got_blob_object *blob,
+ int update_timestamps)
+{
+ const struct got_error *err = NULL;
+
+ if (ie == NULL)
+ ie = got_fileindex_entry_get(fileindex, path);
+ if (ie)
+ err = got_fileindex_entry_update(ie, ondisk_path,
+ blob->id.sha1, worktree->base_commit_id->sha1,
+ update_timestamps);
+ else {
+ struct got_fileindex_entry *new_ie;
+ err = got_fileindex_entry_alloc(&new_ie, ondisk_path,
+ path, blob->id.sha1, worktree->base_commit_id->sha1);
+ if (!err)
+ err = got_fileindex_entry_add(fileindex, new_ie);
+ }
+ return err;
+}
+
+static const struct got_error *
+install_blob(struct got_worktree *worktree, const char *ondisk_path,
+ const char *path, uint16_t te_mode, uint16_t st_mode,
+ struct got_blob_object *blob, int restoring_missing_file,
+ struct got_repository *repo, got_worktree_checkout_cb progress_cb,
+ void *progress_arg)
{
const struct got_error *err = NULL;
int fd = -1;
}
}
- if (entry == NULL)
- 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, 1);
- else {
- err = got_fileindex_entry_alloc(&entry, ondisk_path,
- path, blob->id.sha1, worktree->base_commit_id->sha1);
- if (err)
- goto done;
- err = got_fileindex_entry_add(fileindex, entry);
- }
done:
if (fd != -1 && close(fd) != 0 && err == NULL)
err = got_error_from_errno();
err = merge_blob(worktree, fileindex, ie, ondisk_path, path,
te->mode, sb.st_mode, blob, repo, progress_cb,
progress_arg);
- else
- err = install_blob(worktree, fileindex, ie, ondisk_path, path,
- te->mode, sb.st_mode, blob, status == GOT_STATUS_MISSING,
- repo, progress_cb, progress_arg);
-
+ else if (status == GOT_STATUS_DELETE) {
+ (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
+ err = update_blob_fileindex_entry(worktree, fileindex, ie,
+ ondisk_path, path, blob, 0);
+ if (err)
+ goto done;
+ } else {
+ err = install_blob(worktree, ondisk_path, path, te->mode,
+ sb.st_mode, blob, status == GOT_STATUS_MISSING, repo,
+ progress_cb, progress_arg);
+ if (err)
+ goto done;
+ err = update_blob_fileindex_entry(worktree, fileindex, ie,
+ ondisk_path, path, blob, 1);
+ if (err)
+ goto done;
+ }
got_object_blob_close(blob);
done:
free(ondisk_path);
blob - d30a87ce41088f62e2a9a1f6aa924eada9cd5d12
blob + 5b27ea3fdd42c59f652befa84aa020bb8f3b7139
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
# beta is now an unversioned file... we don't flag tree conflicts yet
echo '? beta' > $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
+ fi
+ test_done "$testroot" "$ret"
+}
+
+function test_update_conflict_wt_rm_vs_repo_edit {
+ local testroot=`test_init update_conflict_wt_rm_vs_repo_edit`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "modified beta" > $testroot/repo/beta
+ git_commit $testroot/repo -m "modified a file"
+
+ (cd $testroot/wt && got rm beta > /dev/null)
+
+ (cd $testroot/wt && got update > $testroot/stdout)
+
+ echo "G beta" > $testroot/stdout.expected
+ echo -n "Updated to commit " >> $testroot/stdout.expected
+ git_show_head $testroot/repo >> $testroot/stdout.expected
+ echo >> $testroot/stdout.expected
+ 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
+
+ # beta remains a deleted file... we don't flag tree conflicts yet
+ echo 'D beta' > $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
+
+ # 'got diff' should show post-update contents of beta being deleted
+ local head_rev=`git_show_head $testroot/repo`
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'beta$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + /dev/null' >> $testroot/stdout.expected
+ echo '--- beta' >> $testroot/stdout.expected
+ echo '+++ beta' >> $testroot/stdout.expected
+ echo '@@ -1 +0,0 @@' >> $testroot/stdout.expected
+ echo '-modified beta' >> $testroot/stdout.expected
+
+ (cd $testroot/wt && got diff > $testroot/stdout)
+ cmp $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
test_done "$testroot" "$ret"
}
run_test test_update_restores_missing_file
run_test test_update_conflict_wt_add_vs_repo_add
run_test test_update_conflict_wt_edit_vs_repo_rm
+run_test test_update_conflict_wt_rm_vs_repo_edit