commit - e4b9a50c4562bd5527f8a0a3c8c754c2c95031ca
commit + 9bead371155cd3f955ba6699b0819df23f008bea
blob - d13a217315b4bc76901ed6b4828f4641abb540b2
blob + 1103157f40a2fc20de0d14bda891787ffdfeeaad
--- lib/worktree.c
+++ lib/worktree.c
struct got_object_id *head_commit_id)
{
const struct got_error *err = NULL;
- struct got_object_id *id_in_head = NULL, *id = NULL;
+ struct got_object_id *id = NULL;
struct got_commit_object *commit = NULL;
- char *path = NULL;
const char *ct_path = ct->in_repo_path;
while (ct_path[0] == '/')
ct_path++;
- /*
- * Ensure that no modifications were made to files *and their parents*
- * in commits between the file's base commit and the branch head.
- *
- * Checking the parents is important for detecting conflicting tree
- * configurations (files or parent folders might have been moved,
- * deleted, added again, etc.). Such changes need to be merged with
- * local changes before a commit can occur.
- *
- * The implication is that the file's (parent) entry in the root
- * directory must have the same ID in all relevant commits.
- */
if (ct->status != GOT_STATUS_ADD) {
- struct got_object_qid *pid;
- char *slash;
- struct got_object_id *root_entry_id = NULL;
-
/* Trivial case: base commit == head commit */
if (got_object_id_cmp(ct->base_commit_id, head_commit_id) == 0)
return NULL;
-
- /* Compute the path to the root directory's entry. */
- path = strdup(ct_path);
- if (path == NULL) {
- err = got_error_from_errno("strdup");
- goto done;
- }
- slash = strchr(path, '/');
- if (slash)
- *slash = '\0';
-
- err = got_object_open_as_commit(&commit, repo, head_commit_id);
- if (err)
- goto done;
-
- err = got_object_id_by_path(&root_entry_id, repo,
- head_commit_id, path);
- if (err)
+ /*
+ * Ensure file content which local changes were based
+ * on matches file content in the branch head.
+ */
+ err = got_object_id_by_path(&id, repo, head_commit_id, ct_path);
+ if (err) {
+ if (err->code != GOT_ERR_NO_TREE_ENTRY)
+ goto done;
+ err = got_error(GOT_ERR_COMMIT_OUT_OF_DATE);
goto done;
-
- pid = SIMPLEQ_FIRST(got_object_commit_get_parent_ids(commit));
- while (pid) {
- struct got_commit_object *pcommit;
-
- err = got_object_id_by_path(&id, repo, pid->id, path);
- if (err) {
- if (err->code != GOT_ERR_NO_TREE_ENTRY)
- goto done;
- err = NULL;
- break;
- }
-
- err = got_object_id_by_path(&id, repo, pid->id, path);
- if (err)
- goto done;
-
- if (got_object_id_cmp(id, root_entry_id) != 0) {
- err = got_error(GOT_ERR_COMMIT_OUT_OF_DATE);
- break;
- }
-
- if (got_object_id_cmp(pid->id, ct->base_commit_id) == 0)
- break; /* all relevant commits scanned */
-
- err = got_object_open_as_commit(&pcommit, repo,
- pid->id);
- if (err)
- goto done;
-
- got_object_commit_close(commit);
- commit = pcommit;
- pid = SIMPLEQ_FIRST(got_object_commit_get_parent_ids(
- commit));
- }
+ } else if (got_object_id_cmp(id, ct->base_blob_id) != 0)
+ err = got_error(GOT_ERR_COMMIT_OUT_OF_DATE);
} else {
/* Require that added files don't exist in the branch head. */
- err = got_object_id_by_path(&id_in_head, repo, head_commit_id,
- ct_path);
+ err = got_object_id_by_path(&id, repo, head_commit_id, ct_path);
if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
goto done;
- err = id_in_head ? got_error(GOT_ERR_COMMIT_OUT_OF_DATE) : NULL;
+ err = id ? got_error(GOT_ERR_COMMIT_OUT_OF_DATE) : NULL;
}
done:
if (commit)
got_object_commit_close(commit);
- free(id_in_head);
free(id);
- free(path);
return err;
}
blob - 6764523b2fe96ef5bcc178f254d6572792056e84
blob + 6eabac87ba0296af5f7ccf17446b0ce88a4c3244
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
test_done "$testroot" "$ret"
return 1
fi
+
+ echo "psi changed zeta with git" > $testroot/repo/epsilon/zeta
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "changing zeta with git"
echo "modified zeta" > $testroot/wt/epsilon/zeta
(cd $testroot/wt && got commit -m "changed zeta" > $testroot/stdout \
(cd $testroot/wt && got update > $testroot/stdout)
+ echo "U epsilon/psi" > $testroot/stdout.expected
+ echo "C epsilon/zeta" >> $testroot/stdout.expected
echo -n "Updated to commit " >> $testroot/stdout.expected
git_show_head $testroot/repo >> $testroot/stdout.expected
echo >> $testroot/stdout.expected
return 1
fi
+ # resolve conflict
+ echo "modified zeta with got and git" > $testroot/wt/epsilon/zeta
+
(cd $testroot/wt && got commit -m "changed zeta" > $testroot/stdout)
local head_rev=`git_show_head $testroot/repo`