commit c932eeeb83c00ba282780d657b539e342d092311 from: Stefan Sperling date: Wed May 22 08:25:50 2019 UTC make 'got update' bump the base commit ID of unchanged files This change makes it actually possible to get around commit-time out-of-dateness by running 'got update'. The test added with this commit shows that our out-of-dateness check is currently too simplistic; an update is required between any two commit operations! It would be better to allow commits to proceed until a situation arises where file content must be merged. commit - e4d984c230e887c67692cfcbb7624ab2ccf95e2d commit + c932eeeb83c00ba282780d657b539e342d092311 blob - 813c2606897283a1597ed1e26f0709ae9ddd2df2 blob + c0b4a22f88ac66488a7663be09009008dd5b3cd0 --- lib/worktree.c +++ lib/worktree.c @@ -1446,7 +1446,30 @@ done: } return err; } + +struct bump_base_commit_id_arg { + struct got_object_id *base_commit_id; + const char *path; + size_t path_len; + const char *entry_name; +}; +/* Bump base commit ID of all files within an updated part of the work tree. */ +static const struct got_error * +bump_base_commit_id(void *arg, struct got_fileindex_entry *ie) +{ + struct bump_base_commit_id_arg *a = arg; + + if (a->entry_name) { + if (strcmp(ie->path, a->path) != 0) + return NULL; + } else if (!got_path_is_child(ie->path, a->path, a->path_len)) + return NULL; + + memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH); + return NULL; +} + const struct got_error * got_worktree_checkout_files(struct got_worktree *worktree, const char *path, struct got_repository *repo, got_worktree_checkout_cb progress_cb, @@ -1584,6 +1607,18 @@ got_worktree_checkout_files(struct got_worktree *workt checkout_err = got_fileindex_diff_tree(fileindex, tree, relpath, entry_name, repo, &diff_cb, &arg); + if (checkout_err == NULL) { + struct bump_base_commit_id_arg bbc_arg; + bbc_arg.base_commit_id = worktree->base_commit_id; + bbc_arg.entry_name = entry_name; + bbc_arg.path = path; + bbc_arg.path_len = strlen(path); + err = got_fileindex_for_each_entry_safe(fileindex, + bump_base_commit_id, &bbc_arg); + if (err) + goto done; + } + /* Try to sync the fileindex back to disk in any case. */ err = got_fileindex_write(fileindex, new_index); if (err) blob - da703088394f8fa0cbbb0dfdeeb5ccd9a3bc0370 blob + 13de6ccc78b1fffae1913d1010e3af7708972c4e --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -1423,7 +1423,73 @@ function test_update_to_commit_on_wrong_branch { test_done "$testroot" "$ret" } + +function test_update_bumps_base_commit_id { + local testroot=`test_init update_to_commit_on_wrong_branch` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + echo "modified alpha" > $testroot/wt/alpha + (cd $testroot/wt && got commit -m "changed alpha" > $testroot/stdout) + + local head_rev=`git_show_head $testroot/repo` + echo "M alpha" > $testroot/stdout.expected + echo "created commit $head_rev" >> $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 "modified beta" > $testroot/wt/beta + (cd $testroot/wt && got commit -m "changed beta" > $testroot/stdout \ + 2> $testroot/stderr) + + echo -n "" > $testroot/stdout.expected + echo "got: work tree must be updated before these changes can be committed" > $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 + fi + + # XXX At present, got requires users to run 'update' after 'commit'. + (cd $testroot/wt && got update > $testroot/stdout) + + echo "Already up-to-date" > $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 + + (cd $testroot/wt && got commit -m "changed beta" > $testroot/stdout) + + local head_rev=`git_show_head $testroot/repo` + echo "M beta" > $testroot/stdout.expected + echo "created commit $head_rev" >> $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 + + test_done "$testroot" "$ret" +} + run_test test_update_basic run_test test_update_adds_file run_test test_update_deletes_file @@ -1452,3 +1518,4 @@ run_test test_update_partial_dir run_test test_update_moved_branch_ref run_test test_update_to_another_branch run_test test_update_to_commit_on_wrong_branch +run_test test_update_bumps_base_commit_id