2011-09-03 07:33:22 +08:00
|
|
|
#include "cache.h"
|
|
|
|
#include "run-command.h"
|
|
|
|
#include "sigchain.h"
|
|
|
|
#include "connected.h"
|
2013-05-26 09:16:17 +08:00
|
|
|
#include "transport.h"
|
2017-08-19 06:20:26 +08:00
|
|
|
#include "packfile.h"
|
2011-09-03 07:33:22 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we feed all the commits we want to verify to this command
|
|
|
|
*
|
2012-03-16 05:57:02 +08:00
|
|
|
* $ git rev-list --objects --stdin --not --all
|
2011-09-03 07:33:22 +08:00
|
|
|
*
|
|
|
|
* and if it does not error out, that means everything reachable from
|
2012-03-16 05:57:02 +08:00
|
|
|
* these commits locally exists and is connected to our existing refs.
|
|
|
|
* Note that this does _not_ validate the individual objects.
|
2011-09-03 07:33:22 +08:00
|
|
|
*
|
|
|
|
* Returns 0 if everything is connected, non-zero otherwise.
|
|
|
|
*/
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
int check_connected(sha1_iterate_fn fn, void *cb_data,
|
|
|
|
struct check_connected_options *opt)
|
2011-09-03 07:33:22 +08:00
|
|
|
{
|
2014-08-20 03:09:35 +08:00
|
|
|
struct child_process rev_list = CHILD_PROCESS_INIT;
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
struct check_connected_options defaults = CHECK_CONNECTED_INIT;
|
2011-09-03 07:33:22 +08:00
|
|
|
char commit[41];
|
|
|
|
unsigned char sha1[20];
|
2016-07-15 18:28:32 +08:00
|
|
|
int err = 0;
|
2013-05-26 09:16:17 +08:00
|
|
|
struct packed_git *new_pack = NULL;
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
struct transport *transport;
|
2014-07-01 00:58:51 +08:00
|
|
|
size_t base_len;
|
2011-09-03 07:33:22 +08:00
|
|
|
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
if (!opt)
|
|
|
|
opt = &defaults;
|
|
|
|
transport = opt->transport;
|
|
|
|
|
2016-07-15 18:32:03 +08:00
|
|
|
if (fn(cb_data, sha1)) {
|
|
|
|
if (opt->err_fd)
|
|
|
|
close(opt->err_fd);
|
2011-09-03 07:33:22 +08:00
|
|
|
return err;
|
2016-07-15 18:32:03 +08:00
|
|
|
}
|
2011-09-03 07:33:22 +08:00
|
|
|
|
2013-05-26 09:16:17 +08:00
|
|
|
if (transport && transport->smart_options &&
|
|
|
|
transport->smart_options->self_contained_and_connected &&
|
|
|
|
transport->pack_lockfile &&
|
2014-07-01 00:58:51 +08:00
|
|
|
strip_suffix(transport->pack_lockfile, ".keep", &base_len)) {
|
2013-05-26 09:16:17 +08:00
|
|
|
struct strbuf idx_file = STRBUF_INIT;
|
2014-07-01 00:58:51 +08:00
|
|
|
strbuf_add(&idx_file, transport->pack_lockfile, base_len);
|
2013-05-26 09:16:17 +08:00
|
|
|
strbuf_addstr(&idx_file, ".idx");
|
|
|
|
new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);
|
|
|
|
strbuf_release(&idx_file);
|
|
|
|
}
|
|
|
|
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
if (opt->shallow_file) {
|
2016-07-15 18:28:32 +08:00
|
|
|
argv_array_push(&rev_list.args, "--shallow-file");
|
check_everything_connected: use a struct with named options
The number of variants of check_everything_connected has
grown over the years, so that the "real" function takes
several possibly-zero, possibly-NULL arguments. We hid the
complexity behind some wrapper functions, but this doesn't
scale well when we want to add new options.
If we add more wrapper variants to handle the new options,
then we can get a combinatorial explosion when those options
might be used together (right now nobody wants to use both
"shallow" and "transport" together, so we get by with just a
few wrappers).
If instead we add new parameters to each function, each of
which can have a default value, then callers who want the
defaults end up with confusing invocations like:
check_everything_connected(fn, 0, data, -1, 0, NULL);
where it is unclear which parameter is which (and every
caller needs updated when we add new options).
Instead, let's add a struct to hold all of the optional
parameters. This is a little more verbose for the callers
(who have to declare the struct and fill it in), but it
makes their code much easier to follow, because every option
is named as it is set (and unused options do not have to be
mentioned at all).
Note that we could also stick the iteration function and its
callback data into the option struct, too. But since those
are required for each call, by avoiding doing so, we can let
very simple callers just pass "NULL" for the options and not
worry about the struct at all.
While we're touching each site, let's also rename the
function to check_connected(). The existing name was quite
long, and not all of the wrappers even used the full name.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-15 18:30:40 +08:00
|
|
|
argv_array_push(&rev_list.args, opt->shallow_file);
|
2013-12-05 21:02:46 +08:00
|
|
|
}
|
2016-07-15 18:28:32 +08:00
|
|
|
argv_array_push(&rev_list.args,"rev-list");
|
|
|
|
argv_array_push(&rev_list.args, "--objects");
|
|
|
|
argv_array_push(&rev_list.args, "--stdin");
|
|
|
|
argv_array_push(&rev_list.args, "--not");
|
|
|
|
argv_array_push(&rev_list.args, "--all");
|
|
|
|
argv_array_push(&rev_list.args, "--quiet");
|
2016-07-15 18:32:28 +08:00
|
|
|
if (opt->progress)
|
|
|
|
argv_array_pushf(&rev_list.args, "--progress=%s",
|
|
|
|
_("Checking connectivity"));
|
2011-09-03 07:33:22 +08:00
|
|
|
|
|
|
|
rev_list.git_cmd = 1;
|
2016-10-04 04:49:08 +08:00
|
|
|
rev_list.env = opt->env;
|
2011-09-03 07:33:22 +08:00
|
|
|
rev_list.in = -1;
|
|
|
|
rev_list.no_stdout = 1;
|
2016-07-15 18:32:03 +08:00
|
|
|
if (opt->err_fd)
|
|
|
|
rev_list.err = opt->err_fd;
|
|
|
|
else
|
|
|
|
rev_list.no_stderr = opt->quiet;
|
|
|
|
|
2011-09-03 07:33:22 +08:00
|
|
|
if (start_command(&rev_list))
|
|
|
|
return error(_("Could not run 'git rev-list'"));
|
|
|
|
|
|
|
|
sigchain_push(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
commit[40] = '\n';
|
|
|
|
do {
|
2013-05-26 09:16:17 +08:00
|
|
|
/*
|
|
|
|
* If index-pack already checked that:
|
|
|
|
* - there are no dangling pointers in the new pack
|
|
|
|
* - the pack is self contained
|
|
|
|
* Then if the updated ref is in the new pack, then we
|
|
|
|
* are sure the ref is good and not sending it to
|
|
|
|
* rev-list for verification.
|
|
|
|
*/
|
|
|
|
if (new_pack && find_pack_entry_one(sha1, new_pack))
|
|
|
|
continue;
|
|
|
|
|
2011-09-03 07:33:22 +08:00
|
|
|
memcpy(commit, sha1_to_hex(sha1), 40);
|
|
|
|
if (write_in_full(rev_list.in, commit, 41) < 0) {
|
|
|
|
if (errno != EPIPE && errno != EINVAL)
|
2016-05-08 17:47:39 +08:00
|
|
|
error_errno(_("failed write to rev-list"));
|
2011-09-03 07:33:22 +08:00
|
|
|
err = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (!fn(cb_data, sha1));
|
|
|
|
|
2016-05-08 17:47:39 +08:00
|
|
|
if (close(rev_list.in))
|
|
|
|
err = error_errno(_("failed to close rev-list's stdin"));
|
2011-09-03 07:33:22 +08:00
|
|
|
|
|
|
|
sigchain_pop(SIGPIPE);
|
|
|
|
return finish_command(&rev_list) || err;
|
|
|
|
}
|