Merge branch 'jk/push-progress'
"git push" and "git clone" learned to give better progress meters to the end user who is waiting on the terminal. * jk/push-progress: receive-pack: send keepalives during quiet periods receive-pack: turn on connectivity progress receive-pack: relay connectivity errors to sideband receive-pack: turn on index-pack resolving progress index-pack: add flag for showing delta-resolution progress clone: use a real progress meter for connectivity check check_connected: add progress flag check_connected: relay errors to alternate descriptor check_everything_connected: use a struct with named options check_everything_connected: convert to argv_array rev-list: add optional progress reporting check_everything_connected: always pass --quiet to rev-list
This commit is contained in:
@ -78,6 +78,13 @@ static long nonce_stamp_slop;
|
||||
static unsigned long nonce_stamp_slop_limit;
|
||||
static struct ref_transaction *transaction;
|
||||
|
||||
static enum {
|
||||
KEEPALIVE_NEVER = 0,
|
||||
KEEPALIVE_AFTER_NUL,
|
||||
KEEPALIVE_ALWAYS
|
||||
} use_keepalive;
|
||||
static int keepalive_in_sec = 5;
|
||||
|
||||
static enum deny_action parse_deny_action(const char *var, const char *value)
|
||||
{
|
||||
if (value) {
|
||||
@ -200,6 +207,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(var, "receive.keepalive") == 0) {
|
||||
keepalive_in_sec = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
@ -328,10 +340,60 @@ static void rp_error(const char *err, ...)
|
||||
static int copy_to_sideband(int in, int out, void *arg)
|
||||
{
|
||||
char data[128];
|
||||
int keepalive_active = 0;
|
||||
|
||||
if (keepalive_in_sec <= 0)
|
||||
use_keepalive = KEEPALIVE_NEVER;
|
||||
if (use_keepalive == KEEPALIVE_ALWAYS)
|
||||
keepalive_active = 1;
|
||||
|
||||
while (1) {
|
||||
ssize_t sz = xread(in, data, sizeof(data));
|
||||
ssize_t sz;
|
||||
|
||||
if (keepalive_active) {
|
||||
struct pollfd pfd;
|
||||
int ret;
|
||||
|
||||
pfd.fd = in;
|
||||
pfd.events = POLLIN;
|
||||
ret = poll(&pfd, 1, 1000 * keepalive_in_sec);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
} else if (ret == 0) {
|
||||
/* no data; send a keepalive packet */
|
||||
static const char buf[] = "0005\1";
|
||||
write_or_die(1, buf, sizeof(buf) - 1);
|
||||
continue;
|
||||
} /* else there is actual data to read */
|
||||
}
|
||||
|
||||
sz = xread(in, data, sizeof(data));
|
||||
if (sz <= 0)
|
||||
break;
|
||||
|
||||
if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active) {
|
||||
const char *p = memchr(data, '\0', sz);
|
||||
if (p) {
|
||||
/*
|
||||
* The NUL tells us to start sending keepalives. Make
|
||||
* sure we send any other data we read along
|
||||
* with it.
|
||||
*/
|
||||
keepalive_active = 1;
|
||||
send_sideband(1, 2, data, p - data, use_sideband);
|
||||
send_sideband(1, 2, p + 1, sz - (p - data + 1), use_sideband);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Either we're not looking for a NUL signal, or we didn't see
|
||||
* it yet; just pass along the data.
|
||||
*/
|
||||
send_sideband(1, 2, data, sz, use_sideband);
|
||||
}
|
||||
close(in);
|
||||
@ -761,7 +823,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
|
||||
{
|
||||
static struct lock_file shallow_lock;
|
||||
struct sha1_array extra = SHA1_ARRAY_INIT;
|
||||
const char *alt_file;
|
||||
struct check_connected_options opt = CHECK_CONNECTED_INIT;
|
||||
uint32_t mask = 1 << (cmd->index % 32);
|
||||
int i;
|
||||
|
||||
@ -773,9 +835,8 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
|
||||
!delayed_reachability_test(si, i))
|
||||
sha1_array_append(&extra, si->shallow->sha1[i]);
|
||||
|
||||
setup_alternate_shallow(&shallow_lock, &alt_file, &extra);
|
||||
if (check_shallow_connected(command_singleton_iterator,
|
||||
0, cmd, alt_file)) {
|
||||
setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra);
|
||||
if (check_connected(command_singleton_iterator, cmd, &opt)) {
|
||||
rollback_lock_file(&shallow_lock);
|
||||
sha1_array_clear(&extra);
|
||||
return -1;
|
||||
@ -1184,8 +1245,8 @@ static void set_connectivity_errors(struct command *commands,
|
||||
if (shallow_update && si->shallow_ref[cmd->index])
|
||||
/* to be checked in update_shallow_ref() */
|
||||
continue;
|
||||
if (!check_everything_connected(command_singleton_iterator,
|
||||
0, &singleton))
|
||||
if (!check_connected(command_singleton_iterator, &singleton,
|
||||
NULL))
|
||||
continue;
|
||||
cmd->error_string = "missing necessary objects";
|
||||
}
|
||||
@ -1343,9 +1404,12 @@ 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;
|
||||
unsigned char sha1[20];
|
||||
struct iterate_data data;
|
||||
struct async muxer;
|
||||
int err_fd = 0;
|
||||
|
||||
if (unpacker_error) {
|
||||
for (cmd = commands; cmd; cmd = cmd->next)
|
||||
@ -1353,11 +1417,25 @@ 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;
|
||||
if (check_everything_connected(iterate_receive_command_list, 0, &data))
|
||||
opt.err_fd = err_fd;
|
||||
opt.progress = err_fd && !quiet;
|
||||
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);
|
||||
|
||||
if (run_receive_hook(commands, "pre-receive", 0, push_options)) {
|
||||
@ -1591,6 +1669,10 @@ static const char *unpack(int err_fd, struct shallow_info *si)
|
||||
(uintmax_t)getpid(),
|
||||
hostname);
|
||||
|
||||
if (!quiet && err_fd)
|
||||
argv_array_push(&child.args, "--show-resolving-progress");
|
||||
if (use_sideband)
|
||||
argv_array_push(&child.args, "--report-end-of-input");
|
||||
if (fsck_objects)
|
||||
argv_array_pushf(&child.args, "--strict%s",
|
||||
fsck_msg_types.buf);
|
||||
@ -1620,6 +1702,7 @@ static const char *unpack_with_sideband(struct shallow_info *si)
|
||||
if (!use_sideband)
|
||||
return unpack(0, si);
|
||||
|
||||
use_keepalive = KEEPALIVE_AFTER_NUL;
|
||||
memset(&muxer, 0, sizeof(muxer));
|
||||
muxer.proc = copy_to_sideband;
|
||||
muxer.in = -1;
|
||||
@ -1811,6 +1894,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
unpack_status = unpack_with_sideband(&si);
|
||||
update_shallow_info(commands, &si, &ref);
|
||||
}
|
||||
use_keepalive = KEEPALIVE_ALWAYS;
|
||||
execute_commands(commands, unpack_status, &si,
|
||||
&push_options);
|
||||
if (pack_lockfile)
|
||||
|
Reference in New Issue
Block a user