Merge branch 'jt/receive-pack-skip-connectivity-check'
"git receive-pack" optionally learns not to care about connectivity check, which can be useful when the repository arranges to ensure connectivity by some other means. * jt/receive-pack-skip-connectivity-check: builtin/receive-pack: add option to skip connectivity check t5410: test receive-pack connectivity checkmaint
commit
b4847a4477
|
|
@ -46,6 +46,18 @@ OPTIONS
|
|||
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
|
||||
`--http-backend-info-refs` in linkgit:git-upload-pack[1].
|
||||
|
||||
--skip-connectivity-check::
|
||||
Bypasses the connectivity checks that validate the existence of all
|
||||
objects in the transitive closure of reachable objects. This option is
|
||||
intended for server operators that want to implement their own object
|
||||
connectivity validation outside of Git. This is useful in such cases
|
||||
where the server-side knows additional information about how Git is
|
||||
being used and thus can rely on certain guarantees to more efficiently
|
||||
compute object connectivity that Git itself cannot make. Usage of this
|
||||
option without a reliable external mechanism to ensure full reachable
|
||||
object connectivity risks corrupting the repository and should not be
|
||||
used in the general case.
|
||||
|
||||
PRE-RECEIVE HOOK
|
||||
----------------
|
||||
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ static int prefer_ofs_delta = 1;
|
|||
static int auto_update_server_info;
|
||||
static int auto_gc = 1;
|
||||
static int reject_thin;
|
||||
static int skip_connectivity_check;
|
||||
static int stateless_rpc;
|
||||
static const char *service_dir;
|
||||
static const char *head_name;
|
||||
|
|
@ -1938,28 +1939,30 @@ static void execute_commands(struct command *commands,
|
|||
return;
|
||||
}
|
||||
|
||||
if (use_sideband) {
|
||||
memset(&muxer, 0, sizeof(muxer));
|
||||
muxer.proc = copy_to_sideband;
|
||||
muxer.in = -1;
|
||||
if (!start_async(&muxer))
|
||||
err_fd = muxer.in;
|
||||
/* ...else, continue without relaying sideband */
|
||||
if (!skip_connectivity_check) {
|
||||
if (use_sideband) {
|
||||
memset(&muxer, 0, sizeof(muxer));
|
||||
muxer.proc = copy_to_sideband;
|
||||
muxer.in = -1;
|
||||
if (!start_async(&muxer))
|
||||
err_fd = muxer.in;
|
||||
/* ...else, continue without relaying sideband */
|
||||
}
|
||||
|
||||
data.cmds = commands;
|
||||
data.si = si;
|
||||
opt.err_fd = err_fd;
|
||||
opt.progress = err_fd && !quiet;
|
||||
opt.env = tmp_objdir_env(tmp_objdir);
|
||||
opt.exclude_hidden_refs_section = "receive";
|
||||
|
||||
if (check_connected(iterate_receive_command_list, &data, &opt))
|
||||
set_connectivity_errors(commands, si);
|
||||
|
||||
if (use_sideband)
|
||||
finish_async(&muxer);
|
||||
}
|
||||
|
||||
data.cmds = commands;
|
||||
data.si = si;
|
||||
opt.err_fd = err_fd;
|
||||
opt.progress = err_fd && !quiet;
|
||||
opt.env = tmp_objdir_env(tmp_objdir);
|
||||
opt.exclude_hidden_refs_section = "receive";
|
||||
|
||||
if (check_connected(iterate_receive_command_list, &data, &opt))
|
||||
set_connectivity_errors(commands, si);
|
||||
|
||||
if (use_sideband)
|
||||
finish_async(&muxer);
|
||||
|
||||
reject_updates_to_hidden(commands);
|
||||
|
||||
/*
|
||||
|
|
@ -2519,6 +2522,7 @@ int cmd_receive_pack(int argc,
|
|||
|
||||
struct option options[] = {
|
||||
OPT__QUIET(&quiet, N_("quiet")),
|
||||
OPT_HIDDEN_BOOL(0, "skip-connectivity-check", &skip_connectivity_check, NULL),
|
||||
OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
|
||||
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
|
||||
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ integration_tests = [
|
|||
't5407-post-rewrite-hook.sh',
|
||||
't5408-send-pack-stdin.sh',
|
||||
't5409-colorize-remote-messages.sh',
|
||||
't5410-receive-pack-alternates.sh',
|
||||
't5410-receive-pack.sh',
|
||||
't5411-proc-receive-hook.sh',
|
||||
't5500-fetch-pack.sh',
|
||||
't5501-fetch-push-alternates.sh',
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='git receive-pack with alternate ref filtering'
|
||||
|
||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
test_commit base &&
|
||||
git clone -s --bare . fork &&
|
||||
git checkout -b public/branch main &&
|
||||
test_commit public &&
|
||||
git checkout -b private/branch main &&
|
||||
test_commit private
|
||||
'
|
||||
|
||||
extract_haves () {
|
||||
depacketize | sed -n 's/^\([^ ][^ ]*\) \.have/\1/p'
|
||||
}
|
||||
|
||||
test_expect_success 'with core.alternateRefsCommand' '
|
||||
write_script fork/alternate-refs <<-\EOF &&
|
||||
git --git-dir="$1" for-each-ref \
|
||||
--format="%(objectname)" \
|
||||
refs/heads/public/
|
||||
EOF
|
||||
test_config -C fork core.alternateRefsCommand ./alternate-refs &&
|
||||
git rev-parse public/branch >expect &&
|
||||
printf "0000" | git receive-pack fork >actual &&
|
||||
extract_haves <actual >actual.haves &&
|
||||
test_cmp expect actual.haves
|
||||
'
|
||||
|
||||
test_expect_success 'with core.alternateRefsPrefixes' '
|
||||
test_config -C fork core.alternateRefsPrefixes "refs/heads/private" &&
|
||||
git rev-parse private/branch >expect &&
|
||||
printf "0000" | git receive-pack fork >actual &&
|
||||
extract_haves <actual >actual.haves &&
|
||||
test_cmp expect actual.haves
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='git receive-pack'
|
||||
|
||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
test_commit base &&
|
||||
git clone -s --bare . fork &&
|
||||
git checkout -b public/branch main &&
|
||||
test_commit public &&
|
||||
git checkout -b private/branch main &&
|
||||
test_commit private
|
||||
'
|
||||
|
||||
extract_haves () {
|
||||
depacketize | sed -n 's/^\([^ ][^ ]*\) \.have/\1/p'
|
||||
}
|
||||
|
||||
test_expect_success 'with core.alternateRefsCommand' '
|
||||
write_script fork/alternate-refs <<-\EOF &&
|
||||
git --git-dir="$1" for-each-ref \
|
||||
--format="%(objectname)" \
|
||||
refs/heads/public/
|
||||
EOF
|
||||
test_config -C fork core.alternateRefsCommand ./alternate-refs &&
|
||||
git rev-parse public/branch >expect &&
|
||||
printf "0000" | git receive-pack fork >actual &&
|
||||
extract_haves <actual >actual.haves &&
|
||||
test_cmp expect actual.haves
|
||||
'
|
||||
|
||||
test_expect_success 'with core.alternateRefsPrefixes' '
|
||||
test_config -C fork core.alternateRefsPrefixes "refs/heads/private" &&
|
||||
git rev-parse private/branch >expect &&
|
||||
printf "0000" | git receive-pack fork >actual &&
|
||||
extract_haves <actual >actual.haves &&
|
||||
test_cmp expect actual.haves
|
||||
'
|
||||
|
||||
test_expect_success 'receive-pack missing objects fails connectivity check' '
|
||||
test_when_finished rm -rf repo remote.git setup.git &&
|
||||
|
||||
git init repo &&
|
||||
git -C repo commit --allow-empty -m 1 &&
|
||||
git clone --bare repo setup.git &&
|
||||
git -C repo commit --allow-empty -m 2 &&
|
||||
|
||||
# Capture git-send-pack(1) output sent to git-receive-pack(1).
|
||||
git -C repo send-pack ../setup.git --all \
|
||||
--receive-pack="tee ${SQ}$(pwd)/out${SQ} | git-receive-pack" &&
|
||||
|
||||
# Replay captured git-send-pack(1) output on new empty repository.
|
||||
git init --bare remote.git &&
|
||||
git receive-pack remote.git <out >actual 2>err &&
|
||||
|
||||
test_grep "missing necessary objects" actual &&
|
||||
test_grep "fatal: Failed to traverse parents" err &&
|
||||
test_must_fail git -C remote.git cat-file -e $(git -C repo rev-parse HEAD)
|
||||
'
|
||||
|
||||
test_expect_success 'receive-pack missing objects bypasses connectivity check' '
|
||||
test_when_finished rm -rf repo remote.git setup.git &&
|
||||
|
||||
git init repo &&
|
||||
git -C repo commit --allow-empty -m 1 &&
|
||||
git clone --bare repo setup.git &&
|
||||
git -C repo commit --allow-empty -m 2 &&
|
||||
|
||||
# Capture git-send-pack(1) output sent to git-receive-pack(1).
|
||||
git -C repo send-pack ../setup.git --all \
|
||||
--receive-pack="tee ${SQ}$(pwd)/out${SQ} | git-receive-pack" &&
|
||||
|
||||
# Replay captured git-send-pack(1) output on new empty repository.
|
||||
git init --bare remote.git &&
|
||||
git receive-pack --skip-connectivity-check remote.git <out >actual 2>err &&
|
||||
|
||||
test_grep ! "missing necessary objects" actual &&
|
||||
test_must_be_empty err &&
|
||||
git -C remote.git cat-file -e $(git -C repo rev-parse HEAD) &&
|
||||
test_must_fail git -C remote.git rev-list $(git -C repo rev-parse HEAD)
|
||||
'
|
||||
|
||||
test_done
|
||||
Loading…
Reference in New Issue