"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
" --all and explicit <head> specification are mutually exclusive.";
static const char *exec = "git-receive-pack";
-static int verbose = 0;
-static int send_all = 0;
-static int force_update = 0;
-static int use_thin_pack = 0;
+static int verbose;
+static int send_all;
+static int force_update;
+static int use_thin_pack;
static int is_zero_sha1(const unsigned char *sha1)
{
static void exec_pack_objects(void)
{
- static char *args[] = {
+ static const char *args[] = {
"pack-objects",
"--stdout",
NULL
static void exec_rev_list(struct ref *refs)
{
- static char *args[1000];
- int i = 0;
+ struct ref *ref;
+ static const char *args[1000];
+ int i = 0, j;
args[i++] = "rev-list"; /* 0 */
if (use_thin_pack) /* 1 */
args[i++] = "--objects-edge";
else
args[i++] = "--objects";
- while (refs) {
- char *buf = malloc(100);
- if (i > 900)
+
+ /* First send the ones we care about most */
+ for (ref = refs; ref; ref = ref->next) {
+ if (900 < i)
die("git-rev-list environment overflow");
- if (!is_zero_sha1(refs->old_sha1) &&
- has_sha1_file(refs->old_sha1)) {
+ if (!is_zero_sha1(ref->new_sha1)) {
+ char *buf = malloc(100);
args[i++] = buf;
- snprintf(buf, 50, "^%s", sha1_to_hex(refs->old_sha1));
+ snprintf(buf, 50, "%s", sha1_to_hex(ref->new_sha1));
buf += 50;
+ if (!is_zero_sha1(ref->old_sha1) &&
+ has_sha1_file(ref->old_sha1)) {
+ args[i++] = buf;
+ snprintf(buf, 50, "^%s",
+ sha1_to_hex(ref->old_sha1));
+ }
}
- if (!is_zero_sha1(refs->new_sha1)) {
+ }
+
+ /* Then a handful of the remainder
+ * NEEDSWORK: we would be better off if used the newer ones first.
+ */
+ for (ref = refs, j = i + 16;
+ i < 900 && i < j && ref;
+ ref = ref->next) {
+ if (is_zero_sha1(ref->new_sha1) &&
+ !is_zero_sha1(ref->old_sha1) &&
+ has_sha1_file(ref->old_sha1)) {
+ char *buf = malloc(42);
args[i++] = buf;
- snprintf(buf, 50, "%s", sha1_to_hex(refs->new_sha1));
+ snprintf(buf, 42, "^%s", sha1_to_hex(ref->old_sha1));
}
- refs = refs->next;
}
args[i] = NULL;
execv_git_cmd(args);
exec_rev_list(refs);
}
-static int pack_objects(int fd, struct ref *refs)
+static void pack_objects(int fd, struct ref *refs)
{
pid_t rev_list_pid;
* We don't wait for the rev-list pipeline in the parent:
* we end up waiting for the other end instead
*/
- return 0;
}
static void unmark_and_free(struct commit_list *list, unsigned int mark)
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
- if (!o || o->type != commit_type)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
o = deref_tag(parse_object(new_sha1), NULL, 0);
- if (!o || o->type != commit_type)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
int expect_status_report = 0;
/* No funny business with the matcher */
- remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, 1);
+ remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);
get_local_heads();
/* Does the other end support the reporting? */
pid_t pid;
setup_git_directory();
+ git_config(git_default_config);
+
argv++;
for (i = 1; i < argc; i++, argv++) {
char *arg = *argv;