"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
" --all and explicit <ref> specification are mutually exclusive.";
-static struct send_pack_args args = {
- /* .receivepack = */ "git-receive-pack",
-};
+static struct send_pack_args args;
static int feed_object(const unsigned char *sha1, int fd, int negative)
{
/*
* Make a pack stream and spit it out into file descriptor fd
*/
-static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
+static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
{
/*
* The child becomes pack-objects --revs; we feed
"--stdout",
NULL,
NULL,
+ NULL,
};
struct child_process po;
int i;
- if (args.use_thin_pack)
- argv[4] = "--thin";
+ i = 4;
+ if (args->use_thin_pack)
+ argv[i++] = "--thin";
+ if (args->use_ofs_delta)
+ argv[i++] = "--delta-base-offset";
memset(&po, 0, sizeof(po));
po.argv = argv;
po.in = -1;
return 0;
}
-static struct ref *remote_refs, **remote_tail;
-
static int receive_status(int in, struct ref *refs)
{
struct ref *hint;
}
}
-static const char *prettify_ref(const struct ref *ref)
-{
- const char *name = ref->name;
- return name + (
- !prefixcmp(name, "refs/heads/") ? 11 :
- !prefixcmp(name, "refs/tags/") ? 10 :
- !prefixcmp(name, "refs/remotes/") ? 13 :
- 0);
-}
-
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
{
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
if (from)
- fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
+ fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
else
- fputs(prettify_ref(to), stderr);
+ fputs(prettify_refname(to->name), stderr);
if (msg) {
fputs(" (", stderr);
fputs(msg, stderr);
return 0;
}
-static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)
+int send_pack(struct send_pack_args *args,
+ int fd[], struct child_process *conn,
+ struct ref *remote_refs,
+ struct extra_have_objects *extra_have)
{
- struct ref *ref, *local_refs;
+ int in = fd[0];
+ int out = fd[1];
+ struct ref *ref;
int new_refs;
int ask_for_status_report = 0;
int allow_deleting_refs = 0;
int expect_status_report = 0;
- int flags = MATCH_REFS_NONE;
int ret;
- struct extra_have_objects extra_have;
-
- memset(&extra_have, 0, sizeof(extra_have));
- if (args.send_all)
- flags |= MATCH_REFS_ALL;
- if (args.send_mirror)
- flags |= MATCH_REFS_MIRROR;
-
- /* No funny business with the matcher */
- remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
- &extra_have);
- local_refs = get_local_heads();
/* Does the other end support the reporting? */
if (server_supports("report-status"))
ask_for_status_report = 1;
if (server_supports("delete-refs"))
allow_deleting_refs = 1;
-
- /* match them up */
- if (!remote_tail)
- remote_tail = &remote_refs;
- if (match_refs(local_refs, remote_refs, &remote_tail,
- nr_refspec, refspec, flags)) {
- close(out);
- return -1;
- }
+ if (server_supports("ofs-delta"))
+ args->use_ofs_delta = 1;
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch such as 'master'.\n");
- close(out);
return 0;
}
if (ref->peer_ref)
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
- else if (!args.send_mirror)
+ else if (!args->send_mirror)
continue;
ref->deletion = is_null_sha1(ref->new_sha1);
(!has_sha1_file(ref->old_sha1)
|| !ref_newer(ref->new_sha1, ref->old_sha1));
- if (ref->nonfastforward && !ref->force && !args.force_update) {
+ if (ref->nonfastforward && !ref->force && !args->force_update) {
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
continue;
}
if (!ref->deletion)
new_refs++;
- if (!args.dry_run) {
+ if (!args->dry_run) {
char *old_hex = sha1_to_hex(ref->old_sha1);
char *new_hex = sha1_to_hex(ref->new_sha1);
}
packet_flush(out);
- if (new_refs && !args.dry_run) {
- if (pack_objects(out, remote_refs, &extra_have) < 0)
+ if (new_refs && !args->dry_run) {
+ if (pack_objects(out, remote_refs, extra_have, args) < 0) {
+ for (ref = remote_refs; ref; ref = ref->next)
+ ref->status = REF_STATUS_NONE;
return -1;
+ }
}
- else
- close(out);
if (expect_status_report)
ret = receive_status(in, remote_refs);
else
ret = 0;
- print_push_status(dest, remote_refs);
-
- if (!args.dry_run && remote) {
- for (ref = remote_refs; ref; ref = ref->next)
- update_tracking_ref(remote, ref);
- }
-
- if (!refs_pushed(remote_refs))
- fprintf(stderr, "Everything up-to-date\n");
if (ret < 0)
return ret;
for (ref = remote_refs; ref; ref = ref->next) {
int cmd_send_pack(int argc, const char **argv, const char *prefix)
{
- int i, nr_heads = 0;
- const char **heads = NULL;
+ int i, nr_refspecs = 0;
+ const char **refspecs = NULL;
const char *remote_name = NULL;
struct remote *remote = NULL;
const char *dest = NULL;
+ int fd[2];
+ struct child_process *conn;
+ struct extra_have_objects extra_have;
+ struct ref *remote_refs, **remote_tail, *local_refs;
+ int ret;
+ int send_all = 0;
+ const char *receivepack = "git-receive-pack";
+ int flags;
argv++;
for (i = 1; i < argc; i++, argv++) {
if (*arg == '-') {
if (!prefixcmp(arg, "--receive-pack=")) {
- args.receivepack = arg + 15;
+ receivepack = arg + 15;
continue;
}
if (!prefixcmp(arg, "--exec=")) {
- args.receivepack = arg + 7;
+ receivepack = arg + 7;
continue;
}
if (!prefixcmp(arg, "--remote=")) {
continue;
}
if (!strcmp(arg, "--all")) {
- args.send_all = 1;
+ send_all = 1;
continue;
}
if (!strcmp(arg, "--dry-run")) {
dest = arg;
continue;
}
- heads = (const char **) argv;
- nr_heads = argc - i;
+ refspecs = (const char **) argv;
+ nr_refspecs = argc - i;
break;
}
if (!dest)
* --all and --mirror are incompatible; neither makes sense
* with any refspecs.
*/
- if ((heads && (args.send_all || args.send_mirror)) ||
- (args.send_all && args.send_mirror))
+ if ((refspecs && (send_all || args.send_mirror)) ||
+ (send_all && args.send_mirror))
usage(send_pack_usage);
if (remote_name) {
}
}
- return send_pack(&args, dest, remote, nr_heads, heads);
-}
+ conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0);
-int send_pack(struct send_pack_args *my_args,
- const char *dest, struct remote *remote,
- int nr_heads, const char **heads)
-{
- int fd[2], ret;
- struct child_process *conn;
+ memset(&extra_have, 0, sizeof(extra_have));
+
+ get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL,
+ &extra_have);
- memcpy(&args, my_args, sizeof(args));
+ verify_remote_names(nr_refspecs, refspecs);
+
+ local_refs = get_local_heads();
+
+ flags = MATCH_REFS_NONE;
+
+ if (send_all)
+ flags |= MATCH_REFS_ALL;
+ if (args.send_mirror)
+ flags |= MATCH_REFS_MIRROR;
+
+ /* match them up */
+ remote_tail = &remote_refs;
+ while (*remote_tail)
+ remote_tail = &((*remote_tail)->next);
+ if (match_refs(local_refs, remote_refs, &remote_tail,
+ nr_refspecs, refspecs, flags)) {
+ return -1;
+ }
- verify_remote_names(nr_heads, heads);
+ ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
- conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
- ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
+ close(fd[1]);
close(fd[0]);
- /* do_send_pack always closes fd[1] */
+
ret |= finish_connect(conn);
- return !!ret;
+
+ print_push_status(dest, remote_refs);
+
+ if (!args.dry_run && remote) {
+ struct ref *ref;
+ for (ref = remote_refs; ref; ref = ref->next)
+ update_tracking_ref(remote, ref);
+ }
+
+ if (!ret && !refs_pushed(remote_refs))
+ fprintf(stderr, "Everything up-to-date\n");
+
+ return ret;
}