commit - c333d3f7e18758890f7454075451edf36eb26c0f
commit + a769b60bb76783d3bc6637d75907b6ca5d623f40
blob - d1e3839c06a7f70e71410592024f426053df2ced
blob + aec06af5925a0cd63ffc6b150466bad036d5abd8
--- lib/fileindex.c
+++ lib/fileindex.c
#define GOT_FILEIDX_F_NO_COMMIT 0x00040000
#define GOT_FILEIDX_F_NO_FILE_ON_DISK 0x00080000
#define GOT_FILEIDX_F_REMOVE_ON_FLUSH 0x00100000
+#define GOT_FILEIDX_F_SKIPPED 0x00200000
struct got_fileindex {
struct got_fileindex_tree entries;
got_fileindex_entry_mark_deleted_from_disk(struct got_fileindex_entry *ie)
{
ie->flags |= GOT_FILEIDX_F_NO_FILE_ON_DISK;
+}
+
+void
+got_fileindex_entry_mark_skipped(struct got_fileindex_entry *ie)
+{
+ ie->flags |= GOT_FILEIDX_F_SKIPPED;
}
const struct got_error *
return (ie->flags & GOT_FILEIDX_F_NO_FILE_ON_DISK) == 0;
}
+int
+got_fileindex_entry_was_skipped(struct got_fileindex_entry *ie)
+{
+ return (ie->flags & GOT_FILEIDX_F_SKIPPED) != 0;
+}
+
static const struct got_error *
add_entry(struct got_fileindex *fileindex, struct got_fileindex_entry *ie)
{
RB_FOREACH_SAFE(ie, got_fileindex_tree, &fileindex->entries, tmp) {
ie->flags &= ~GOT_FILEIDX_F_NOT_FLUSHED;
+ ie->flags &= ~GOT_FILEIDX_F_SKIPPED;
if (ie->flags & GOT_FILEIDX_F_REMOVE_ON_FLUSH) {
RB_REMOVE(got_fileindex_tree, &fileindex->entries, ie);
got_fileindex_entry_free(ie);
blob - 537374d719e84293f1b449465ab63e092b44a20a
blob + d03058e83c5f5c0a69baf66795455eb3ab8b7af7
--- lib/got_lib_fileindex.h
+++ lib/got_lib_fileindex.h
const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *,
int, const char *, uint8_t *, uint8_t *, int);
+void got_fileindex_entry_mark_skipped(struct got_fileindex_entry *);
const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **,
const char *);
void got_fileindex_entry_free(struct got_fileindex_entry *);
int got_fileindex_entry_has_blob(struct got_fileindex_entry *);
int got_fileindex_entry_has_commit(struct got_fileindex_entry *);
int got_fileindex_entry_has_file_on_disk(struct got_fileindex_entry *);
+int got_fileindex_entry_was_skipped(struct got_fileindex_entry *);
uint32_t got_fileindex_entry_stage_get(const struct got_fileindex_entry *);
void got_fileindex_entry_stage_set(struct got_fileindex_entry *ie, uint32_t);
int got_fileindex_entry_filetype_get(struct got_fileindex_entry *);
blob - 57631f318cb2eb1b8a1bfc2cbe610407f87d90da
blob + 9cc4b321126df2564f860576e790daa70c927295
--- lib/worktree.c
+++ lib/worktree.c
goto done;
}
if (status == GOT_STATUS_CONFLICT) {
+ if (ie)
+ got_fileindex_entry_mark_skipped(ie);
err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
path);
goto done;
} else if (!got_path_is_child(ie->path, a->path, a->path_len))
return NULL;
+ if (got_fileindex_entry_was_skipped(ie))
+ return NULL;
+
if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
SHA1_DIGEST_LENGTH) == 0)
return NULL;
blob - fa0398814a0312e4d8d4d343c490f6b7b4129804
blob + 18691664018f8a6afd325e890af93afbcdd51b2b
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
test_done "$testroot" "0"
return 0
+}
+
+test_update_file_skipped_due_to_conflict() {
+ local testroot=`test_init update_file_skipped_due_to_conflict`
+ local commit_id0=`git_show_head $testroot/repo`
+ blob_id0=`get_blob_id $testroot/repo "" beta`
+
+ echo "changed beta" > $testroot/repo/beta
+ git_commit $testroot/repo -m "changed beta"
+ local commit_id1=`git_show_head $testroot/repo`
+ blob_id1=`get_blob_id $testroot/repo "" beta`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ blob_id=`(cd $testroot/wt && got info beta | grep 'blob:' | \
+ cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$blob_id" != "$blob_id1" ]; then
+ echo "file beta has the wrong base blob ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ commit_id=`(cd $testroot/wt && got info beta | \
+ grep 'based on commit:' | cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$commit_id" != "$commit_id1" ]; then
+ echo "file beta has the wrong base commit ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ echo "modified beta" > $testroot/wt/beta
+
+ (cd $testroot/wt && got update -c $commit_id0 > $testroot/stdout)
+
+ echo "C beta" > $testroot/stdout.expected
+ echo "Updated to commit $commit_id0" >> $testroot/stdout.expected
+ echo "Files with new merge conflicts: 1" >> $testroot/stdout.expected
+ cmp -s $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 "<<<<<<< merged change: commit $commit_id0" \
+ > $testroot/content.expected
+ echo "beta" >> $testroot/content.expected
+ echo "||||||| 3-way merge base: commit $commit_id1" \
+ >> $testroot/content.expected
+ echo "changed beta" >> $testroot/content.expected
+ echo "=======" >> $testroot/content.expected
+ echo "modified beta" >> $testroot/content.expected
+ echo ">>>>>>>" >> $testroot/content.expected
+
+ cat $testroot/wt/beta > $testroot/content
+
+ cmp -s $testroot/content.expected $testroot/content
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/content.expected $testroot/content
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ blob_id=`(cd $testroot/wt && got info beta | grep 'blob:' | \
+ cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$blob_id" != "$blob_id0" ]; then
+ echo "file beta has the wrong base blob ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ commit_id=`(cd $testroot/wt && got info beta | \
+ grep 'based on commit:' | cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$commit_id" != "$commit_id0" ]; then
+ echo "file beta has the wrong base commit ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ # update to the latest commit again; this skips beta
+ (cd $testroot/wt && got update > $testroot/stdout)
+ echo "# beta" > $testroot/stdout.expected
+ echo "Updated to commit $commit_id1" >> $testroot/stdout.expected
+ echo "Files not updated because of existing merge conflicts: 1" \
+ >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # blob ID of beta should not have changed
+ blob_id=`(cd $testroot/wt && got info beta | grep 'blob:' | \
+ cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$blob_id" != "$blob_id0" ]; then
+ echo "file beta has the wrong base blob ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ # commit ID of beta should not have changed; There was a bug
+ # here where the commit ID had been changed even though the
+ # file was not updated.
+ commit_id=`(cd $testroot/wt && got info beta | \
+ grep 'based on commit:' | cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$commit_id" != "$commit_id0" ]; then
+ echo "file beta has the wrong base commit ID: $commit_id" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ # beta is still conflicted and based on commit 0
+ echo 'C beta' > $testroot/stdout.expected
+ (cd $testroot/wt && got status > $testroot/stdout)
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # resolve the conflict via revert
+ (cd $testroot/wt && got revert beta >/dev/null)
+
+ # beta now matches its base blob which is still from commit 0
+ echo "beta" > $testroot/content.expected
+ cat $testroot/wt/beta > $testroot/content
+ cmp -s $testroot/content.expected $testroot/content
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/content.expected $testroot/content
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # updating to the latest commit should now update beta
+ (cd $testroot/wt && got update > $testroot/stdout)
+ echo "U beta" > $testroot/stdout.expected
+ echo "Updated to commit $commit_id1" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ blob_id=`(cd $testroot/wt && got info beta | grep 'blob:' | \
+ cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$blob_id" != "$blob_id1" ]; then
+ echo "file beta has the wrong base blob ID" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ commit_id=`(cd $testroot/wt && got info beta | \
+ grep 'based on commit:' | cut -d ':' -f 2 | tr -d ' ')`
+ if [ "$commit_id" != "$commit_id1" ]; then
+ echo "file beta has the wrong base commit ID: $commit_id" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ echo "changed beta" > $testroot/content.expected
+ cat $testroot/wt/beta > $testroot/content
+ cmp -s $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_deletes_symlink
run_test test_update_symlink_conflicts
run_test test_update_single_file
+run_test test_update_file_skipped_due_to_conflict