From 13eb4626c43b3116bb431671d593565eadc36852 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Thu, 5 Dec 2013 20:02:29 +0700 Subject: remote.h: replace struct extra_have_objects with struct sha1_array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latter can do everything the former can and is used in many more places. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- send-pack.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'send-pack.c') diff --git a/send-pack.c b/send-pack.c index fab62e3da0..14005faefc 100644 --- a/send-pack.c +++ b/send-pack.c @@ -10,6 +10,7 @@ #include "quote.h" #include "transport.h" #include "version.h" +#include "sha1-array.h" static int feed_object(const unsigned char *sha1, int fd, int negative) { @@ -28,7 +29,7 @@ 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 sha1_array *extra, struct send_pack_args *args) { /* * The child becomes pack-objects --revs; we feed @@ -71,7 +72,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext * parameters by writing to the pipe. */ for (i = 0; i < extra->nr; i++) - if (!feed_object(extra->array[i], po.in, 1)) + if (!feed_object(extra->sha1[i], po.in, 1)) break; while (refs) { @@ -177,7 +178,7 @@ 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 sha1_array *extra_have) { int in = fd[0]; int out = fd[1]; -- cgit v1.3-5-g9baa From 5dbd767601812209273ae007a97b7c9305dc6cfd Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Thu, 5 Dec 2013 20:02:44 +0700 Subject: receive/send-pack: support pushing from a shallow clone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/technical/pack-protocol.txt | 4 +- builtin/receive-pack.c | 78 +++++++++++++++++++++++++++---- builtin/send-pack.c | 2 +- send-pack.c | 3 ++ t/t5538-push-shallow.sh | 70 +++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 11 deletions(-) create mode 100755 t/t5538-push-shallow.sh (limited to 'send-pack.c') diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index eb8edd1d4d..c73b62f5e1 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -464,7 +464,9 @@ contain all the objects that the server will need to complete the new references. ---- - update-request = command-list [pack-file] + update-request = *shallow command-list [pack-file] + + shallow = PKT-LINE("shallow" SP obj-id) command-list = PKT-LINE(command NUL capability-list LF) *PKT-LINE(command LF) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 8927ddfd4f..b9de2e8ff6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -44,6 +44,7 @@ static int fix_thin = 1; static const char *head_name; static void *head_name_to_free; static int sent_capabilities; +static const char *alt_shallow_file; static enum deny_action parse_deny_action(const char *var, const char *value) { @@ -190,6 +191,7 @@ struct command { const char *error_string; unsigned int skip_update:1, did_not_exist:1; + int index; unsigned char old_sha1[20]; unsigned char new_sha1[20]; char ref_name[FLEX_ARRAY]; /* more */ @@ -688,7 +690,7 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20]) struct command *cmd = *cmd_list; while (cmd) { - if (!is_null_sha1(cmd->new_sha1)) { + if (!is_null_sha1(cmd->new_sha1) && !cmd->skip_update) { hashcpy(sha1, cmd->new_sha1); *cmd_list = cmd->next; return 0; @@ -755,7 +757,7 @@ static void execute_commands(struct command *commands, const char *unpacker_erro } } -static struct command *read_head_info(void) +static struct command *read_head_info(struct sha1_array *shallow) { struct command *commands = NULL; struct command **p = &commands; @@ -769,6 +771,14 @@ static struct command *read_head_info(void) line = packet_read_line(0, &len); if (!line) break; + + if (len == 48 && !prefixcmp(line, "shallow ")) { + if (get_sha1_hex(line + 8, old_sha1)) + die("protocol error: expected shallow sha, got '%s'", line + 8); + sha1_array_append(shallow, old_sha1); + continue; + } + if (len < 83 || line[40] != ' ' || line[81] != ' ' || @@ -820,7 +830,7 @@ static const char *parse_pack_header(struct pack_header *hdr) static const char *pack_lockfile; -static const char *unpack(int err_fd) +static const char *unpack(int err_fd, struct shallow_info *si) { struct pack_header hdr; struct argv_array av = ARGV_ARRAY_INIT; @@ -844,6 +854,11 @@ static const char *unpack(int err_fd) "--pack_header=%"PRIu32",%"PRIu32, ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries)); + if (si->nr_ours || si->nr_theirs) { + alt_shallow_file = setup_temporary_shallow(si->shallow); + argv_array_pushl(&av, "--shallow-file", alt_shallow_file, NULL); + } + memset(&child, 0, sizeof(child)); if (ntohl(hdr.hdr_entries) < unpack_limit) { argv_array_pushl(&av, "unpack-objects", hdr_arg, NULL); @@ -889,13 +904,13 @@ static const char *unpack(int err_fd) return NULL; } -static const char *unpack_with_sideband(void) +static const char *unpack_with_sideband(struct shallow_info *si) { struct async muxer; const char *ret; if (!use_sideband) - return unpack(0); + return unpack(0, si); memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; @@ -903,12 +918,48 @@ static const char *unpack_with_sideband(void) if (start_async(&muxer)) return NULL; - ret = unpack(muxer.in); + ret = unpack(muxer.in, si); finish_async(&muxer); return ret; } +static void update_shallow_info(struct command *commands, + struct shallow_info *si, + struct sha1_array *ref) +{ + struct command *cmd; + int *ref_status; + remove_nonexistent_theirs_shallow(si); + /* XXX remove_nonexistent_ours_in_pack() */ + if (!si->nr_ours && !si->nr_theirs) + return; + + for (cmd = commands; cmd; cmd = cmd->next) { + if (is_null_sha1(cmd->new_sha1)) + continue; + sha1_array_append(ref, cmd->new_sha1); + cmd->index = ref->nr - 1; + } + si->ref = ref; + + ref_status = xmalloc(sizeof(*ref_status) * ref->nr); + assign_shallow_commits_to_refs(si, NULL, ref_status); + for (cmd = commands; cmd; cmd = cmd->next) { + if (is_null_sha1(cmd->new_sha1)) + continue; + if (ref_status[cmd->index]) { + cmd->error_string = "shallow update not allowed"; + cmd->skip_update = 1; + } + } + if (alt_shallow_file && *alt_shallow_file) { + unlink(alt_shallow_file); + alt_shallow_file = NULL; + } + free(ref_status); +} + static void report(struct command *commands, const char *unpack_status) { struct command *cmd; @@ -950,6 +1001,9 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) int i; char *dir = NULL; struct command *commands; + struct sha1_array shallow = SHA1_ARRAY_INIT; + struct sha1_array ref = SHA1_ARRAY_INIT; + struct shallow_info si; packet_trace_identity("receive-pack"); @@ -1006,11 +1060,14 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) if (advertise_refs) return 0; - if ((commands = read_head_info()) != NULL) { + if ((commands = read_head_info(&shallow)) != NULL) { const char *unpack_status = NULL; - if (!delete_only(commands)) - unpack_status = unpack_with_sideband(); + prepare_shallow_info(&si, &shallow); + if (!delete_only(commands)) { + unpack_status = unpack_with_sideband(&si); + update_shallow_info(commands, &si, &ref); + } execute_commands(commands, unpack_status); if (pack_lockfile) unlink_or_warn(pack_lockfile); @@ -1027,8 +1084,11 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) } if (auto_update_server_info) update_server_info(0); + clear_shallow_info(&si); } if (use_sideband) packet_flush(1); + sha1_array_clear(&shallow); + sha1_array_clear(&ref); return 0; } diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 62cc4d3681..ea2ab2815e 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -208,7 +208,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) (send_all && args.send_mirror)) usage(send_pack_usage); - if (is_repository_shallow()) + if (is_repository_shallow() && args.stateless_rpc) die("attempt to push from a shallow repository"); if (remote_name) { diff --git a/send-pack.c b/send-pack.c index 14005faefc..cd536b4ed5 100644 --- a/send-pack.c +++ b/send-pack.c @@ -214,6 +214,9 @@ int send_pack(struct send_pack_args *args, return 0; } + if (!args->dry_run) + advertise_shallow_grafts(out); + /* * Finally, tell the other end! */ diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh new file mode 100755 index 0000000000..650c31a888 --- /dev/null +++ b/t/t5538-push-shallow.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='push from/to a shallow clone' + +. ./test-lib.sh + +commit() { + echo "$1" >tracked && + git add tracked && + git commit -m "$1" +} + +test_expect_success 'setup' ' + git config --global transfer.fsckObjects true && + commit 1 && + commit 2 && + commit 3 && + commit 4 && + ( + git init full-abc && + cd full-abc && + commit a && + commit b && + commit c + ) && + git clone --no-local --depth=2 .git shallow && + git --git-dir=shallow/.git log --format=%s >actual && + cat <expect && +4 +3 +EOF + test_cmp expect actual && + git clone --no-local --depth=2 full-abc/.git shallow2 && + git --git-dir=shallow2/.git log --format=%s >actual && + cat <expect && +c +b +EOF + test_cmp expect actual +' + +test_expect_success 'push from shallow clone' ' + ( + cd shallow && + commit 5 && + git push ../.git +master:refs/remotes/shallow/master + ) && + git log --format=%s shallow/master >actual && + git fsck && + cat <expect && +5 +4 +3 +2 +1 +EOF + test_cmp expect actual +' + +test_expect_success 'push from shallow clone, with grafted roots' ' + ( + cd shallow2 && + test_must_fail git push ../.git +master:refs/remotes/shallow2/master 2>err && + grep "shallow2/master.*shallow update not allowed" err + ) && + test_must_fail git rev-parse shallow2/master && + git fsck +' + +test_done -- cgit v1.3-5-g9baa From f2c681cf12c54ce3859b36693f8a13c36126577b Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Thu, 5 Dec 2013 20:02:52 +0700 Subject: send-pack: support pushing from a shallow clone via http MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- builtin/send-pack.c | 3 --- send-pack.c | 19 +++++++++++++++++-- t/t5538-push-shallow.sh | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) (limited to 'send-pack.c') diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 664dd20f40..cc25744817 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -209,9 +209,6 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) (send_all && args.send_mirror)) usage(send_pack_usage); - if (is_repository_shallow() && args.stateless_rpc) - die("attempt to push from a shallow repository"); - if (remote_name) { remote = remote_get(remote_name); if (!remote_has_url(remote, dest)) { diff --git a/send-pack.c b/send-pack.c index cd536b4ed5..848d15e9b5 100644 --- a/send-pack.c +++ b/send-pack.c @@ -175,6 +175,21 @@ static int sideband_demux(int in, int out, void *data) return ret; } +static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *cb) +{ + struct strbuf *sb = cb; + if (graft->nr_parent == -1) + packet_buf_write(sb, "shallow %s\n", sha1_to_hex(graft->sha1)); + return 0; +} + +void advertise_shallow_grafts_buf(struct strbuf *sb) +{ + if (!is_repository_shallow()) + return; + for_each_commit_graft(advertise_shallow_grafts_cb, sb); +} + int send_pack(struct send_pack_args *args, int fd[], struct child_process *conn, struct ref *remote_refs, @@ -215,7 +230,7 @@ int send_pack(struct send_pack_args *args, } if (!args->dry_run) - advertise_shallow_grafts(out); + advertise_shallow_grafts_buf(&req_buf); /* * Finally, tell the other end! @@ -276,7 +291,7 @@ int send_pack(struct send_pack_args *args, } if (args->stateless_rpc) { - if (!args->dry_run && cmds_sent) { + if (!args->dry_run && (cmds_sent || is_repository_shallow())) { packet_buf_flush(&req_buf); send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX); } diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh index 866621a745..0a6e40f144 100755 --- a/t/t5538-push-shallow.sh +++ b/t/t5538-push-shallow.sh @@ -154,5 +154,30 @@ EOF ) ' +test_expect_success 'push from shallow repo via http' ' + mv "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" shallow-upstream.git && + git clone --bare --no-local full "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + ( + cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git config http.receivepack true + ) && + commit 10 && + git push $HTTPD_URL/smart/repo.git +master:refs/remotes/top/master && + ( + cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git fsck && + git log --format=%s top/master >actual && + cat <expect && +10 +1 +4 +3 +2 +1 +EOF + test_cmp expect actual + ) +' + stop_httpd test_done -- cgit v1.3-5-g9baa From 16a2743cd08c74d71b17e663c05c878fddffa03c Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Sun, 5 Jan 2014 23:55:01 +0000 Subject: send-pack.c: mark a file-local function static Commit f2c681cf ("send-pack: support pushing from a shallow clone via http", 05-12-2013) adds the 'advertise_shallow_grafts_buf' function as an external symbol. Noticed by sparse. ("'advertise_shallow_grafts_buf' was not declared. Should it be static?") Signed-off-by: Ramsay Jones Signed-off-by: Junio C Hamano --- send-pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'send-pack.c') diff --git a/send-pack.c b/send-pack.c index 848d15e9b5..cdcdea7a75 100644 --- a/send-pack.c +++ b/send-pack.c @@ -183,7 +183,7 @@ static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *c return 0; } -void advertise_shallow_grafts_buf(struct strbuf *sb) +static void advertise_shallow_grafts_buf(struct strbuf *sb) { if (!is_repository_shallow()) return; -- cgit v1.3-5-g9baa