When send-pack receives "shallow" lines from receive-pack, it knows the other end does not have a complete commit chains. It restrict itself to the commits that are not cut out by either end to make sure the result pack is usuable by receive-pack. The same technique here, using setup_alternate_shallow() and --shallow-file, might simplify similar code in upload-pack. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/send-pack.c | 7 +++++-- send-pack.c | 37 ++++++++++++++++++++++++++++++++----- send-pack.h | 4 +++- t/t5537-push-shallow.sh | 36 ++++++++++++++++++++++++++++++++++++ transport.c | 7 +++---- 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 7dd254f..14a73ba 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -94,6 +94,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) int fd[2]; struct child_process *conn; struct extra_have_objects extra_have; + struct extra_have_objects shallow; struct ref *remote_refs, *local_refs; int ret; int helper_status = 0; @@ -209,8 +210,10 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) } memset(&extra_have, 0, sizeof(extra_have)); + memset(&shallow, 0, sizeof(shallow)); - get_remote_heads(fd[0], NULL, 0, &remote_refs, REF_NORMAL, &extra_have, NULL); + get_remote_heads(fd[0], NULL, 0, &remote_refs, REF_NORMAL, + &extra_have, &shallow); transport_verify_remote_names(nr_refspecs, refspecs); @@ -230,7 +233,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); - ret = send_pack(&args, fd, conn, remote_refs, &extra_have); + ret = send_pack(&args, fd, conn, remote_refs, &extra_have, &shallow); if (helper_status) print_helper_status(remote_refs); diff --git a/send-pack.c b/send-pack.c index dcd3345..1b828b0 100644 --- a/send-pack.c +++ b/send-pack.c @@ -27,14 +27,19 @@ 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, struct send_pack_args *args) +static int pack_objects(int fd, struct ref *refs, + struct extra_have_objects *extra, + struct extra_have_objects *extra_shallow, + struct send_pack_args *args) { /* * The child becomes pack-objects --revs; we feed * the revision parameters to it via its stdin and * let its stdout go back to the other end. */ - const char *argv[] = { + const char *av[] = { + "--shallow-file", + NULL, "pack-objects", "--all-progress-implied", "--revs", @@ -45,10 +50,26 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext NULL, NULL, }; + const char **argv; struct child_process po; + static struct lock_file shallow_lock; + const char *alternate_shallow_file = NULL; int i; - i = 4; + if (extra_shallow->nr) { + memset(&shallow_lock, 0, sizeof(shallow_lock)); + /* just to load up .git/shallow if exists */ + is_repository_shallow(); + setup_alternate_shallow(&shallow_lock, + &alternate_shallow_file, + extra_shallow, 0); + av[1] = alternate_shallow_file; + argv = av; + i = 6; + } else { + argv = &av[2]; + i = 4; + } if (args->use_thin_pack) argv[i++] = "--thin"; if (args->use_ofs_delta) @@ -100,6 +121,10 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext if (finish_command(&po)) return -1; + + if (extra_shallow->nr) + rollback_lock_file(&shallow_lock); + return 0; } @@ -176,7 +201,8 @@ static int sideband_demux(int in, int out, void *data) 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 extra_have_objects *extra_have, + struct extra_have_objects *extra_shallow) { int in = fd[0]; int out = fd[1]; @@ -294,7 +320,8 @@ int send_pack(struct send_pack_args *args, } if (new_refs && cmds_sent) { - if (pack_objects(out, remote_refs, extra_have, args) < 0) { + if (pack_objects(out, remote_refs, extra_have, extra_shallow, + args) < 0) { for (ref = remote_refs; ref; ref = ref->next) ref->status = REF_STATUS_NONE; if (args->stateless_rpc) diff --git a/send-pack.h b/send-pack.h index 05d7ab1..1c8a343 100644 --- a/send-pack.h +++ b/send-pack.h @@ -16,6 +16,8 @@ struct send_pack_args { 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 *remote_refs, + struct extra_have_objects *extra_have, + struct extra_have_objects *extra_shallow); #endif diff --git a/t/t5537-push-shallow.sh b/t/t5537-push-shallow.sh index 37ad69b..beb85ce 100755 --- a/t/t5537-push-shallow.sh +++ b/t/t5537-push-shallow.sh @@ -71,4 +71,40 @@ EOF test_cmp expect actual ' +test_expect_success 'push from shallow to shallow' ' + ( + cd shallow && + git push ../shallow2/.git +master:refs/remotes/shallow/master + ) && + ( + cd shallow2 && + git log --format=%s shallow/master >actual && + git fsck && + cat <<EOF >expect && +5 +4 +3 +EOF + test_cmp expect actual + ) +' + +test_expect_success 'push from full to shallow' ' + ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` && + commit 1 && + git push shallow2/.git +master:refs/remotes/top/master && + ( + cd shallow2 && + git log --format=%s top/master >actual && + git fsck && + cat <<EOF >expect && +1 +4 +3 +EOF + test_cmp expect actual && + git cat-file blob `echo 1|git hash-object --stdin` >/dev/null + ) +' + test_done diff --git a/transport.c b/transport.c index f167ca5..d592e8d 100644 --- a/transport.c +++ b/transport.c @@ -802,11 +802,10 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re struct ref *tmp_refs; connect_setup(transport, 1, 0); - get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, NULL, NULL); + get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, + NULL, &data->shallow); data->got_remote_heads = 1; } - if (data->shallow.nr) - die("pushing to a shallow repository is not supported"); memset(&args, 0, sizeof(args)); args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR); @@ -819,7 +818,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN); ret = send_pack(&args, data->fd, data->conn, remote_refs, - &data->extra_have); + &data->extra_have, &data->shallow); close(data->fd[1]); close(data->fd[0]); -- 1.8.2.83.gc99314b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html