Commit Diff


commit - e4b9a50c4562bd5527f8a0a3c8c754c2c95031ca
commit + 9bead371155cd3f955ba6699b0819df23f008bea
blob - d13a217315b4bc76901ed6b4828f4641abb540b2
blob + 1103157f40a2fc20de0d14bda891787ffdfeeaad
--- lib/worktree.c
+++ lib/worktree.c
@@ -3299,102 +3299,40 @@ check_ct_out_of_date(struct got_commitable *ct, struct
 	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
@@ -1458,6 +1458,10 @@ function test_update_bumps_base_commit_id {
 		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 \
@@ -1475,6 +1479,8 @@ function test_update_bumps_base_commit_id {
 
 	(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
@@ -1486,6 +1492,9 @@ function test_update_bumps_base_commit_id {
 		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`