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 check
This commit is contained in:
@@ -46,6 +46,18 @@ OPTIONS
|
|||||||
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
|
`$GIT_URL/info/refs?service=git-receive-pack` requests. See
|
||||||
`--http-backend-info-refs` in linkgit:git-upload-pack[1].
|
`--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
|
PRE-RECEIVE HOOK
|
||||||
----------------
|
----------------
|
||||||
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
|
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_update_server_info;
|
||||||
static int auto_gc = 1;
|
static int auto_gc = 1;
|
||||||
static int reject_thin;
|
static int reject_thin;
|
||||||
|
static int skip_connectivity_check;
|
||||||
static int stateless_rpc;
|
static int stateless_rpc;
|
||||||
static const char *service_dir;
|
static const char *service_dir;
|
||||||
static const char *head_name;
|
static const char *head_name;
|
||||||
@@ -1938,28 +1939,30 @@ static void execute_commands(struct command *commands,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_sideband) {
|
if (!skip_connectivity_check) {
|
||||||
memset(&muxer, 0, sizeof(muxer));
|
if (use_sideband) {
|
||||||
muxer.proc = copy_to_sideband;
|
memset(&muxer, 0, sizeof(muxer));
|
||||||
muxer.in = -1;
|
muxer.proc = copy_to_sideband;
|
||||||
if (!start_async(&muxer))
|
muxer.in = -1;
|
||||||
err_fd = muxer.in;
|
if (!start_async(&muxer))
|
||||||
/* ...else, continue without relaying sideband */
|
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);
|
reject_updates_to_hidden(commands);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2519,6 +2522,7 @@ int cmd_receive_pack(int argc,
|
|||||||
|
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT__QUIET(&quiet, N_("quiet")),
|
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, "stateless-rpc", &stateless_rpc, NULL),
|
||||||
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
|
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
|
||||||
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
|
||||||
|
|||||||
@@ -629,7 +629,7 @@ integration_tests = [
|
|||||||
't5407-post-rewrite-hook.sh',
|
't5407-post-rewrite-hook.sh',
|
||||||
't5408-send-pack-stdin.sh',
|
't5408-send-pack-stdin.sh',
|
||||||
't5409-colorize-remote-messages.sh',
|
't5409-colorize-remote-messages.sh',
|
||||||
't5410-receive-pack-alternates.sh',
|
't5410-receive-pack.sh',
|
||||||
't5411-proc-receive-hook.sh',
|
't5411-proc-receive-hook.sh',
|
||||||
't5500-fetch-pack.sh',
|
't5500-fetch-pack.sh',
|
||||||
't5501-fetch-push-alternates.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
|
|
||||||
87
t/t5410-receive-pack.sh
Executable file
87
t/t5410-receive-pack.sh
Executable file
@@ -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
|
||||||
Reference in New Issue
Block a user