In the case where git-receive-pack(1) receives only commands which delete references, then per technical specification the client MUST NOT send a packfile. As a result, we know that no new objects have been received, which makes it a moot point to check whether all received objects are fully connected. Fix this by not doing a connectivity check in case there were no pushed objects. Given that git-rev-walk(1) with only negative references will not do any graph walk, no performance improvements are to be expected. Conceptionally, it is still the right thing to do though. The following tests were executed on linux.git and back up above expectation: Test origin/master HEAD --------------------------------------------------------------------------------------------------------- 5400.4: empty receive-pack updated:new 178.36(428.22+164.36) 177.62(421.33+164.48) -0.4% 5400.7: clone receive-pack updated:new 0.10(0.08+0.02) 0.10(0.08+0.02) +0.0% 5400.9: clone receive-pack updated:main 0.10(0.08+0.02) 0.11(0.08+0.02) +10.0% 5400.11: clone receive-pack main~10:main 0.15(0.11+0.04) 0.15(0.10+0.05) +0.0% 5400.13: clone receive-pack :main 0.01(0.00+0.01) 0.01(0.01+0.00) +0.0% 5400.16: clone_bitmap receive-pack updated:new 0.10(0.07+0.02) 0.09(0.06+0.02) -10.0% 5400.18: clone_bitmap receive-pack updated:main 0.10(0.07+0.02) 0.10(0.08+0.02) +0.0% 5400.20: clone_bitmap receive-pack main~10:main 0.15(0.11+0.03) 0.15(0.12+0.03) +0.0% 5400.22: clone_bitmap receive-pack :main 0.02(0.01+0.01) 0.01(0.00+0.00) -50.0% 5400.25: extrarefs receive-pack updated:new 32.34(20.72+11.86) 32.56(20.82+11.95) +0.7% 5400.27: extrarefs receive-pack updated:main 32.42(21.02+11.61) 32.52(20.64+12.10) +0.3% 5400.29: extrarefs receive-pack main~10:main 32.53(20.74+12.01) 32.39(20.63+11.97) -0.4% 5400.31: extrarefs receive-pack :main 7.13(3.53+3.59) 7.15(3.80+3.34) +0.3% 5400.34: extrarefs_bitmap receive-pack updated:new 32.55(20.72+12.04) 32.65(20.68+12.18) +0.3% 5400.36: extrarefs_bitmap receive-pack updated:main 32.50(20.90+11.86) 32.67(20.93+11.94) +0.5% 5400.38: extrarefs_bitmap receive-pack main~10:main 32.43(20.88+11.75) 32.35(20.68+11.89) -0.2% 5400.40: extrarefs_bitmap receive-pack :main 7.21(3.58+3.63) 7.18(3.61+3.57) -0.4% Signed-off-by: Patrick Steinhardt --- builtin/receive-pack.c | 49 ++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index a34742513a..b9263cec15 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1918,11 +1918,8 @@ static void execute_commands(struct command *commands, struct shallow_info *si, const struct string_list *push_options) { - struct check_connected_options opt = CHECK_CONNECTED_INIT; struct command *cmd; struct iterate_data data; - struct async muxer; - int err_fd = 0; int run_proc_receive = 0; if (unpacker_error) { @@ -1931,25 +1928,39 @@ 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 */ - } - data.cmds = commands; data.si = si; - opt.err_fd = err_fd; - opt.progress = err_fd && !quiet; - opt.env = tmp_objdir_env(tmp_objdir); - if (check_connected(iterate_receive_command_list, &data, &opt)) - set_connectivity_errors(commands, si); - if (use_sideband) - finish_async(&muxer); + /* + * If received commands only consist of deletions, then the client MUST + * NOT send a packfile because there cannot be any new objects in the + * first place. As a result, we do not set up a quarantine environment + * because we know no new objects will be received. And that in turn + * means that we can skip connectivity checks here. + */ + if (tmp_objdir) { + struct check_connected_options opt = CHECK_CONNECTED_INIT; + struct async muxer; + int err_fd = 0; + + 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 */ + } + + opt.err_fd = err_fd; + opt.progress = err_fd && !quiet; + opt.env = tmp_objdir_env(tmp_objdir); + 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); -- 2.32.0