Fix sparse warnings
Fix warnings from 'make check'.
- These files don't include 'builtin.h' causing sparse to complain that
cmd_* isn't declared:
builtin/clone.c:364, builtin/fetch-pack.c:797,
builtin/fmt-merge-msg.c:34, builtin/hash-object.c:78,
builtin/merge-index.c:69, builtin/merge-recursive.c:22
builtin/merge-tree.c:341, builtin/mktag.c:156, builtin/notes.c:426
builtin/notes.c:822, builtin/pack-redundant.c:596,
builtin/pack-refs.c:10, builtin/patch-id.c:60, builtin/patch-id.c:149,
builtin/remote.c:1512, builtin/remote-ext.c:240,
builtin/remote-fd.c:53, builtin/reset.c:236, builtin/send-pack.c:384,
builtin/unpack-file.c:25, builtin/var.c:75
- These files have symbols which should be marked static since they're
only file scope:
submodule.c:12, diff.c:631, replace_object.c:92, submodule.c:13,
submodule.c:14, trace.c:78, transport.c:195, transport-helper.c:79,
unpack-trees.c:19, url.c:3, url.c:18, url.c:104, url.c:117, url.c:123,
url.c:129, url.c:136, thread-utils.c:21, thread-utils.c:48
- These files redeclare symbols to be different types:
builtin/index-pack.c:210, parse-options.c:564, parse-options.c:571,
usage.c:49, usage.c:58, usage.c:63, usage.c:72
- These files use a literal integer 0 when they really should use a NULL
pointer:
daemon.c:663, fast-import.c:2942, imap-send.c:1072, notes-merge.c:362
While we're in the area, clean up some unused #includes in builtin files
(mostly exec_cmd.h).
Signed-off-by: Stephen Boyd <bebarino@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-03-22 08:51:05 +01:00
|
|
|
#include "builtin.h"
|
2017-06-14 20:07:36 +02:00
|
|
|
#include "config.h"
|
2005-07-19 13:03:47 +02:00
|
|
|
#include "commit.h"
|
2023-02-24 01:09:27 +01:00
|
|
|
#include "hex.h"
|
2005-07-08 22:58:40 +02:00
|
|
|
#include "refs.h"
|
2005-06-30 05:50:15 +02:00
|
|
|
#include "pkt-line.h"
|
2009-10-31 01:47:41 +01:00
|
|
|
#include "sideband.h"
|
2007-03-13 00:00:29 +01:00
|
|
|
#include "run-command.h"
|
2007-05-12 17:45:59 +02:00
|
|
|
#include "remote.h"
|
2013-07-08 22:56:53 +02:00
|
|
|
#include "connect.h"
|
2007-10-30 03:03:39 +01:00
|
|
|
#include "send-pack.h"
|
2009-10-31 01:47:41 +01:00
|
|
|
#include "quote.h"
|
2010-02-17 00:42:52 +01:00
|
|
|
#include "transport.h"
|
2012-08-03 18:19:16 +02:00
|
|
|
#include "version.h"
|
2020-03-30 16:03:46 +02:00
|
|
|
#include "oid-array.h"
|
2015-07-22 00:06:43 +02:00
|
|
|
#include "gpg-interface.h"
|
2015-08-19 17:26:45 +02:00
|
|
|
#include "gettext.h"
|
2018-03-14 19:31:45 +01:00
|
|
|
#include "protocol.h"
|
treewide: include parse-options.h in source files
The builtins 'ls-remote', 'pack-objects', 'receive-pack', 'reflog' and
'send-pack' use parse_options(), but their source files don't directly
include 'parse-options.h'. Furthermore, the source files
'diagnose.c', 'list-objects-filter-options.c', 'remote.c' and
'send-pack.c' define option parsing callback functions, while
'revision.c' defines an option parsing helper function, and thus need
access to various fields in 'struct option' and 'struct
parse_opt_ctx_t', but they don't directly include 'parse-options.h'
either. They all can still be built, of course, because they include
one of the header files that does include 'parse-options.h' (though
unnecessarily, see the next commit).
Add those missing includes to these files, as our general rule is that
"a C file must directly include the header files that declare the
functions and the types it uses".
Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-19 17:27:11 +01:00
|
|
|
#include "parse-options.h"
|
2023-03-21 07:26:07 +01:00
|
|
|
#include "write-or-die.h"
|
2005-06-30 04:09:05 +02:00
|
|
|
|
2015-08-19 17:26:45 +02:00
|
|
|
static const char * const send_pack_usage[] = {
|
2021-09-13 02:13:20 +02:00
|
|
|
N_("git send-pack [--mirror] [--dry-run] [--force]\n"
|
|
|
|
" [--receive-pack=<git-receive-pack>]\n"
|
|
|
|
" [--verbose] [--thin] [--atomic]\n"
|
2022-10-13 17:39:13 +02:00
|
|
|
" [--[no-]signed | --signed=(true|false|if-asked)]\n"
|
2021-09-13 02:13:20 +02:00
|
|
|
" [<host>:]<directory> (--all | <ref>...)"),
|
2015-08-19 17:26:45 +02:00
|
|
|
NULL,
|
|
|
|
};
|
2007-10-30 03:03:39 +01:00
|
|
|
|
2009-03-27 03:37:53 +01:00
|
|
|
static struct send_pack_args args;
|
2005-06-30 04:09:05 +02:00
|
|
|
|
2009-10-31 01:47:41 +01:00
|
|
|
static void print_helper_status(struct ref *ref)
|
|
|
|
{
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2020-08-27 17:45:46 +02:00
|
|
|
struct ref_push_report *report;
|
2009-10-31 01:47:41 +01:00
|
|
|
|
|
|
|
for (; ref; ref = ref->next) {
|
|
|
|
const char *msg = NULL;
|
|
|
|
const char *res;
|
2020-08-27 17:45:46 +02:00
|
|
|
int count = 0;
|
2009-10-31 01:47:41 +01:00
|
|
|
|
|
|
|
switch(ref->status) {
|
|
|
|
case REF_STATUS_NONE:
|
|
|
|
res = "error";
|
|
|
|
msg = "no match";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_OK:
|
|
|
|
res = "ok";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_UPTODATE:
|
|
|
|
res = "ok";
|
|
|
|
msg = "up to date";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_REJECT_NONFASTFORWARD:
|
|
|
|
res = "error";
|
|
|
|
msg = "non-fast forward";
|
2012-11-30 02:41:37 +01:00
|
|
|
break;
|
|
|
|
|
push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE
When we push to update an existing ref, if:
* the object at the tip of the remote is not a commit; or
* the object we are pushing is not a commit,
it won't be correct to suggest to fetch, integrate and push again,
as the old and new objects will not "merge". We should explain that
the push must be forced when there is a non-committish object is
involved in such a case.
If we do not have the current object at the tip of the remote, we do
not even know that object, when fetched, is something that can be
merged. In such a case, suggesting to pull first just like
non-fast-forward case may not be technically correct, but in
practice, most such failures are seen when you try to push your work
to a branch without knowing that somebody else already pushed to
update the same branch since you forked, so "pull first" would work
as a suggestion most of the time. And if the object at the tip is
not a commit, "pull first" will fail, without making any permanent
damage. As a side effect, it also makes the error message the user
will get during the next "push" attempt easier to understand, now
the user is aware that a non-commit object is involved.
In these cases, the current code already rejects such a push on the
client end, but we used the same error and advice messages as the
ones used when rejecting a non-fast-forward push, i.e. pull from
there and integrate before pushing again.
Introduce new rejection reasons and reword the messages
appropriately.
[jc: with help by Peff on message details]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-01-23 22:55:30 +01:00
|
|
|
case REF_STATUS_REJECT_FETCH_FIRST:
|
|
|
|
res = "error";
|
|
|
|
msg = "fetch first";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_REJECT_NEEDS_FORCE:
|
|
|
|
res = "error";
|
|
|
|
msg = "needs force";
|
|
|
|
break;
|
|
|
|
|
2013-07-08 23:42:40 +02:00
|
|
|
case REF_STATUS_REJECT_STALE:
|
|
|
|
res = "error";
|
|
|
|
msg = "stale info";
|
|
|
|
break;
|
|
|
|
|
2020-10-03 14:10:44 +02:00
|
|
|
case REF_STATUS_REJECT_REMOTE_UPDATED:
|
|
|
|
res = "error";
|
|
|
|
msg = "remote ref updated since checkout";
|
|
|
|
break;
|
|
|
|
|
2012-11-30 02:41:37 +01:00
|
|
|
case REF_STATUS_REJECT_ALREADY_EXISTS:
|
|
|
|
res = "error";
|
|
|
|
msg = "already exists";
|
2009-10-31 01:47:41 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_REJECT_NODELETE:
|
|
|
|
case REF_STATUS_REMOTE_REJECT:
|
|
|
|
res = "error";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REF_STATUS_EXPECTING_REPORT:
|
send-pack: complain about "expecting report" with --helper-status
When pushing to a server which erroneously omits the final ref-status
report, the client side should complain about the refs for which we
didn't receive the status (because we can't just assume they were
updated). This works over most transports like ssh, but for http we'll
print a very misleading "Everything up-to-date".
It works for ssh because send-pack internally sets the status of each
ref to REF_STATUS_EXPECTING_REPORT, and then if the server doesn't tell
us about a particular ref, it will stay at that value. When we print the
final status table, we'll see that we're still on EXPECTING_REPORT and
complain then.
But for http, we go through remote-curl, which invokes send-pack with
"--stateless-rpc --helper-status". The latter option causes send-pack to
return a machine-readable list of ref statuses to the remote helper. But
ever since its inception in de1a2fdd38 (Smart push over HTTP: client
side, 2009-10-30), the send-pack code has simply omitted mention of any
ref which ended up in EXPECTING_REPORT.
In the remote helper, we then take the absence of any status report
from send-pack to mean that the ref was not even something we tried to
send, and thus it prints "Everything up-to-date". Fortunately it does
detect the eventual non-zero exit from send-pack, and propagates that in
its own non-zero exit code. So at least a careful script invoking "git
push" would notice the failure. But sending the misleading message on
stderr is certainly confusing for humans (not to mention the
machine-readable "push --porcelain" output, though again, any careful
script should be checking the exit code from push, too).
Nobody seems to have noticed because the server in this instance has to
be misbehaving: it has promised to support the ref-status capability
(otherwise the client will not set EXPECTING_REPORT at all), but didn't
send us any. If the connection were simply cut, then send-pack would
complain about getting EOF while trying to read the status. But if the
server actually sends a flush packet (i.e., saying "now you have all of
the ref statuses" without actually sending any), then the client ends up
in this confused situation.
The fix is simple: we should return an error message from "send-pack
--helper-status", just like we would for any other error per-ref error
condition (in the test I included, the server simply omits all ref
status responses, but a more insidious version of this would skip only
some of them).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-10-18 21:43:47 +02:00
|
|
|
res = "error";
|
|
|
|
msg = "expecting report";
|
|
|
|
break;
|
|
|
|
|
2009-10-31 01:47:41 +01:00
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
strbuf_reset(&buf);
|
|
|
|
strbuf_addf(&buf, "%s %s", res, ref->name);
|
|
|
|
if (ref->remote_status)
|
|
|
|
msg = ref->remote_status;
|
|
|
|
if (msg) {
|
|
|
|
strbuf_addch(&buf, ' ');
|
|
|
|
quote_two_c_style(&buf, "", msg, 0);
|
|
|
|
}
|
|
|
|
strbuf_addch(&buf, '\n');
|
|
|
|
|
2020-08-27 17:45:46 +02:00
|
|
|
if (ref->status == REF_STATUS_OK) {
|
|
|
|
for (report = ref->report; report; report = report->next) {
|
|
|
|
if (count++ > 0)
|
|
|
|
strbuf_addf(&buf, "ok %s\n", ref->name);
|
|
|
|
if (report->ref_name)
|
|
|
|
strbuf_addf(&buf, "option refname %s\n",
|
|
|
|
report->ref_name);
|
|
|
|
if (report->old_oid)
|
|
|
|
strbuf_addf(&buf, "option old-oid %s\n",
|
|
|
|
oid_to_hex(report->old_oid));
|
|
|
|
if (report->new_oid)
|
|
|
|
strbuf_addf(&buf, "option new-oid %s\n",
|
|
|
|
oid_to_hex(report->new_oid));
|
|
|
|
if (report->forced_update)
|
|
|
|
strbuf_addstr(&buf, "option forced-update\n");
|
|
|
|
}
|
|
|
|
}
|
2013-02-20 21:01:56 +01:00
|
|
|
write_or_die(1, buf.buf, buf.len);
|
2009-10-31 01:47:41 +01:00
|
|
|
}
|
|
|
|
strbuf_release(&buf);
|
|
|
|
}
|
|
|
|
|
2015-08-19 17:26:47 +02:00
|
|
|
static int send_pack_config(const char *k, const char *v, void *cb)
|
|
|
|
{
|
|
|
|
if (!strcmp(k, "push.gpgsign")) {
|
|
|
|
const char *value;
|
|
|
|
if (!git_config_get_value("push.gpgsign", &value)) {
|
2017-08-07 20:20:49 +02:00
|
|
|
switch (git_parse_maybe_bool(value)) {
|
2015-08-19 17:26:47 +02:00
|
|
|
case 0:
|
|
|
|
args.push_cert = SEND_PACK_PUSH_CERT_NEVER;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
args.push_cert = SEND_PACK_PUSH_CERT_ALWAYS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (value && !strcasecmp(value, "if-asked"))
|
|
|
|
args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
|
|
|
|
else
|
2022-01-31 23:07:47 +01:00
|
|
|
return error(_("invalid value for '%s'"), k);
|
2015-08-19 17:26:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-12 19:26:23 +02:00
|
|
|
return git_default_config(k, v, cb);
|
2015-08-19 17:26:47 +02:00
|
|
|
}
|
|
|
|
|
2007-10-30 03:03:39 +01:00
|
|
|
int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
2005-06-30 04:09:05 +02:00
|
|
|
{
|
2018-05-17 00:58:18 +02:00
|
|
|
struct refspec rs = REFSPEC_INIT_PUSH;
|
2007-10-30 03:03:39 +01:00
|
|
|
const char *remote_name = NULL;
|
2007-05-16 04:50:19 +02:00
|
|
|
struct remote *remote = NULL;
|
2007-10-30 03:03:39 +01:00
|
|
|
const char *dest = NULL;
|
2009-03-09 02:06:07 +01:00
|
|
|
int fd[2];
|
|
|
|
struct child_process *conn;
|
2017-03-31 03:40:00 +02:00
|
|
|
struct oid_array extra_have = OID_ARRAY_INIT;
|
|
|
|
struct oid_array shallow = OID_ARRAY_INIT;
|
2009-05-31 16:26:48 +02:00
|
|
|
struct ref *remote_refs, *local_refs;
|
2009-03-09 02:06:07 +01:00
|
|
|
int ret;
|
2009-10-31 01:47:41 +01:00
|
|
|
int helper_status = 0;
|
2009-03-09 02:06:07 +01:00
|
|
|
int send_all = 0;
|
2015-08-19 17:26:45 +02:00
|
|
|
int verbose = 0;
|
2009-03-09 02:06:07 +01:00
|
|
|
const char *receivepack = "git-receive-pack";
|
2015-08-19 17:26:45 +02:00
|
|
|
unsigned dry_run = 0;
|
|
|
|
unsigned send_mirror = 0;
|
|
|
|
unsigned force_update = 0;
|
|
|
|
unsigned quiet = 0;
|
2015-08-19 17:26:46 +02:00
|
|
|
int push_cert = 0;
|
2017-03-22 23:22:00 +01:00
|
|
|
struct string_list push_options = STRING_LIST_INIT_NODUP;
|
2015-08-19 17:26:45 +02:00
|
|
|
unsigned use_thin_pack = 0;
|
|
|
|
unsigned atomic = 0;
|
|
|
|
unsigned stateless_rpc = 0;
|
2009-03-09 02:06:07 +01:00
|
|
|
int flags;
|
2012-11-30 02:41:33 +01:00
|
|
|
unsigned int reject_reasons;
|
2012-05-01 10:42:24 +02:00
|
|
|
int progress = -1;
|
2014-08-21 14:21:20 +02:00
|
|
|
int from_stdin = 0;
|
remote.c: add command line option parser for "--force-with-lease"
Update "git push" and "git send-pack" to parse this commnd line
option.
The intended sematics is:
* "--force-with-lease" alone, without specifying the details, will
protect _all_ remote refs that are going to be updated by
requiring their current value to be the same as some reasonable
default, unless otherwise specified;
* "--force-with-lease=refname", without specifying the expected
value, will protect that refname, if it is going to be updated,
by requiring its current value to be the same as some reasonable
default.
* "--force-with-lease=refname:value" will protect that refname, if
it is going to be updated, by requiring its current value to be
the same as the specified value; and
* "--no-force-with-lease" will cancel all the previous --force-with-lease on the
command line.
For now, "some reasonable default" is tentatively defined as "the
value of the remote-tracking branch we have for the ref of the
remote being updated", and it is an error if we do not have such a
remote-tracking branch. But this is known to be fragile, its use is
not yet recommended, and hopefully we will find more reasonable
default as we gain experience with this feature. The manual marks
the feature as experimental unless the expected value is specified
explicitly for this reason.
Because the command line options are parsed _before_ we know which
remote we are pushing to, there needs further processing to the
parsed data after we instantiate the transport object to:
* expand "refname" given by the user to a full refname to be
matched with the list of "struct ref" used in match_push_refs()
and set_ref_status_for_push(); and
* learning the actual local ref that is the remote-tracking branch
for the specified remote ref.
Further, some processing need to be deferred until we find the set
of remote refs and match_push_refs() returns in order to find the
ones that need to be checked after explicit ones have been processed
for "--force-with-lease" (no specific details).
These post-processing will be the topic of the next patch.
This option was originally called "cas" (for "compare and swap"),
the name which nobody liked because it was too technical. The
second attempt called it "lockref" (because it is conceptually like
pushing after taking a lock) but the word "lock" was hated because
it implied that it may reject push by others, which is not the way
this option works. This round calls it "force-with-lease". You
assume you took the lease on the ref when you fetched to decide what
the rebased history should be, and you can push back only if the
lease has not been broken.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-09 00:34:36 +02:00
|
|
|
struct push_cas_option cas = {0};
|
2020-10-03 14:10:45 +02:00
|
|
|
int force_if_includes = 0;
|
2018-03-14 19:31:45 +01:00
|
|
|
struct packet_reader reader;
|
2006-03-24 08:41:18 +01:00
|
|
|
|
2015-08-19 17:26:45 +02:00
|
|
|
struct option options[] = {
|
|
|
|
OPT__VERBOSITY(&verbose),
|
|
|
|
OPT_STRING(0, "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
|
|
|
|
OPT_STRING(0, "exec", &receivepack, "receive-pack", N_("receive pack program")),
|
|
|
|
OPT_STRING(0, "remote", &remote_name, "remote", N_("remote name")),
|
|
|
|
OPT_BOOL(0, "all", &send_all, N_("push all refs")),
|
|
|
|
OPT_BOOL('n' , "dry-run", &dry_run, N_("dry run")),
|
|
|
|
OPT_BOOL(0, "mirror", &send_mirror, N_("mirror all refs")),
|
|
|
|
OPT_BOOL('f', "force", &force_update, N_("force updates")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 10:36:28 +02:00
|
|
|
OPT_CALLBACK_F(0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
|
|
|
|
PARSE_OPT_OPTARG, option_parse_push_signed),
|
2017-03-22 23:22:00 +01:00
|
|
|
OPT_STRING_LIST(0, "push-option", &push_options,
|
|
|
|
N_("server-specific"),
|
|
|
|
N_("option to transmit")),
|
2015-08-19 17:26:45 +02:00
|
|
|
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
|
|
|
|
OPT_BOOL(0, "thin", &use_thin_pack, N_("use thin pack")),
|
|
|
|
OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")),
|
|
|
|
OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless RPC protocol")),
|
|
|
|
OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
|
|
|
|
OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 10:36:28 +02:00
|
|
|
OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
|
2015-08-19 17:26:45 +02:00
|
|
|
N_("require old value of ref to be at this value"),
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 10:36:28 +02:00
|
|
|
PARSE_OPT_OPTARG, parseopt_push_cas_option),
|
2020-10-03 14:10:45 +02:00
|
|
|
OPT_BOOL(0, TRANS_OPT_FORCE_IF_INCLUDES, &force_if_includes,
|
|
|
|
N_("require remote updates to be integrated locally")),
|
2015-08-19 17:26:45 +02:00
|
|
|
OPT_END()
|
|
|
|
};
|
2005-06-30 04:09:05 +02:00
|
|
|
|
2015-08-19 17:26:47 +02:00
|
|
|
git_config(send_pack_config, NULL);
|
2015-08-19 17:26:45 +02:00
|
|
|
argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
|
|
|
|
if (argc > 0) {
|
|
|
|
dest = argv[0];
|
2018-05-17 00:58:18 +02:00
|
|
|
refspec_appendn(&rs, argv + 1, argc - 1);
|
2005-06-30 04:09:05 +02:00
|
|
|
}
|
2015-08-19 17:26:45 +02:00
|
|
|
|
2005-06-30 04:09:05 +02:00
|
|
|
if (!dest)
|
2015-08-19 17:26:45 +02:00
|
|
|
usage_with_options(send_pack_usage, options);
|
|
|
|
|
|
|
|
args.verbose = verbose;
|
|
|
|
args.dry_run = dry_run;
|
|
|
|
args.send_mirror = send_mirror;
|
|
|
|
args.force_update = force_update;
|
|
|
|
args.quiet = quiet;
|
|
|
|
args.push_cert = push_cert;
|
|
|
|
args.progress = progress;
|
|
|
|
args.use_thin_pack = use_thin_pack;
|
|
|
|
args.atomic = atomic;
|
|
|
|
args.stateless_rpc = stateless_rpc;
|
2017-03-22 23:22:00 +01:00
|
|
|
args.push_options = push_options.nr ? &push_options : NULL;
|
2021-07-15 19:44:30 +02:00
|
|
|
args.url = dest;
|
2014-08-21 14:21:20 +02:00
|
|
|
|
|
|
|
if (from_stdin) {
|
|
|
|
if (args.stateless_rpc) {
|
|
|
|
const char *buf;
|
|
|
|
while ((buf = packet_read_line(0, NULL)))
|
2018-05-17 00:58:18 +02:00
|
|
|
refspec_append(&rs, buf);
|
2014-08-21 14:21:20 +02:00
|
|
|
} else {
|
|
|
|
struct strbuf line = STRBUF_INIT;
|
2015-10-28 22:00:59 +01:00
|
|
|
while (strbuf_getline(&line, stdin) != EOF)
|
2018-05-17 00:58:18 +02:00
|
|
|
refspec_append(&rs, line.buf);
|
2014-08-21 14:21:20 +02:00
|
|
|
strbuf_release(&line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-10 00:32:10 +01:00
|
|
|
/*
|
|
|
|
* --all and --mirror are incompatible; neither makes sense
|
|
|
|
* with any refspecs.
|
|
|
|
*/
|
2018-05-17 00:58:18 +02:00
|
|
|
if ((rs.nr > 0 && (send_all || args.send_mirror)) ||
|
2009-03-09 02:06:07 +01:00
|
|
|
(send_all && args.send_mirror))
|
2015-08-19 17:26:45 +02:00
|
|
|
usage_with_options(send_pack_usage, options);
|
2006-12-13 19:30:11 +01:00
|
|
|
|
2007-05-16 04:50:19 +02:00
|
|
|
if (remote_name) {
|
|
|
|
remote = remote_get(remote_name);
|
2007-09-19 06:49:27 +02:00
|
|
|
if (!remote_has_url(remote, dest)) {
|
2007-05-16 04:50:19 +02:00
|
|
|
die("Destination %s is not a uri for %s",
|
|
|
|
dest, remote_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-01 10:42:24 +02:00
|
|
|
if (progress == -1)
|
|
|
|
progress = !args.quiet && isatty(2);
|
|
|
|
args.progress = progress;
|
send-pack: show progress when isatty(2)
The send_pack_args struct has two verbosity flags: "quiet"
and "progress". Originally, if "quiet" was set, we would
tell pack-objects explicitly to be quiet, and if "progress"
was set, we would tell it to show progress. Otherwise, we
told it neither, and it relied on isatty(2) to make the
decision itself.
However, commit 01fdc21 changed the meaning of these
variables. Now both "quiet" and "!progress" instruct us to
tell pack-objects to be quiet (and a non-zero "progress"
means the same as before). This works well for transports
which call send_pack directly, as the transport code copies
transport->progress into send_pack_args->progress, and they
both have the same meaning.
However, the code path of calling "git send-pack" was left
behind. It always sets "progress" to 0, and thus always
tells pack-objects to be quiet. We can work around this by
checking isatty(2) ourselves in the cmd_send_pack code path,
restoring the original behavior of the send-pack command.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-01 10:41:42 +02:00
|
|
|
|
2009-10-31 01:47:41 +01:00
|
|
|
if (args.stateless_rpc) {
|
|
|
|
conn = NULL;
|
|
|
|
fd[0] = 0;
|
|
|
|
fd[1] = 1;
|
|
|
|
} else {
|
git_connect(): fix corner cases in downgrading v2 to v0
There's code in git_connect() that checks whether we are doing a push
with protocol_v2, and if so, drops us to protocol_v0 (since we know
how to do v2 only for fetches). But it misses some corner cases:
1. it checks the "prog" variable, which is actually the path to
receive-pack on the remote side. By default this is just
"git-receive-pack", but it could be an arbitrary string (like
"/path/to/git receive-pack", etc). We'd accidentally stay in v2
mode in this case.
2. besides "receive-pack" and "upload-pack", there's one other value
we'd expect: "upload-archive" for handling "git archive --remote".
Like receive-pack, this doesn't understand v2, and should use the
v0 protocol.
In practice, neither of these causes bugs in the real world so far. We
do send a "we understand v2" probe to the server, but since no server
implements v2 for anything but upload-pack, it's simply ignored. But
this would eventually become a problem if we do implement v2 for those
endpoints, as older clients would falsely claim to understand it,
leading to a server response they can't parse.
We can fix (1) by passing in both the program path and the "name" of the
operation. I treat the name as a string here, because that's the pattern
set in transport_connect(), which is one of our callers (we were simply
throwing away the "name" value there before).
We can fix (2) by allowing only known-v2 protocols ("upload-pack"),
rather than blocking unknown ones ("receive-pack" and "upload-archive").
That will mean whoever eventually implements v2 push will have to adjust
this list, but that's reasonable. We'll do the safe, conservative thing
(sticking to v0) by default, and anybody working on v2 will quickly
realize this spot needs to be updated.
The new tests cover the receive-pack and upload-archive cases above, and
re-confirm that we allow v2 with an arbitrary "--upload-pack" path (that
already worked before this patch, of course, but it would be an easy
thing to break if we flipped the allow/block logic without also handling
"name" separately).
Here are a few miscellaneous implementation notes, since I had to do a
little head-scratching to understand who calls what:
- transport_connect() is called only for git-upload-archive. For
non-http git remotes, that resolves to the virtual connect_git()
function (which then calls git_connect(); confused yet?). So
plumbing through "name" in connect_git() covers that.
- for regular fetches and pushes, callers use higher-level functions
like transport_fetch_refs(). For non-http git remotes, that means
calling git_connect() under the hood via connect_setup(). And that
uses the "for_push" flag to decide which name to use.
- likewise, plumbing like fetch-pack and send-pack may call
git_connect() directly; they each know which name to use.
- for remote helpers (including http), we already have separate
parameters for "name" and "exec" (another name for "prog"). In
process_connect_service(), we feed the "name" to the helper via
"connect" or "stateless-connect" directives.
There's also a "servpath" option, which can be used to tell the
helper about the "exec" path. But no helpers we implement support
it! For http it would be useless anyway (no reasonable server
implementation will allow you to send a shell command to run the
server). In theory it would be useful for more obscure helpers like
remote-ext, but even there it is not implemented.
It's tempting to get rid of it simply to reduce confusion, but we
have publicly documented it since it was added in fa8c097cc9
(Support remote helpers implementing smart transports, 2009-12-09),
so it's possible some helper in the wild is using it.
- So for v2, helpers (again, including http) are mainly used via
stateless-connect, driven by the main program. But they do still
need to decide whether to do a v2 probe. And so there's similar
logic in remote-curl.c's discover_refs() that looks for
"git-receive-pack". But it's not buggy in the same way. Since it
doesn't support servpath, it is always dealing with a "service"
string like "git-receive-pack". And since it doesn't support
straight "connect", it can't be used for "upload-archive".
So we could leave that spot alone. But I've updated it here to match
the logic we're changing in connect_git(). That seems like the least
confusing thing for somebody who has to touch both of these spots
later (say, to add v2 push support). I didn't add a new test to make
sure this doesn't break anything; we already have several tests (in
t5551 and elsewhere) that make sure we are using v2 over http.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-17 20:08:51 +01:00
|
|
|
conn = git_connect(fd, dest, "git-receive-pack", receivepack,
|
2009-10-31 01:47:41 +01:00
|
|
|
args.verbose ? CONNECT_VERBOSE : 0);
|
|
|
|
}
|
2007-10-30 03:03:39 +01:00
|
|
|
|
2018-03-14 19:31:45 +01:00
|
|
|
packet_reader_init(&reader, fd[0], NULL, 0,
|
|
|
|
PACKET_READ_CHOMP_NEWLINE |
|
pack-protocol.txt: accept error packets in any context
In the Git pack protocol definition, an error packet may appear only in
a certain context. However, servers can face a runtime error (e.g. I/O
error) at an arbitrary timing. This patch changes the protocol to allow
an error packet to be sent instead of any packet.
Without this protocol spec change, when a server cannot process a
request, there's no way to tell that to a client. Since the server
cannot produce a valid response, it would be forced to cut a connection
without telling why. With this protocol spec change, the server can be
more gentle in this situation. An old client may see these error packets
as an unexpected packet, but this is not worse than having an unexpected
EOF.
Following this protocol spec change, the error packet handling code is
moved to pkt-line.c. Implementation wise, this implementation uses
pkt-line to communicate with a subprocess. Since this is not a part of
Git protocol, it's possible that a packet that is not supposed to be an
error packet is mistakenly parsed as an error packet. This error packet
handling is enabled only for the Git pack protocol parsing code
considering this.
Signed-off-by: Masaya Suzuki <masayasuzuki@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-12-29 22:19:15 +01:00
|
|
|
PACKET_READ_GENTLE_ON_EOF |
|
|
|
|
PACKET_READ_DIE_ON_ERR_PACKET);
|
2018-03-14 19:31:45 +01:00
|
|
|
|
|
|
|
switch (discover_version(&reader)) {
|
2018-03-14 19:31:47 +01:00
|
|
|
case protocol_v2:
|
|
|
|
die("support for protocol v2 not implemented yet");
|
|
|
|
break;
|
2018-03-14 19:31:45 +01:00
|
|
|
case protocol_v1:
|
|
|
|
case protocol_v0:
|
|
|
|
get_remote_heads(&reader, &remote_refs, REF_NORMAL,
|
|
|
|
&extra_have, &shallow);
|
|
|
|
break;
|
|
|
|
case protocol_unknown_version:
|
|
|
|
BUG("unknown protocol version");
|
|
|
|
}
|
2009-03-09 02:06:07 +01:00
|
|
|
|
|
|
|
local_refs = get_local_heads();
|
2007-10-30 03:03:39 +01:00
|
|
|
|
2009-03-09 02:06:07 +01:00
|
|
|
flags = MATCH_REFS_NONE;
|
|
|
|
|
|
|
|
if (send_all)
|
|
|
|
flags |= MATCH_REFS_ALL;
|
|
|
|
if (args.send_mirror)
|
|
|
|
flags |= MATCH_REFS_MIRROR;
|
|
|
|
|
|
|
|
/* match them up */
|
2018-05-17 00:58:21 +02:00
|
|
|
if (match_push_refs(local_refs, &remote_refs, &rs, flags))
|
2009-03-09 02:06:07 +01:00
|
|
|
return -1;
|
2007-10-30 03:03:39 +01:00
|
|
|
|
2013-07-09 20:01:06 +02:00
|
|
|
if (!is_empty_cas(&cas))
|
|
|
|
apply_push_cas(&cas, remote, remote_refs);
|
|
|
|
|
2020-10-03 14:10:45 +02:00
|
|
|
if (!is_empty_cas(&cas) && force_if_includes)
|
|
|
|
cas.use_force_if_includes = 1;
|
|
|
|
|
2010-01-08 03:12:42 +01:00
|
|
|
set_ref_status_for_push(remote_refs, args.send_mirror,
|
|
|
|
args.force_update);
|
|
|
|
|
2009-03-09 02:06:07 +01:00
|
|
|
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
|
2007-10-30 03:03:39 +01:00
|
|
|
|
2009-10-31 01:47:41 +01:00
|
|
|
if (helper_status)
|
|
|
|
print_helper_status(remote_refs);
|
|
|
|
|
2009-03-09 02:06:07 +01:00
|
|
|
close(fd[1]);
|
2005-06-30 07:50:48 +02:00
|
|
|
close(fd[0]);
|
2009-03-09 02:06:07 +01:00
|
|
|
|
2007-10-19 21:47:53 +02:00
|
|
|
ret |= finish_connect(conn);
|
2009-03-09 02:06:07 +01:00
|
|
|
|
2009-10-31 01:47:41 +01:00
|
|
|
if (!helper_status)
|
2012-11-30 02:41:33 +01:00
|
|
|
transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
|
2009-03-09 02:06:07 +01:00
|
|
|
|
|
|
|
if (!args.dry_run && remote) {
|
|
|
|
struct ref *ref;
|
|
|
|
for (ref = remote_refs; ref; ref = ref->next)
|
2010-02-17 00:42:52 +01:00
|
|
|
transport_update_tracking_ref(remote, ref, args.verbose);
|
2009-03-09 02:06:07 +01:00
|
|
|
}
|
|
|
|
|
2010-02-17 00:42:52 +01:00
|
|
|
if (!ret && !transport_refs_pushed(remote_refs))
|
2009-03-09 02:06:07 +01:00
|
|
|
fprintf(stderr, "Everything up-to-date\n");
|
|
|
|
|
|
|
|
return ret;
|
2005-06-30 04:09:05 +02:00
|
|
|
}
|