commit 9bead371155cd3f955ba6699b0819df23f008bea from: Stefan Sperling date: Sun Jul 28 08:28:25 2019 UTC relax commit out-of-dateness check: consider file content only 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`