commit - 7755e2f80723b22eb4fcc203ffd75608db7055c7
commit + cc88020e952af813c1e01b91ab6516969562e972
blob - 317d11a2dde1181dd8dca488ba5ed7f353895c70
blob + eefdc7de1087c2a2956a9fdbbd25ad81719a783c
--- gotd/repo_write.c
+++ gotd/repo_write.c
int nref_updates;
int nref_del;
int nref_new;
+ int nref_move;
} repo_write_client;
static volatile sig_atomic_t sigint_received;
client->nref_updates = 0;
client->nref_del = 0;
client->nref_new = 0;
+ client->nref_move = 0;
imsg_init(&ibuf, client_fd);
}
static const struct got_error *
+ensure_all_objects_exist_locally(struct gotd_ref_updates *ref_updates)
+{
+ const struct got_error *err = NULL;
+ struct gotd_ref_update *ref_update;
+ struct got_object *obj;
+
+ STAILQ_FOREACH(ref_update, ref_updates, entry) {
+ err = got_object_open(&obj, repo_write.repo,
+ &ref_update->new_id);
+ if (err)
+ return err;
+ got_object_close(obj);
+ }
+
+ return NULL;
+}
+
+static const struct got_error *
recv_packdata(off_t *outsize, uint32_t *nobj, uint8_t *sha1,
int infd, int outfd)
{
client->nref_updates == client->nref_new)
return NULL;
- return got_error_msg(GOT_ERR_BAD_PACKFILE,
- "bad packfile with zero objects");
+ /*
+ * Clients which only move existing refs will send us an empty
+ * pack file. All referenced objects must exist locally.
+ */
+ err = ensure_all_objects_exist_locally(&client->ref_updates);
+ if (err) {
+ if (err->code != GOT_ERR_NO_OBJ)
+ return err;
+ return got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "bad packfile with zero objects");
+ }
+
+ client->nref_move = client->nref_updates;
+ return NULL;
}
log_debug("expecting %d objects", *nobj);
if (nobj == 0 &&
client->nref_del > 0 &&
client->nref_updates == client->nref_del)
+ goto done;
+
+ /*
+ * Clients which only move existing refs will send us an empty
+ * pack file. All referenced objects must exist locally.
+ */
+ if (nobj == 0 &&
+ pack_filesize == sizeof(struct got_packfile_hdr) &&
+ client->nref_move > 0 &&
+ client->nref_updates == client->nref_move)
goto done;
pack->filesize = pack_filesize;
blob - d75e82812ee4b8e5c04144e1f6f981703b541699
blob + daff924b47ca360160665215790f700bf0f8bfda
--- regress/gotd/repo_write.sh
+++ regress/gotd/repo_write.sh
test_done "$testroot" 0
}
+test_rewind_branch() {
+ local testroot=`test_init rewind_branch 1`
+
+ got clone -a -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got clone failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ got checkout -q $testroot/repo-clone $testroot/wt >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got checkout failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ (cd $testroot/wt && got branch foo) >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got branch failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ echo modified alpha > $testroot/wt/alpha
+ (cd $testroot/wt && got commit -m 'edit alpha') >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got commit failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ if ! got send -q -r $testroot/repo-clone -b foo; then
+ echo "got send failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ local foo_id=`git_show_branch_head "$testroot/repo-clone" foo`
+ local main_id=`git_show_branch_head "$testroot/repo-clone" main`
+ local tag_id=`got ref -r "$testroot/repo-clone" -l refs/tags/1.0 | \
+ awk '{print $2}'`
+
+ (cd $testroot/wt && got update -c $main_id) >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got update failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ (cd $testroot/wt && got histedit -d) >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got histedit failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ if ! got send -q -r $testroot/repo-clone -f -b foo; then
+ echo "got send failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ got fetch -q -r $testroot/repo-clone -l >$testroot/refs
+ cat <<EOF >$testroot/refs.expected
+HEAD: refs/heads/main
+HEAD: $main_id
+refs/heads/foo: $main_id
+refs/heads/main: $main_id
+refs/tags/1.0: $tag_id
+EOF
+ if ! cmp -s $testroot/refs.expected $testroot/refs; then
+ diff -u $testroot/refs.expected $testroot/refs
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ test_done "$testroot" 0
+}
+
test_parseargs "$@"
run_test test_send_basic
run_test test_fetch_more_history
run_test test_send_new_empty_branch
run_test test_delete_branch
+run_test test_rewind_branch