* [PATCH] Packfile-uris support excluding commit objects @ 2021-05-07 2:11 Teng Long 2021-05-10 11:14 ` Ævar Arnfjörð Bjarmason 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long 0 siblings, 2 replies; 72+ messages in thread From: Teng Long @ 2021-05-07 2:11 UTC (permalink / raw) To: git; +Cc: jonathantanmy, Teng Long On the server, more sophisticated means of excluding objects should be supported, such as commit object. This commit introduces a new configuration `uploadpack.commitpackfileuri` for this. This patch only pack the commit object, not including the that commit and all objects that it references. This work will be done in a further patch recently. Similarly, there are related documents that will be included in subsequent patches. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 8 ++--- fetch-pack.c | 8 +++++ t/t5702-protocol-v2.sh | 71 +++++++++++++++++++++++++++++++++--------- upload-pack.c | 7 +++-- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..2f1817fe28 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2985,7 +2985,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.flags &= ~WRITE_REV; return 0; } - if (!strcmp(k, "uploadpack.blobpackfileuri")) { + if (!strcmp(k, "uploadpack.blobpackfileuri") || !strcmp(k, "uploadpack.commitpackfileuri")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); const char *oid_end, *pack_end; /* @@ -2998,11 +2998,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) *oid_end != ' ' || parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); + die(_("value of uploadpack.blobpackfileuri or upload.commitpackfileuri must be " + "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); + "uploadpack.blobpackfileuri or uploadpack.commitpackfileuri (got '%s')"), v); ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); diff --git a/fetch-pack.c b/fetch-pack.c index 2318ebe680..24a947835b 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -23,6 +23,7 @@ #include "fetch-negotiator.h" #include "fsck.h" #include "shallow.h" +#include "strmap.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -1677,6 +1678,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, } } + struct strset uris; + strset_init(&uris); for (i = 0; i < packfile_uris.nr; i++) { int j; struct child_process cmd = CHILD_PROCESS_INIT; @@ -1684,6 +1687,11 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, const char *uri = packfile_uris.items[i].string + the_hash_algo->hexsz + 1; + if (strset_contains(&uris, uri)) { + continue; + } + + strset_add(&uris, uri); strvec_push(&cmd.args, "http-fetch"); strvec_pushf(&cmd.args, "--packfile=%.*s", (int) the_hash_algo->hexsz, diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..d444177fb5 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -824,12 +824,22 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + if test "$1" = "blob" + then + git -C "$2" hash-object "$3" >objh && + git -C "$2" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$2" config --add \ + "uploadpack.blobpackfileuri" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "$3" > objh && + git -C "$2" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$2" config --add \ + "uploadpack.commitpackfileuri" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + fi } test_expect_success 'part of packfile response provided as URI' ' @@ -845,8 +855,8 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add other-blob && git -C "$P" commit -m x && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob >h && + configure_exclusion blob "$P" other-blob >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -881,7 +891,7 @@ test_expect_success 'part of packfile response provided as URI' ' test_line_count = 6 filelist ' -test_expect_success 'packfile URIs with fetch instead of clone' ' +test_expect_success 'blobs packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && rm -rf "$P" http_child log && @@ -892,7 +902,7 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' git -C "$P" add my-blob && git -C "$P" commit -m x && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && git init http_child && @@ -902,6 +912,37 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' fetch "$HTTPD_URL/smart/http_parent" ' +test_expect_success 'commits packfile URIs with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + rm -rf "$P" http_child log && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + git -C "$P" commit -m x && + + + mycommit=$(git -C "$P" rev-parse HEAD) && + echo other-blob >"$P/other-blob" && + git -C "$P" add other-blob && + git -C "$P" commit -m x && + othercommit=$(git -C "$P" rev-parse HEAD) && + configure_exclusion commit "$P" "$mycommit" >h && + configure_exclusion commit "$P" "$othercommit" >h2 && + + git init http_child && + + GIT_TRACE=1 GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch "$HTTPD_URL/smart/http_parent" && + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 6 filelist +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && rm -rf "$P" http_child log && @@ -915,7 +956,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add other-blob && git -C "$P" commit -m x && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -944,7 +985,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' git -C "$P" add my-blob && git -C "$P" commit -m x && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -978,7 +1019,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' git -C "$P" add my-blob && git -C "$P" commit -m x && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1000,7 +1041,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1026,7 +1067,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..34f8bb81a8 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1744,9 +1744,12 @@ int upload_pack_advertise(struct repository *r, allow_sideband_all_value)) strbuf_addstr(value, " sideband-all"); - if (!repo_config_get_string(the_repository, + if ((!repo_config_get_string(the_repository, "uploadpack.blobpackfileuri", - &str) && + &str) || + !repo_config_get_string(the_repository, + "uploadpack.commitpackfileuri", + &str)) && str) { strbuf_addstr(value, " packfile-uris"); free(str); -- 2.31.1.442.g7e39198978.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH] Packfile-uris support excluding commit objects 2021-05-07 2:11 [PATCH] Packfile-uris support excluding commit objects Teng Long @ 2021-05-10 11:14 ` Ævar Arnfjörð Bjarmason 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long 1 sibling, 0 replies; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-05-10 11:14 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy On Fri, May 07 2021, Teng Long wrote: It seems like this and your http://lore.kernel.org/git/20210506073354.27833-1-dyroneteng@gmail.com should be part of one series, not split up. > On the server, more sophisticated means of excluding objects should be > supported, such as commit object. This commit introduces a new > configuration `uploadpack.commitpackfileuri` for this. Per my understanding in https://lore.kernel.org/git/87o8hk820f.fsf@evledraar.gmail.com/ this + Jonathan's earlier bfc2a36ff2a (Doc: clarify contents of packfile sent as URI, 2021-01-20) still makes this whole thing more confusing that it needs to be. I think we should just have a new uploadpack.excludeObject, and document that uploadpack.blobpackfileuri is an (unfortunately named) synonym for it. I.e. the actual implementation doesn't care about the objec type it just excludes any object listed via an oidmap. No? As for some comments on the implementation: > This patch only pack the commit object, not including the that commit > and all objects that it references. This work will be done in a further > patch recently. I realize you're probably not a native English speaker (neither am I), but I honestly can't understand that "This work will be done in a further patch recently.". Do you mean something like: This change does not add support for recursively excluding things referenced by container objects such as "commit", "tag", and "tree". We'll still just dumbly exclude that specific object (this was originally meant for specific "blobs"). Smartly excluding things recursively might be implemented by a future change. > Similarly, there are related documents that will be included in > subsequent patches. Please send the earlier doc cleanup + the spec change for this + any doc updates as one series. Narrow comments on the patch: > Signed-off-by: Teng Long <dyroneteng@gmail.com> > --- > builtin/pack-objects.c | 8 ++--- > fetch-pack.c | 8 +++++ > t/t5702-protocol-v2.sh | 71 +++++++++++++++++++++++++++++++++--------- > upload-pack.c | 7 +++-- > 4 files changed, 73 insertions(+), 21 deletions(-) > > diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c > index 6d13cd3e1a..2f1817fe28 100644 > --- a/builtin/pack-objects.c > +++ b/builtin/pack-objects.c > @@ -2985,7 +2985,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) > pack_idx_opts.flags &= ~WRITE_REV; > return 0; > } > - if (!strcmp(k, "uploadpack.blobpackfileuri")) { > + if (!strcmp(k, "uploadpack.blobpackfileuri") || !strcmp(k, "uploadpack.commitpackfileuri")) { Nit: Split this across two lines. > struct configured_exclusion *ex = xmalloc(sizeof(*ex)); > const char *oid_end, *pack_end; > /* > @@ -2998,11 +2998,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) > *oid_end != ' ' || > parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || > *pack_end != ' ') > - die(_("value of uploadpack.blobpackfileuri must be " > - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); > + die(_("value of uploadpack.blobpackfileuri or upload.commitpackfileuri must be " > + "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); Indending with spaces. > if (oidmap_get(&configured_exclusions, &ex->e.oid)) > die(_("object already configured in another " > - "uploadpack.blobpackfileuri (got '%s')"), v); > + "uploadpack.blobpackfileuri or uploadpack.commitpackfileuri (got '%s')"), v); I think by having a uploadpack.excludeObject documented as the primary interface to this we could just say "object already listed by an earlier exclusion" or something like that. > ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); > memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); > ex->uri = xstrdup(pack_end + 1); > diff --git a/fetch-pack.c b/fetch-pack.c > index 2318ebe680..24a947835b 100644 > --- a/fetch-pack.c > +++ b/fetch-pack.c > @@ -23,6 +23,7 @@ > #include "fetch-negotiator.h" > #include "fsck.h" > #include "shallow.h" > +#include "strmap.h" > > static int transfer_unpack_limit = -1; > static int fetch_unpack_limit = -1; > @@ -1677,6 +1678,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > } > } > > + struct strset uris; > + strset_init(&uris); > for (i = 0; i < packfile_uris.nr; i++) { > int j; > struct child_process cmd = CHILD_PROCESS_INIT; > @@ -1684,6 +1687,11 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > const char *uri = packfile_uris.items[i].string + > the_hash_algo->hexsz + 1; > > + if (strset_contains(&uris, uri)) { > + continue; > + } More indenting with spaces, also don't need the {} here. > + > + strset_add(&uris, uri); > strvec_push(&cmd.args, "http-fetch"); > strvec_pushf(&cmd.args, "--packfile=%.*s", > (int) the_hash_algo->hexsz, > diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh > index 2e1243ca40..d444177fb5 100755 > --- a/t/t5702-protocol-v2.sh > +++ b/t/t5702-protocol-v2.sh > @@ -824,12 +824,22 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' > ' > > configure_exclusion () { > - git -C "$1" hash-object "$2" >objh && > - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && > - git -C "$1" config --add \ > - "uploadpack.blobpackfileuri" \ > - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > - cat objh > + if test "$1" = "blob" > + then Don't indent the "then", also spaces... > + git -C "$2" hash-object "$3" >objh && > + git -C "$2" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && > + git -C "$2" config --add \ > + "uploadpack.blobpackfileuri" \ > + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > + cat objh > + else > + echo "$3" > objh && Use ">objh" not "> objh". > + git -C "$2" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && > + git -C "$2" config --add \ > + "uploadpack.commitpackfileuri" \ > + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > + cat objh This whole if/else seems like it could be better split up by discovering the variable first, using that as a variable, and then avoiding the duplication. But if we just used uploadpack.excludeObject... > + fi > } > > test_expect_success 'part of packfile response provided as URI' ' > @@ -845,8 +855,8 @@ test_expect_success 'part of packfile response provided as URI' ' > git -C "$P" add other-blob && > git -C "$P" commit -m x && > > - configure_exclusion "$P" my-blob >h && > - configure_exclusion "$P" other-blob >h2 && > + configure_exclusion blob "$P" my-blob >h && > + configure_exclusion blob "$P" other-blob >h2 && > > GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ > git -c protocol.version=2 \ > @@ -881,7 +891,7 @@ test_expect_success 'part of packfile response provided as URI' ' > test_line_count = 6 filelist > ' > > -test_expect_success 'packfile URIs with fetch instead of clone' ' > +test_expect_success 'blobs packfile URIs with fetch instead of clone' ' > P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > rm -rf "$P" http_child log && > > @@ -892,7 +902,7 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' > git -C "$P" add my-blob && > git -C "$P" commit -m x && > > - configure_exclusion "$P" my-blob >h && > + configure_exclusion blob "$P" my-blob >h && > > git init http_child && > > @@ -902,6 +912,37 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' > fetch "$HTTPD_URL/smart/http_parent" > ' > > +test_expect_success 'commits packfile URIs with fetch instead of clone' ' > + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > + rm -rf "$P" http_child log && Put stuff like this in "test_when_finished" > + > + git init "$P" && > + git -C "$P" config "uploadpack.allowsidebandall" "true" && > + > + echo my-blob >"$P/my-blob" && > + git -C "$P" add my-blob && > + git -C "$P" commit -m x && You can just use test_commit here, no? > + > + > + mycommit=$(git -C "$P" rev-parse HEAD) && > + echo other-blob >"$P/other-blob" && > + git -C "$P" add other-blob && > + git -C "$P" commit -m x && ditto test_commit. > + othercommit=$(git -C "$P" rev-parse HEAD) && > + configure_exclusion commit "$P" "$mycommit" >h && > + configure_exclusion commit "$P" "$othercommit" >h2 && Personally I'd just skip this whole "rev-parse HEAD" etc. and just pass the tag name(s) created by earlier test_commit, then have configure_exclusion ust always do a rev-parse... > + > + git init http_child && > + > + GIT_TRACE=1 GIT_TEST_SIDEBAND_ALL=1 \ > + git -C http_child -c protocol.version=2 \ > + -c fetch.uriprotocols=http,https \ > + fetch "$HTTPD_URL/smart/http_parent" && > + ls http_child/.git/objects/pack/*.pack \ > + http_child/.git/objects/pack/*.idx >filelist && > + test_line_count = 6 filelist > +' > + > test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' > P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > rm -rf "$P" http_child log && > @@ -915,7 +956,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' > git -C "$P" add other-blob && > git -C "$P" commit -m x && > > - configure_exclusion "$P" my-blob >h && > + configure_exclusion blob "$P" my-blob >h && > # Configure a URL for other-blob. Just reuse the hash of the object as > # the hash of the packfile, since the hash does not matter for this > # test as long as it is not the hash of the pack, and it is of the > @@ -944,7 +985,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' > git -C "$P" add my-blob && > git -C "$P" commit -m x && > > - configure_exclusion "$P" my-blob >h && > + configure_exclusion blob "$P" my-blob >h && > > sane_unset GIT_TEST_SIDEBAND_ALL && > git -c protocol.version=2 -c transfer.fsckobjects=1 \ > @@ -978,7 +1019,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' > git -C "$P" add my-blob && > git -C "$P" commit -m x && > > - configure_exclusion "$P" my-blob >h && > + configure_exclusion blob "$P" my-blob >h && > > sane_unset GIT_TEST_SIDEBAND_ALL && > test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ > @@ -1000,7 +1041,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo > git -C "$P" add .gitmodules && > git -C "$P" commit -m x && > > - configure_exclusion "$P" .gitmodules >h && > + configure_exclusion blob "$P" .gitmodules >h && > > sane_unset GIT_TEST_SIDEBAND_ALL && > git -c protocol.version=2 -c transfer.fsckobjects=1 \ > @@ -1026,7 +1067,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul > git -C "$P" add .gitmodules && > git -C "$P" commit -m x && > > - configure_exclusion "$P" .gitmodules >h && > + configure_exclusion blob "$P" .gitmodules >h && > > sane_unset GIT_TEST_SIDEBAND_ALL && > test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ > diff --git a/upload-pack.c b/upload-pack.c > index 5c1cd19612..34f8bb81a8 100644 > --- a/upload-pack.c > +++ b/upload-pack.c > @@ -1744,9 +1744,12 @@ int upload_pack_advertise(struct repository *r, > allow_sideband_all_value)) > strbuf_addstr(value, " sideband-all"); > > - if (!repo_config_get_string(the_repository, > + if ((!repo_config_get_string(the_repository, > "uploadpack.blobpackfileuri", > - &str) && > + &str) || > + !repo_config_get_string(the_repository, > + "uploadpack.commitpackfileuri", > + &str)) && > str) { > strbuf_addstr(value, " packfile-uris"); > free(str); Not a new issue, but I wonder if we shouldn't just export configset_find_element(). This is at least 2 stackframes down the chain of the "does this key exist?" we actually care about here. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v2 0/3] packfile-uris: commit objects exclusion 2021-05-07 2:11 [PATCH] Packfile-uris support excluding commit objects Teng Long 2021-05-10 11:14 ` Ævar Arnfjörð Bjarmason @ 2021-05-18 8:49 ` Teng Long 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long ` (3 more replies) 1 sibling, 4 replies; 72+ messages in thread From: Teng Long @ 2021-05-18 8:49 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Changes since v2: * Rename the "uploadpack.blobpackfileuri" configuration to "uploadpack.excludeobject". * In addition to blobs, packfile-uris now supports the exclusion of commit objects (recursive and non-recursive). * Added a patch to modify the packfile-uris.txt file. * Added a patch for related tests in t5702. About renaming, I do not know whether it will bring some compatibility impact, packfile-uris now is an experimental feature, how to deal with this situation, hoping to get some advice. Also, I did not consider implementing packfile-uri support for tree objects, because in the design scenario of packfile-uris, it seems to be of little use. Teng Long (3): packfile-uris: support for excluding commit object packfile-uris.txt: excluding commit object t5702: excluding commits with packfile-uris Documentation/technical/packfile-uri.txt | 20 ++-- builtin/pack-objects.c | 53 ++++++--- fetch-pack.c | 5 + t/t5702-protocol-v2.sh | 145 +++++++++++++++++------ upload-pack.c | 5 +- 5 files changed, 166 insertions(+), 62 deletions(-) Range-diff against v1: 1: 1f2fb5c85f < -: ---------- Packfile-uris support excluding commit objects -: ---------- > 1: 73e64147b1 packfile-uris: support for excluding commit object -: ---------- > 2: 4abab98a76 packfile-uris.txt: excluding commit object -: ---------- > 3: e824cc26a7 t5702: excluding commits with packfile-uris -- 2.31.1.442.g7e39198978.dirty ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v2 1/3] packfile-uris: support for excluding commit object 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long @ 2021-05-18 8:49 ` Teng Long 2021-05-19 4:28 ` Junio C Hamano 2021-05-20 4:46 ` Junio C Hamano 2021-05-18 8:49 ` [PATCH v2 2/3] packfile-uris.txt: " Teng Long ` (2 subsequent siblings) 3 siblings, 2 replies; 72+ messages in thread From: Teng Long @ 2021-05-18 8:49 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long On the server, more sophisticated means of excluding objects should be supported, such as commit object. This commit introduces a new configuration `uploadpack.excludeobject` for this. The old configuration `uploadpack.blobpackfileuri` is only support to exclude blobs and the name has no abstract meaning, so the configruation name changes, to support more object types. Compatibility issues will not be considered because packfile-uris now is an experimental feature. In addition to the configuration name, the format of the configuration value has also been expanded. When excluding the commits (or trees in the future) objects, the old format `<object-hash> <pack-hash> <uri>` can not express the meaning of recursion. So, the format is expanded, the new format `<object-hash> <recursively> <pack-hash> <uri>` should deal with this scenario (When processing commit objects, whether they are absolutely recursively excluded). Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 53 ++++++++++++++++++++++++++++++------------ fetch-pack.c | 5 ++++ upload-pack.c | 5 ++-- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..e687061420 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -99,6 +99,8 @@ static struct bitmap *reuse_packfile_bitmap; static int use_bitmap_index_default = 1; static int use_bitmap_index = -1; static int allow_pack_reuse = 1; +static int in_commit_order; +static int exclude_until_next_commit; static enum { WRITE_BITMAP_FALSE = 0, WRITE_BITMAP_QUIET, @@ -132,6 +134,7 @@ struct configured_exclusion { struct oidmap_entry e; char *pack_hash_hex; char *uri; + int recursively:1; }; static struct oidmap configured_exclusions; @@ -1291,10 +1294,16 @@ static int want_object_in_pack_one(struct packed_git *p, * and its offset in these variables. */ static int want_object_in_pack(const struct object_id *oid, + enum object_type type, int exclude, struct packed_git **found_pack, off_t *found_offset) { + if (exclude_until_next_commit && type != OBJ_COMMIT) + return 0; + if (type == OBJ_COMMIT) + exclude_until_next_commit = 0 ; + int want; struct list_head *pos; struct multi_pack_index *m; @@ -1345,6 +1354,8 @@ static int want_object_in_pack(const struct object_id *oid, &p) && *p == ':') { oidset_insert(&excluded_by_config, oid); + if(ex->recursively && type == OBJ_COMMIT) + exclude_until_next_commit = 1; return 0; } } @@ -1394,7 +1405,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { + if (!want_object_in_pack(oid, type, exclude, &found_pack, &found_offset)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1420,7 +1431,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, if (have_duplicate_entry(oid, 0)) return 0; - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack(oid, type, 0, &pack, &offset)) return 0; create_object_entry(oid, type, name_hash, 0, 0, pack, offset); @@ -2985,27 +2996,33 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.flags &= ~WRITE_REV; return 0; } - if (!strcmp(k, "uploadpack.blobpackfileuri")) { + if (!strcmp(k, "uploadpack.excludeobject")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); - const char *oid_end, *pack_end; + const char *oid_end, *pack_end, *recursively_end; /* * Stores the pack hash. This is not a true object ID, but is * of the same form. */ struct object_id pack_hash; - + char recursively[2]; if (parse_oid_hex(v, &ex->e.oid, &oid_end) || *oid_end != ' ' || - parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || + !strlcpy(recursively, oid_end + 1, sizeof(recursively)) || + parse_oid_hex(oid_end + 3, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); + die(_("value of uploadpack.excludeobject must be " + "of the form '<object-hash> <recursively> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) - die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); - ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); - memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); + die(_("object already configured by an earlier " + "uploadpack.excludeobject (got '%s')"), v); + recursively_end = oid_end + 2; + ex->pack_hash_hex = xcalloc(1, pack_end - recursively_end); + memcpy(ex->pack_hash_hex, recursively_end + 1, pack_end - recursively_end - 1); ex->uri = xstrdup(pack_end + 1); + if (atoi(recursively)) { + ex->recursively = 1; + in_commit_order = 1; + } oidmap_put(&configured_exclusions, ex); } return git_default_config(k, v, cb); @@ -3023,7 +3040,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, struct rev_info *revs = _data; struct object_info oi = OBJECT_INFO_INIT; off_t ofs; - enum object_type type; + static enum object_type type; display_progress(progress_state, ++nr_seen); @@ -3031,7 +3048,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; ofs = nth_packed_object_offset(p, pos); - if (!want_object_in_pack(oid, 0, &p, &ofs)) + if (!want_object_in_pack(oid, type, 0, &p, &ofs)) return 0; oi.typep = &type; @@ -3831,7 +3848,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject with this protocol")), OPT_END(), }; @@ -3903,6 +3920,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) fetch_if_missing = 0; strvec_push(&rp, "--exclude-promisor-objects"); } + + if (in_commit_order){ + use_internal_rev_list = 1; + strvec_push(&rp, "--in-commit-order"); + } + if (unpack_unreachable || keep_unreachable || pack_loose_unreachable) use_internal_rev_list = 1; diff --git a/fetch-pack.c b/fetch-pack.c index 2318ebe680..cdf8777907 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -23,6 +23,7 @@ #include "fetch-negotiator.h" #include "fsck.h" #include "shallow.h" +#include "strmap.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -1677,6 +1678,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, } } + struct strset uris; + strset_init(&uris); for (i = 0; i < packfile_uris.nr; i++) { int j; struct child_process cmd = CHILD_PROCESS_INIT; @@ -1684,6 +1687,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, const char *uri = packfile_uris.items[i].string + the_hash_algo->hexsz + 1; + if (!strset_add(&uris, uri)) + continue; strvec_push(&cmd.args, "http-fetch"); strvec_pushf(&cmd.args, "--packfile=%.*s", (int) the_hash_algo->hexsz, diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..4d994658d2 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1745,9 +1745,8 @@ int upload_pack_advertise(struct repository *r, strbuf_addstr(value, " sideband-all"); if (!repo_config_get_string(the_repository, - "uploadpack.blobpackfileuri", - &str) && - str) { + "uploadpack.excludeobject", + &str) && str) { strbuf_addstr(value, " packfile-uris"); free(str); } -- 2.31.1.442.g7e39198978.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v2 1/3] packfile-uris: support for excluding commit object 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long @ 2021-05-19 4:28 ` Junio C Hamano 2021-05-20 4:46 ` Junio C Hamano 1 sibling, 0 replies; 72+ messages in thread From: Junio C Hamano @ 2021-05-19 4:28 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy, avarab Teng Long <dyroneteng@gmail.com> writes: > On the server, more sophisticated means of excluding objects should be > supported, such as commit object. This commit introduces a new > configuration `uploadpack.excludeobject` for this. This "should" is not justfied at all, it seems? What is lacking in what we already have? What new things does it all us to do by adding a new configuration variable? > The old configuration `uploadpack.blobpackfileuri` is only support to > exclude blobs and the name has no abstract meaning, so the configruation > name changes, to support more object types. Compatibility issues will > not be considered because packfile-uris now is an experimental feature. I'll let Jonathan speak up, but even for an experimental feature, whatever new and incompatible way to do things should have a clear advantage compared to the old way. Sell the backward incomptibility along that line---"it is an experimental so I'll trash it" is not, but "by doing this it gets this much better, and migrating existing users won't be too taxing (it is just this simple thing)" is an acceptable way to justify such a change. Note that I am not opposed to the proposed change (and I am not supporting it, either). I do have a problem with the way the change is sold, though. > builtin/pack-objects.c | 53 ++++++++++++++++++++++++++++++------------ > fetch-pack.c | 5 ++++ > upload-pack.c | 5 ++-- > 3 files changed, 45 insertions(+), 18 deletions(-) Even though the name of the configuration variable changed, and the semantics of the value of it changed, there is no documentation change, because...? Because the original didn't even document the variable properly? It may be another reason why changing it may not impact the existing users too much. > @@ -132,6 +134,7 @@ struct configured_exclusion { > struct oidmap_entry e; > char *pack_hash_hex; > char *uri; > + int recursively:1; > }; > static struct oidmap configured_exclusions; > > @@ -1291,10 +1294,16 @@ static int want_object_in_pack_one(struct packed_git *p, > * and its offset in these variables. > */ > static int want_object_in_pack(const struct object_id *oid, > + enum object_type type, > int exclude, > struct packed_git **found_pack, > off_t *found_offset) > { > + if (exclude_until_next_commit && type != OBJ_COMMIT) > + return 0; > + if (type == OBJ_COMMIT) > + exclude_until_next_commit = 0 ; Lose SP before the semicolon. Our codebase does not allow statements before declarations. Move all of the above down to be below the block of decls at the beginning of the function. > int want; > struct list_head *pos; > struct multi_pack_index *m; > @@ -1345,6 +1354,8 @@ static int want_object_in_pack(const struct object_id *oid, > &p) && > *p == ':') { > oidset_insert(&excluded_by_config, oid); > + if(ex->recursively && type == OBJ_COMMIT) > + exclude_until_next_commit = 1; This depends on a new file-scope global variable, which means two things. * if two or more threads are deciding which object to pack and not to pack, this code will horribly break, as they are traversing totally different parts of the object DAG to find out which objects to pack, but one thread hitting a commit to be excluded and setting this flag will cause other thread skip unrelated blobs and trees that it discovers, doesn't it? * even if we assume there is no concurrency and reentrancy issues (e.g. by forcing single-threaded operation when this feature is in use), the code _assumes_ a concrete order in which this helper function gets called, namely, non-commit objects fed to this helper after the helper gets a single commit object *all* belong to that commit. With the current code that feeds objects as they are discovered during depth first traversal of the top-level tree starting at each commit, that assumption might hold, but it feels that the assumption is too much to be healty. For example, would it be possible for the bitmap code to cause this helper to be called in different order (i.e. it might find it more convenent to feed a tree, a blob or a tag that is unrelated to the commit that was last fed to the helper)? If so, the logic in this code will constrain the caller too much. I'll stop reading for now at this place; review of the remainder may come at a later time, but not now. Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v2 1/3] packfile-uris: support for excluding commit object 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long 2021-05-19 4:28 ` Junio C Hamano @ 2021-05-20 4:46 ` Junio C Hamano 1 sibling, 0 replies; 72+ messages in thread From: Junio C Hamano @ 2021-05-20 4:46 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy, avarab (continuing from yesterday's review) > @@ -3023,7 +3040,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, > struct rev_info *revs = _data; > struct object_info oi = OBJECT_INFO_INIT; > off_t ofs; > - enum object_type type; > + static enum object_type type; > > display_progress(progress_state, ++nr_seen); > > @@ -3031,7 +3048,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, > return 0; > > ofs = nth_packed_object_offset(p, pos); > - if (!want_object_in_pack(oid, 0, &p, &ofs)) > + if (!want_object_in_pack(oid, type, 0, &p, &ofs)) > return 0; > > oi.typep = &type; This change is puzzling. The first call to this helper will use BSS initialized type to call want_object_in_pack(), and then after that call says "yes, we want that object", packed_object_info() gets called to learn what type it is. And the second call would use the type of the object we previously handled, because type is a function scope static. Or if we are not that lucky and multiple threads are involved, the type we pass is from a random and unrelated object some other thread has called this helper with. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v2 2/3] packfile-uris.txt: excluding commit object 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long @ 2021-05-18 8:49 ` Teng Long 2021-05-18 8:49 ` [PATCH v2 3/3] t5702: excluding commits with packfile-uris Teng Long 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long 3 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-05-18 8:49 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Modified the content related to the configuration of packfile-uris, that is, the modification of the configuration format and the support for excluding commit objects, and cut some descriptions about future work. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- Documentation/technical/packfile-uri.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index f7eabc6c76..6ed850930f 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -35,13 +35,16 @@ include some sort of non-trivial implementation in the Minimum Viable Product, at least so that we can test the client. This is the implementation: a feature, marked experimental, that allows the -server to be configured by one or more `uploadpack.blobPackfileUri=<sha1> -<uri>` entries. Whenever the list of objects to be sent is assembled, all such -blobs are excluded, replaced with URIs. As noted in "Future work" below, the -server can evolve in the future to support excluding other objects (or other -implementations of servers could be made that support excluding other objects) -without needing a protocol change, so clients should not expect that packfiles -downloaded in this way only contain single blobs. +server to be configured by one or more entries with the format: + + uploadpack.excludeobject=<object-hash> <recursively> <pack-hash> <uri> + +Value <object-hash> is the key of entry, and the object type can be a blob +or commit. Value <recursively> works for commit object, if <recursively> +is configured as '1', then the commit and all the referenced objects by +the commit will be recursively excluded. Otherwise, only the commit itself +will be excluded. Whenever the list of objects to be sent is assembled, all +such objects are excluded, replaced with URIs. Client design ------------- @@ -65,9 +68,6 @@ The protocol design allows some evolution of the server and client without any need for protocol changes, so only a small-scoped design is included here to form the MVP. For example, the following can be done: - * On the server, more sophisticated means of excluding objects (e.g. by - specifying a commit to represent that commit and all objects that it - references). * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more -- 2.31.1.442.g7e39198978.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v2 3/3] t5702: excluding commits with packfile-uris 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long 2021-05-18 8:49 ` [PATCH v2 2/3] packfile-uris.txt: " Teng Long @ 2021-05-18 8:49 ` Teng Long 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long 3 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-05-18 8:49 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Modify the logic of configure_exclusion to support the processing of commits objects and add test cases for excluding commit objects (recursive and non-recursive). Replace "rm..." in the original test with "test_when_finished...". Replace "git commit..." in the original test with "test_commit...". Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 145 +++++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 34 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..2148bfcda1 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -753,7 +753,7 @@ test_expect_success 'ls-remote with v2 http sends only one POST' ' ' test_expect_success 'push with http:// and a config of v2 does not request v2' ' - test_when_finished "rm -f log" && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && # Till v2 for push is designed, make sure that if a client has # protocol.version configured to use v2, that the client instead falls # back and uses v0. @@ -776,7 +776,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' ' test_expect_success 'when server sends "ready", expect DELIM' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -796,7 +796,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' ' test_expect_success 'when server does not send "ready", expect FLUSH' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -824,17 +824,39 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + objt="$1" + P="$2" + recursive="$4" + + if test "$objt" = "blob" + then + git -C "$P" hash-object "$3" >objh && + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$P" config --add \ + "uploadpack.excludeobject" \ + "$(cat objh) $recursive $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + elif test "$objt" = "commit" + then + echo "$3" >objh + if test "$recursive" = 0 + then + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + else + git -C "$2" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + fi + git -C "$P" config --add \ + "uploadpack.excludeobject" \ + "$(cat objh) $recursive $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "unsupported object type in configure_exclusion (got $objt)" + fi } test_expect_success 'part of packfile response provided as URI' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -843,10 +865,10 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob 0 >h && + configure_exclusion blob "$P" other-blob 0 >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -881,18 +903,18 @@ test_expect_success 'part of packfile response provided as URI' ' test_line_count = 6 filelist ' -test_expect_success 'packfile URIs with fetch instead of clone' ' +test_expect_success 'blobs packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob 0 >h && git init http_child && @@ -902,9 +924,65 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' fetch "$HTTPD_URL/smart/http_parent" ' +test_expect_success 'commits(not recursively) packfile URIs with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + + mycommit=$(git -C "$P" rev-parse A) && + echo other-blob >"$P/other-blob" && + git -C "$P" add other-blob && + test_commit -C "$P" B && + othercommit=$(git -C "$P" rev-parse B) && + + configure_exclusion commit "$P" "$mycommit" 0 >h && + configure_exclusion commit "$P" "$othercommit" 0 >h2 && + + git init http_child && + + GIT_TRACE=1 GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch "$HTTPD_URL/smart/http_parent" +' + +test_expect_success 'commits(recursively) packfile URIs with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + + mycommit=$(git -C "$P" rev-parse A) && + echo other-blob >"$P/other-blob" && + git -C "$P" add other-blob && + test_commit -C "$P" B && + othercommit=$(git -C "$P" rev-parse B) && + + configure_exclusion commit "$P" "$mycommit" 1 >h2 && + configure_exclusion commit "$P" "$othercommit" 1 >h2 && + + git init http_child && + + GIT_TRACE=1 GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch "$HTTPD_URL/smart/http_parent" +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -913,9 +991,9 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob 0 >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -923,8 +1001,8 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" hash-object other-blob >objh && git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && git -C "$P" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + "uploadpack.excludeobject" \ + "$(cat objh) 0 $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && test_must_fail env GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -935,16 +1013,15 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' test_expect_success 'packfile-uri with transfer.fsckobjects' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob 0 >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -959,7 +1036,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -976,9 +1053,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob 0 >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -989,7 +1066,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child && + test_when_finished "rm -rf \"$P\" http_child" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1000,7 +1077,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules 0 >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1015,7 +1092,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodules separate from tree is invalid' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child err && + test_when_finished "rm -rf \"$P\" http_child err" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1024,9 +1101,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul echo "path = include/foo" >>"$P/.gitmodules" && echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules 0 >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -- 2.31.1.442.g7e39198978.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v3 0/3] packfile-uris: commit objects exclusio 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long ` (2 preceding siblings ...) 2021-05-18 8:49 ` [PATCH v2 3/3] t5702: excluding commits with packfile-uris Teng Long @ 2021-07-26 9:46 ` Teng Long 2021-07-26 9:46 ` [PATCH v3 1/3] packfile-uris: support for excluding commit objects Teng Long ` (4 more replies) 3 siblings, 5 replies; 72+ messages in thread From: Teng Long @ 2021-07-26 9:46 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Changes since v3: * Ensure the forward compatibility of the old configuration (uploadpack.blobpackfileuri). * Reimplementation of the commit object exclusion method (without rely on the "--in-commit-order" arg). * Extend `show_object` function. * Remove `exclude_until_next_commit` var in pack-objects.c (Concurrency issues). * Restore the definition of want_object_in_pack method (problems caused by the new "type" parameter) Teng Long (3): packfile-uris: support for excluding commit objects t5702: support for excluding commit objects packfile-uri.txt: support for excluding commit objects Documentation/technical/packfile-uri.txt | 20 +-- builtin/describe.c | 4 +- builtin/pack-objects.c | 97 +++++++------ builtin/rev-list.c | 2 +- fetch-pack.c | 6 + list-objects.c | 37 ++--- list-objects.h | 2 +- object.c | 15 +- object.h | 4 + pack-bitmap.c | 8 +- reachable.c | 8 +- revision.c | 36 +++-- revision.h | 4 + t/t5702-protocol-v2.sh | 166 ++++++++++++++++++----- upload-pack.c | 7 + 15 files changed, 291 insertions(+), 125 deletions(-) Range-diff against v2: -: ---------- > 1: 91dce385f6 packfile-uris: support for excluding commit objects -: ---------- > 2: 92def8c72b t5702: support for excluding commit objects -: ---------- > 3: 01ab2cbb34 packfile-uri.txt: support for excluding commit objects -- 2.31.1.443.g55c63af4c9.dirty ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v3 1/3] packfile-uris: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long @ 2021-07-26 9:46 ` Teng Long 2021-07-26 18:15 ` Junio C Hamano 2021-07-26 9:46 ` [PATCH v3 2/3] t5702: " Teng Long ` (3 subsequent siblings) 4 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-07-26 9:46 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long On the server, more sophisticated means of excluding objects should be supported, such as commit object. This commit introduces a new configuration `uploadpack.excludeobject` for this. The reason for bringing a new configuration is for two considerations. First, the old configuration supports a single object type (blob), which limits the use of this feature. Secondly, the name of the old configuration is not abstract enough, this make extension difficult. If different object types use different configuration names, the configuration items will be bloated and difficult to maintain, so the new configuration is more abstract in name and easy to extend. Although a new configuration has been introduced, the old one is still available and compatible with the new configuration. The old configuration `uploadpack.blobpackfileuri` only supports excluding blobs. The new configuration `uploadpack.excludeobject` not only supports excluding blob objects, but also supports excluding commit objects, as well as recursively excluding tree objects and blob objects they contain. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/describe.c | 4 +- builtin/pack-objects.c | 97 ++++++++++++++++++++++++------------------ builtin/rev-list.c | 2 +- fetch-pack.c | 6 +++ list-objects.c | 37 +++++++++------- list-objects.h | 2 +- object.c | 15 +++++-- object.h | 4 ++ pack-bitmap.c | 8 ++-- reachable.c | 8 ++-- revision.c | 36 +++++++++++----- revision.h | 4 ++ upload-pack.c | 7 +++ 13 files changed, 148 insertions(+), 82 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 40482d8e9f..045da79b5c 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -485,9 +485,9 @@ static void process_commit(struct commit *commit, void *data) pcd->current_commit = commit->object.oid; } -static void process_object(struct object *obj, const char *path, void *data) +static void process_object(struct object *obj, const char *path, void *show_data, void *carry_data) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = show_data; if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { reset_revision_walk(); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..154c98bcb6 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1188,6 +1188,24 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int match_packfile_uri_exclusions(struct configured_exclusion *ex) +{ + int i; + const char *p; + + if (ex) { + for (i = 0; i < uri_protocols.nr; i++) { + if (skip_prefix(ex->uri, + uri_protocols.items[i].string, + &p) && + *p == ':') + return 1; + + } + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1293,7 +1311,8 @@ static int want_object_in_pack_one(struct packed_git *p, static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + struct object *referred_commit) { int want; struct list_head *pos; @@ -1333,21 +1352,13 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - struct configured_exclusion *ex = - oidmap_get(&configured_exclusions, oid); - int i; - const char *p; - - if (ex) { - for (i = 0; i < uri_protocols.nr; i++) { - if (skip_prefix(ex->uri, - uri_protocols.items[i].string, - &p) && - *p == ':') { - oidset_insert(&excluded_by_config, oid); - return 0; - } - } + if (referred_commit) { + if (oidmap_get(&configured_exclusions, &referred_commit->oid) && match_packfile_uri_exclusions(referred_ex)) + return 0; + } + if (oidmap_get(&configured_exclusions, oid) && match_packfile_uri_exclusions(ex)) { + oidset_insert(&excluded_by_config, oid); + return 0; } } @@ -1384,7 +1395,8 @@ static const char no_closure_warning[] = N_( ); static int add_object_entry(const struct object_id *oid, enum object_type type, - const char *name, int exclude) + const char *name, int exclude, + struct object *referred_commit) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1394,7 +1406,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1420,7 +1432,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, if (have_duplicate_entry(oid, 0)) return 0; - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) return 0; create_object_entry(oid, type, name_hash, 0, 0, pack, offset); @@ -1560,7 +1572,7 @@ static void add_pbase_object(struct tree_desc *tree, if (name[cmplen] != '/') { add_object_entry(&entry.oid, object_type(entry.mode), - fullname, 1); + fullname, 1, NULL); return; } if (S_ISDIR(entry.mode)) { @@ -1628,7 +1640,7 @@ static void add_preferred_base_object(const char *name) cmplen = name_cmp_len(name); for (it = pbase_tree; it; it = it->next) { if (cmplen == 0) { - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); } else { struct tree_desc tree; @@ -2830,7 +2842,7 @@ static void add_tag_chain(const struct object_id *oid) die(_("unable to pack objects reachable from tag %s"), oid_to_hex(oid)); - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); if (tag->tagged->type != OBJ_TAG) return; @@ -2985,7 +2997,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.flags &= ~WRITE_REV; return 0; } - if (!strcmp(k, "uploadpack.blobpackfileuri")) { + if (!strcmp(k, "uploadpack.excludeobject") || !strcmp(k, "uploadpack.blobpackfileuri")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); const char *oid_end, *pack_end; /* @@ -2998,11 +3010,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) *oid_end != ' ' || parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); + die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " + "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) - die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); + die(_("object already configured by an earlier " + "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); @@ -3031,7 +3043,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; ofs = nth_packed_object_offset(p, pos); - if (!want_object_in_pack(oid, 0, &p, &ofs)) + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) return 0; oi.typep = &type; @@ -3059,7 +3071,7 @@ static void show_commit_pack_hint(struct commit *commit, void *_data) } static void show_object_pack_hint(struct object *object, const char *name, - void *_data) + void *show_data, void *carry_data) { struct object_entry *oe = packlist_find(&to_pack, &object->oid); if (!oe) @@ -3224,7 +3236,7 @@ static void read_object_list_from_stdin(void) die(_("expected object ID, got garbage:\n %s"), line); add_preferred_base_object(p + 1); - add_object_entry(&oid, OBJ_NONE, p + 1, 0); + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); } } @@ -3233,7 +3245,7 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, void *data) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) @@ -3243,10 +3255,11 @@ static void show_commit(struct commit *commit, void *data) propagate_island_marks(commit); } -static void show_object(struct object *obj, const char *name, void *data) +static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { + struct object *referred_commit = carry_data; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0); + add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { @@ -3265,7 +3278,7 @@ static void show_object(struct object *obj, const char *name, void *data) } } -static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_any(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_ANY); @@ -3276,10 +3289,10 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void if (!has_object(the_repository, &obj->oid, 0)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } -static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_PROMISOR); @@ -3290,7 +3303,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } static int option_parse_missing_action(const struct option *opt, @@ -3397,7 +3410,7 @@ static void add_objects_in_unpacked_packs(void) QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; - add_object_entry(&o->oid, o->type, "", 0); + add_object_entry(&o->oid, o->type, "", 0, NULL); } } free(in_pack.array); @@ -3413,7 +3426,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, return 0; } - add_object_entry(oid, type, "", 0); + add_object_entry(oid, type, "", 0, NULL); return 0; } @@ -3538,7 +3551,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs) static void record_recent_object(struct object *obj, const char *name, - void *data) + void *show_data, + void *carry_data) { oid_array_append(&recent_objects, &obj->oid); } @@ -3831,7 +3845,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject or " + "uploadpack.blobpackfileuri with this protocol")), OPT_END(), }; diff --git a/builtin/rev-list.c b/builtin/rev-list.c index b4d8ea0a35..1cad33d9e8 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -266,7 +266,7 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) return 0; } -static void show_object(struct object *obj, const char *name, void *cb_data) +static void show_object(struct object *obj, const char *name, void *cb_data, void *carry_data) { struct rev_list_info *info = cb_data; struct rev_info *revs = info->revs; diff --git a/fetch-pack.c b/fetch-pack.c index 2318ebe680..39bb449586 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -23,6 +23,7 @@ #include "fetch-negotiator.h" #include "fsck.h" #include "shallow.h" +#include "strmap.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -1576,6 +1577,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, struct string_list packfile_uris = STRING_LIST_INIT_DUP; int i; struct strvec index_pack_args = STRVEC_INIT; + struct strset uris; negotiator = &negotiator_alloc; fetch_negotiator_init(r, negotiator); @@ -1677,6 +1679,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, } } + strset_init(&uris); for (i = 0; i < packfile_uris.nr; i++) { int j; struct child_process cmd = CHILD_PROCESS_INIT; @@ -1684,6 +1687,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, const char *uri = packfile_uris.items[i].string + the_hash_algo->hexsz + 1; + if (!strset_add(&uris, uri)) + continue; strvec_push(&cmd.args, "http-fetch"); strvec_pushf(&cmd.args, "--packfile=%.*s", (int) the_hash_algo->hexsz, @@ -1727,6 +1732,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, get_object_directory(), packname)); } + strset_clear(&uris); string_list_clear(&packfile_uris, 0); strvec_clear(&index_pack_args); diff --git a/list-objects.c b/list-objects.c index e19589baa0..fa3156dc89 100644 --- a/list-objects.c +++ b/list-objects.c @@ -24,7 +24,8 @@ struct traversal_context { static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &blob->object; size_t pathlen; @@ -60,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data); + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); strbuf_setlen(path, pathlen); } @@ -97,11 +98,13 @@ static void process_gitlink(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name); + const char *name, + struct object *referred_commit); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, - struct strbuf *base) + struct strbuf *base, + struct object *referred_commit) { struct tree_desc desc; struct name_entry entry; @@ -129,7 +132,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path); + process_tree(ctx, t, base, entry.path, referred_commit); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -142,7 +145,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path); + process_blob(ctx, b, base, entry.path, referred_commit); } } } @@ -150,7 +153,8 @@ static void process_tree_contents(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -191,14 +195,14 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); if (base->len) strbuf_addch(base, '/'); if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base); + process_tree_contents(ctx, tree, base, referred_commit); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -207,7 +211,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -314,9 +318,9 @@ void mark_edges_uninteresting(struct rev_info *revs, } } -static void add_pending_tree(struct rev_info *revs, struct tree *tree) +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) { - add_pending_object(revs, &tree->object, ""); + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); } static void traverse_trees_and_blobs(struct traversal_context *ctx, @@ -329,23 +333,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; + struct object *referred_commit = pending->referred_commit; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data); + ctx->show_object(obj, name, ctx->show_data, referred_commit); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path); + process_tree(ctx, (struct tree *)obj, base, path, referred_commit); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path); + process_blob(ctx, (struct blob *)obj, base, path, referred_commit); continue; } die("unknown pending object %s (%s)", @@ -370,7 +375,7 @@ static void do_traverse(struct traversal_context *ctx) else if (get_commit_tree(commit)) { struct tree *tree = get_commit_tree(commit); tree->object.flags |= NOT_USER_GIVEN; - add_pending_tree(ctx->revs, tree); + add_pending_tree(ctx->revs, tree, &commit->object); } else if (commit->object.parsed) { die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); diff --git a/list-objects.h b/list-objects.h index a952680e46..ab946d34db 100644 --- a/list-objects.h +++ b/list-objects.h @@ -6,7 +6,7 @@ struct object; struct rev_info; typedef void (*show_commit_fn)(struct commit *, void *); -typedef void (*show_object_fn)(struct object *, const char *, void *); +typedef void (*show_object_fn)(struct object *, const char *, void *, void *); void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); typedef void (*show_edge_fn)(struct commit *); diff --git a/object.c b/object.c index 14188453c5..6b1ce2fcde 100644 --- a/object.c +++ b/object.c @@ -322,9 +322,10 @@ void object_list_free(struct object_list **list) */ static char object_array_slopbuf[1]; -void add_object_array_with_path(struct object *obj, const char *name, - struct object_array *array, - unsigned mode, const char *path) +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path, + struct object *referred_commit) { unsigned nr = array->nr; unsigned alloc = array->alloc; @@ -339,6 +340,7 @@ void add_object_array_with_path(struct object *obj, const char *name, } entry = &objects[nr]; entry->item = obj; + entry->referred_commit = referred_commit; if (!name) entry->name = NULL; else if (!*name) @@ -354,6 +356,13 @@ void add_object_array_with_path(struct object *obj, const char *name, array->nr = ++nr; } +void add_object_array_with_path(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path) +{ + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); +} + void add_object_array(struct object *obj, const char *name, struct object_array *array) { add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); diff --git a/object.h b/object.h index 87a6da47c8..de9f15b97d 100644 --- a/object.h +++ b/object.h @@ -43,6 +43,7 @@ struct object_array { unsigned int alloc; struct object_array_entry { struct object *item; + struct object *referred_commit; /* * name or NULL. If non-NULL, the memory pointed to * is owned by this object *except* if it points at @@ -157,6 +158,9 @@ void object_list_free(struct object_list **list); /* Object array handling .. */ void add_object_array(struct object *obj, const char *name, struct object_array *array); void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, + unsigned mode, const char *path, + struct object *referred_commit); /* * Returns NULL if the array is empty. Otherwise, returns the last object diff --git a/pack-bitmap.c b/pack-bitmap.c index 3ed15431cd..516eb235da 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -459,9 +459,9 @@ struct bitmap_show_data { struct bitmap *base; }; -static void show_object(struct object *object, const char *name, void *data_) +static void show_object(struct object *object, const char *name, void *show_data, void *carry_data) { - struct bitmap_show_data *data = data_; + struct bitmap_show_data *data = show_data; int bitmap_pos; bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); @@ -1268,9 +1268,9 @@ struct bitmap_test_data { }; static void test_show_object(struct object *object, const char *name, - void *data) + void *show_data, void *carry_data) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); diff --git a/reachable.c b/reachable.c index 77a60c70a5..ebd817c446 100644 --- a/reachable.c +++ b/reachable.c @@ -47,14 +47,14 @@ static int add_one_ref(const char *path, const struct object_id *oid, * The traversal will have already marked us as SEEN, so we * only need to handle any progress reporting here. */ -static void mark_object(struct object *obj, const char *name, void *data) +static void mark_object(struct object *obj, const char *name, void *show_data, void *carry_data) { - update_progress(data); + update_progress(show_data); } -static void mark_commit(struct commit *c, void *data) +static void mark_commit(struct commit *c, void *show_data) { - mark_object(&c->object, NULL, data); + mark_object(&c->object, NULL, show_data, NULL); } struct recent_data { diff --git a/revision.c b/revision.c index 4853c85d0b..da0ce0e3f2 100644 --- a/revision.c +++ b/revision.c @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) commit_stack_clear(&pending); } -static void add_pending_object_with_path(struct rev_info *revs, - struct object *obj, - const char *name, unsigned mode, - const char *path) +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path, + struct object *referred_commit) { struct interpret_branch_name_options options = { 0 }; if (!obj) @@ -326,20 +327,36 @@ static void add_pending_object_with_path(struct rev_info *revs, strbuf_release(&buf); return; /* do not add the commit itself */ } - add_object_array_with_path(obj, name, &revs->pending, mode, path); + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); +} + +static void add_pending_object_with_path(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path) { + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); } static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, - const char *name, unsigned mode) + const char *name, unsigned mode, + struct object *referred_commit) { - add_pending_object_with_path(revs, obj, name, mode, NULL); + + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); +} + +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit) +{ + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); } void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); } void add_head_to_pending(struct rev_info *revs) @@ -2764,7 +2781,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s continue; } - if (handle_revision_arg(arg, revs, flags, revarg_opt)) { int j; if (seen_dashdash || *arg == '^') @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) diagnose_missing_default(revs->def); object = get_reference(revs, revs->def, &oid, 0); - add_pending_object_with_mode(revs, object, revs->def, oc.mode); + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); } /* Did the user ask for any diff output? Run the diff! */ diff --git a/revision.h b/revision.h index a24f72dcd1..8a632e3587 100644 --- a/revision.h +++ b/revision.h @@ -424,6 +424,10 @@ void show_object_with_name(FILE *, struct object *, const char *); void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit); + void add_pending_oid(struct rev_info *revs, const char *name, const struct object_id *oid, unsigned int flags); diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..d26fb351a3 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, strbuf_addstr(value, " packfile-uris"); free(str); } + + if (!repo_config_get_string(the_repository, + "uploadpack.excludeobject", + &str) && str) { + strbuf_addstr(value, " packfile-uris"); + free(str); + } } return 1; -- 2.31.1.443.g55c63af4c9.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v3 1/3] packfile-uris: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 1/3] packfile-uris: support for excluding commit objects Teng Long @ 2021-07-26 18:15 ` Junio C Hamano 2021-07-26 19:45 ` Felipe Contreras 2021-08-11 1:44 ` Teng Long 0 siblings, 2 replies; 72+ messages in thread From: Junio C Hamano @ 2021-07-26 18:15 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy, avarab Teng Long <dyroneteng@gmail.com> writes: > On the server, more sophisticated means of excluding objects should be > supported, such as commit object. This commit introduces a new > configuration `uploadpack.excludeobject` for this. Please avoid adjectives that express subjective values, like "sophisticated". Readers will expect a lot more sophistication than your code actually offers and will be disappointed ("wow, that would be wonderful if we can say 'exclude commits made by bots, and those older than 3 months'---eh, you cannot do that? where is your sophistication then?"). Please avoid "should" without first describing the background for "why it should". It would help if you briefly describe what we currently have and its limitation before this first paragraph (i.e. your "we can already exclude only blob objects" would become major part of the explanation, but you'd need to present in what situations it would help to be able to exclude other types). This commit is probalby doing too many things at once. For example, refactoring like creation of match_packfile_uri_exclusions() helper function out of existing code (there probably are others) can and should be done as separate preparatory steps before the API gets modified (e.g. process-object callbacks gain an extra parameter) in tree-wide way. And by slimming the primary step that introduces the new feature, there will be a space to also add documentation and test in the same step, which would help reviewers. With the current structure of the series, with a code dump in the first step with only a vague promiss of "sophistication" without documentation updates, reviewers cannot even tell how the "commit object" is used easily. Thanks. > builtin/describe.c | 4 +- > builtin/pack-objects.c | 97 ++++++++++++++++++++++++------------------ > builtin/rev-list.c | 2 +- > fetch-pack.c | 6 +++ > list-objects.c | 37 +++++++++------- > list-objects.h | 2 +- > object.c | 15 +++++-- > object.h | 4 ++ > pack-bitmap.c | 8 ++-- > reachable.c | 8 ++-- > revision.c | 36 +++++++++++----- > revision.h | 4 ++ > upload-pack.c | 7 +++ > 13 files changed, 148 insertions(+), 82 deletions(-) > > diff --git a/builtin/describe.c b/builtin/describe.c > index 40482d8e9f..045da79b5c 100644 > --- a/builtin/describe.c > +++ b/builtin/describe.c > @@ -485,9 +485,9 @@ static void process_commit(struct commit *commit, void *data) > pcd->current_commit = commit->object.oid; > } > > -static void process_object(struct object *obj, const char *path, void *data) > +static void process_object(struct object *obj, const char *path, void *show_data, void *carry_data) > { > - struct process_commit_data *pcd = data; > + struct process_commit_data *pcd = show_data; > > if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { > reset_revision_walk(); > diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c > index 6d13cd3e1a..154c98bcb6 100644 > --- a/builtin/pack-objects.c > +++ b/builtin/pack-objects.c > @@ -1188,6 +1188,24 @@ static int have_duplicate_entry(const struct object_id *oid, > return 1; > } > > +static int match_packfile_uri_exclusions(struct configured_exclusion *ex) > +{ > + int i; > + const char *p; > + > + if (ex) { > + for (i = 0; i < uri_protocols.nr; i++) { > + if (skip_prefix(ex->uri, > + uri_protocols.items[i].string, > + &p) && > + *p == ':') > + return 1; > + > + } > + } > + return 0; > +} > + > static int want_found_object(const struct object_id *oid, int exclude, > struct packed_git *p) > { > @@ -1293,7 +1311,8 @@ static int want_object_in_pack_one(struct packed_git *p, > static int want_object_in_pack(const struct object_id *oid, > int exclude, > struct packed_git **found_pack, > - off_t *found_offset) > + off_t *found_offset, > + struct object *referred_commit) > { > int want; > struct list_head *pos; > @@ -1333,21 +1352,13 @@ static int want_object_in_pack(const struct object_id *oid, > } > > if (uri_protocols.nr) { > - struct configured_exclusion *ex = > - oidmap_get(&configured_exclusions, oid); > - int i; > - const char *p; > - > - if (ex) { > - for (i = 0; i < uri_protocols.nr; i++) { > - if (skip_prefix(ex->uri, > - uri_protocols.items[i].string, > - &p) && > - *p == ':') { > - oidset_insert(&excluded_by_config, oid); > - return 0; > - } > - } > + if (referred_commit) { > + if (oidmap_get(&configured_exclusions, &referred_commit->oid) && match_packfile_uri_exclusions(referred_ex)) > + return 0; > + } > + if (oidmap_get(&configured_exclusions, oid) && match_packfile_uri_exclusions(ex)) { > + oidset_insert(&excluded_by_config, oid); > + return 0; > } > } > > @@ -1384,7 +1395,8 @@ static const char no_closure_warning[] = N_( > ); > > static int add_object_entry(const struct object_id *oid, enum object_type type, > - const char *name, int exclude) > + const char *name, int exclude, > + struct object *referred_commit) > { > struct packed_git *found_pack = NULL; > off_t found_offset = 0; > @@ -1394,7 +1406,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, > if (have_duplicate_entry(oid, exclude)) > return 0; > > - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { > + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { > /* The pack is missing an object, so it will not have closure */ > if (write_bitmap_index) { > if (write_bitmap_index != WRITE_BITMAP_QUIET) > @@ -1420,7 +1432,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, > if (have_duplicate_entry(oid, 0)) > return 0; > > - if (!want_object_in_pack(oid, 0, &pack, &offset)) > + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) > return 0; > > create_object_entry(oid, type, name_hash, 0, 0, pack, offset); > @@ -1560,7 +1572,7 @@ static void add_pbase_object(struct tree_desc *tree, > if (name[cmplen] != '/') { > add_object_entry(&entry.oid, > object_type(entry.mode), > - fullname, 1); > + fullname, 1, NULL); > return; > } > if (S_ISDIR(entry.mode)) { > @@ -1628,7 +1640,7 @@ static void add_preferred_base_object(const char *name) > cmplen = name_cmp_len(name); > for (it = pbase_tree; it; it = it->next) { > if (cmplen == 0) { > - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); > + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); > } > else { > struct tree_desc tree; > @@ -2830,7 +2842,7 @@ static void add_tag_chain(const struct object_id *oid) > die(_("unable to pack objects reachable from tag %s"), > oid_to_hex(oid)); > > - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); > + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); > > if (tag->tagged->type != OBJ_TAG) > return; > @@ -2985,7 +2997,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) > pack_idx_opts.flags &= ~WRITE_REV; > return 0; > } > - if (!strcmp(k, "uploadpack.blobpackfileuri")) { > + if (!strcmp(k, "uploadpack.excludeobject") || !strcmp(k, "uploadpack.blobpackfileuri")) { > struct configured_exclusion *ex = xmalloc(sizeof(*ex)); > const char *oid_end, *pack_end; > /* > @@ -2998,11 +3010,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) > *oid_end != ' ' || > parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || > *pack_end != ' ') > - die(_("value of uploadpack.blobpackfileuri must be " > - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); > + die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " > + "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); > if (oidmap_get(&configured_exclusions, &ex->e.oid)) > - die(_("object already configured in another " > - "uploadpack.blobpackfileuri (got '%s')"), v); > + die(_("object already configured by an earlier " > + "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); > ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); > memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); > ex->uri = xstrdup(pack_end + 1); > @@ -3031,7 +3043,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, > return 0; > > ofs = nth_packed_object_offset(p, pos); > - if (!want_object_in_pack(oid, 0, &p, &ofs)) > + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) > return 0; > > oi.typep = &type; > @@ -3059,7 +3071,7 @@ static void show_commit_pack_hint(struct commit *commit, void *_data) > } > > static void show_object_pack_hint(struct object *object, const char *name, > - void *_data) > + void *show_data, void *carry_data) > { > struct object_entry *oe = packlist_find(&to_pack, &object->oid); > if (!oe) > @@ -3224,7 +3236,7 @@ static void read_object_list_from_stdin(void) > die(_("expected object ID, got garbage:\n %s"), line); > > add_preferred_base_object(p + 1); > - add_object_entry(&oid, OBJ_NONE, p + 1, 0); > + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); > } > } > > @@ -3233,7 +3245,7 @@ static void read_object_list_from_stdin(void) > > static void show_commit(struct commit *commit, void *data) > { > - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); > + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); > commit->object.flags |= OBJECT_ADDED; > > if (write_bitmap_index) > @@ -3243,10 +3255,11 @@ static void show_commit(struct commit *commit, void *data) > propagate_island_marks(commit); > } > > -static void show_object(struct object *obj, const char *name, void *data) > +static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) > { > + struct object *referred_commit = carry_data; > add_preferred_base_object(name); > - add_object_entry(&obj->oid, obj->type, name, 0); > + add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); > obj->flags |= OBJECT_ADDED; > > if (use_delta_islands) { > @@ -3265,7 +3278,7 @@ static void show_object(struct object *obj, const char *name, void *data) > } > } > > -static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) > +static void show_object__ma_allow_any(struct object *obj, const char *name, void *show_data, void *carry_data) > { > assert(arg_missing_action == MA_ALLOW_ANY); > > @@ -3276,10 +3289,10 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void > if (!has_object(the_repository, &obj->oid, 0)) > return; > > - show_object(obj, name, data); > + show_object(obj, name, show_data, carry_data); > } > > -static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) > +static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *show_data, void *carry_data) > { > assert(arg_missing_action == MA_ALLOW_PROMISOR); > > @@ -3290,7 +3303,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, > if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) > return; > > - show_object(obj, name, data); > + show_object(obj, name, show_data, carry_data); > } > > static int option_parse_missing_action(const struct option *opt, > @@ -3397,7 +3410,7 @@ static void add_objects_in_unpacked_packs(void) > QSORT(in_pack.array, in_pack.nr, ofscmp); > for (i = 0; i < in_pack.nr; i++) { > struct object *o = in_pack.array[i].object; > - add_object_entry(&o->oid, o->type, "", 0); > + add_object_entry(&o->oid, o->type, "", 0, NULL); > } > } > free(in_pack.array); > @@ -3413,7 +3426,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, > return 0; > } > > - add_object_entry(oid, type, "", 0); > + add_object_entry(oid, type, "", 0, NULL); > return 0; > } > > @@ -3538,7 +3551,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs) > > static void record_recent_object(struct object *obj, > const char *name, > - void *data) > + void *show_data, > + void *carry_data) > { > oid_array_append(&recent_objects, &obj->oid); > } > @@ -3831,7 +3845,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) > N_("respect islands during delta compression")), > OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, > N_("protocol"), > - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), > + N_("exclude any configured uploadpack.excludeobject or " > + "uploadpack.blobpackfileuri with this protocol")), > OPT_END(), > }; > > diff --git a/builtin/rev-list.c b/builtin/rev-list.c > index b4d8ea0a35..1cad33d9e8 100644 > --- a/builtin/rev-list.c > +++ b/builtin/rev-list.c > @@ -266,7 +266,7 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) > return 0; > } > > -static void show_object(struct object *obj, const char *name, void *cb_data) > +static void show_object(struct object *obj, const char *name, void *cb_data, void *carry_data) > { > struct rev_list_info *info = cb_data; > struct rev_info *revs = info->revs; > diff --git a/fetch-pack.c b/fetch-pack.c > index 2318ebe680..39bb449586 100644 > --- a/fetch-pack.c > +++ b/fetch-pack.c > @@ -23,6 +23,7 @@ > #include "fetch-negotiator.h" > #include "fsck.h" > #include "shallow.h" > +#include "strmap.h" > > static int transfer_unpack_limit = -1; > static int fetch_unpack_limit = -1; > @@ -1576,6 +1577,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > struct string_list packfile_uris = STRING_LIST_INIT_DUP; > int i; > struct strvec index_pack_args = STRVEC_INIT; > + struct strset uris; > > negotiator = &negotiator_alloc; > fetch_negotiator_init(r, negotiator); > @@ -1677,6 +1679,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > } > } > > + strset_init(&uris); > for (i = 0; i < packfile_uris.nr; i++) { > int j; > struct child_process cmd = CHILD_PROCESS_INIT; > @@ -1684,6 +1687,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > const char *uri = packfile_uris.items[i].string + > the_hash_algo->hexsz + 1; > > + if (!strset_add(&uris, uri)) > + continue; > strvec_push(&cmd.args, "http-fetch"); > strvec_pushf(&cmd.args, "--packfile=%.*s", > (int) the_hash_algo->hexsz, > @@ -1727,6 +1732,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, > get_object_directory(), > packname)); > } > + strset_clear(&uris); > string_list_clear(&packfile_uris, 0); > strvec_clear(&index_pack_args); > > diff --git a/list-objects.c b/list-objects.c > index e19589baa0..fa3156dc89 100644 > --- a/list-objects.c > +++ b/list-objects.c > @@ -24,7 +24,8 @@ struct traversal_context { > static void process_blob(struct traversal_context *ctx, > struct blob *blob, > struct strbuf *path, > - const char *name) > + const char *name, > + struct object *referred_commit) > { > struct object *obj = &blob->object; > size_t pathlen; > @@ -60,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, path->buf, ctx->show_data); > + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); > strbuf_setlen(path, pathlen); > } > > @@ -97,11 +98,13 @@ static void process_gitlink(struct traversal_context *ctx, > static void process_tree(struct traversal_context *ctx, > struct tree *tree, > struct strbuf *base, > - const char *name); > + const char *name, > + struct object *referred_commit); > > static void process_tree_contents(struct traversal_context *ctx, > struct tree *tree, > - struct strbuf *base) > + struct strbuf *base, > + struct object *referred_commit) > { > struct tree_desc desc; > struct name_entry entry; > @@ -129,7 +132,7 @@ static void process_tree_contents(struct traversal_context *ctx, > entry.path, oid_to_hex(&tree->object.oid)); > } > t->object.flags |= NOT_USER_GIVEN; > - process_tree(ctx, t, base, entry.path); > + process_tree(ctx, t, base, entry.path, referred_commit); > } > else if (S_ISGITLINK(entry.mode)) > process_gitlink(ctx, entry.oid.hash, > @@ -142,7 +145,7 @@ static void process_tree_contents(struct traversal_context *ctx, > entry.path, oid_to_hex(&tree->object.oid)); > } > b->object.flags |= NOT_USER_GIVEN; > - process_blob(ctx, b, base, entry.path); > + process_blob(ctx, b, base, entry.path, referred_commit); > } > } > } > @@ -150,7 +153,8 @@ static void process_tree_contents(struct traversal_context *ctx, > static void process_tree(struct traversal_context *ctx, > struct tree *tree, > struct strbuf *base, > - const char *name) > + const char *name, > + struct object *referred_commit) > { > struct object *obj = &tree->object; > struct rev_info *revs = ctx->revs; > @@ -191,14 +195,14 @@ static void process_tree(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, base->buf, ctx->show_data); > + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); > if (base->len) > strbuf_addch(base, '/'); > > if (r & LOFR_SKIP_TREE) > trace_printf("Skipping contents of tree %s...\n", base->buf); > else if (!failed_parse) > - process_tree_contents(ctx, tree, base); > + process_tree_contents(ctx, tree, base, referred_commit); > > r = list_objects_filter__filter_object(ctx->revs->repo, > LOFS_END_TREE, obj, > @@ -207,7 +211,7 @@ static void process_tree(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, base->buf, ctx->show_data); > + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); > > strbuf_setlen(base, baselen); > free_tree_buffer(tree); > @@ -314,9 +318,9 @@ void mark_edges_uninteresting(struct rev_info *revs, > } > } > > -static void add_pending_tree(struct rev_info *revs, struct tree *tree) > +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) > { > - add_pending_object(revs, &tree->object, ""); > + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); > } > > static void traverse_trees_and_blobs(struct traversal_context *ctx, > @@ -329,23 +333,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, > for (i = 0; i < ctx->revs->pending.nr; i++) { > struct object_array_entry *pending = ctx->revs->pending.objects + i; > struct object *obj = pending->item; > + struct object *referred_commit = pending->referred_commit; > const char *name = pending->name; > const char *path = pending->path; > if (obj->flags & (UNINTERESTING | SEEN)) > continue; > if (obj->type == OBJ_TAG) { > obj->flags |= SEEN; > - ctx->show_object(obj, name, ctx->show_data); > + ctx->show_object(obj, name, ctx->show_data, referred_commit); > continue; > } > if (!path) > path = ""; > if (obj->type == OBJ_TREE) { > - process_tree(ctx, (struct tree *)obj, base, path); > + process_tree(ctx, (struct tree *)obj, base, path, referred_commit); > continue; > } > if (obj->type == OBJ_BLOB) { > - process_blob(ctx, (struct blob *)obj, base, path); > + process_blob(ctx, (struct blob *)obj, base, path, referred_commit); > continue; > } > die("unknown pending object %s (%s)", > @@ -370,7 +375,7 @@ static void do_traverse(struct traversal_context *ctx) > else if (get_commit_tree(commit)) { > struct tree *tree = get_commit_tree(commit); > tree->object.flags |= NOT_USER_GIVEN; > - add_pending_tree(ctx->revs, tree); > + add_pending_tree(ctx->revs, tree, &commit->object); > } else if (commit->object.parsed) { > die(_("unable to load root tree for commit %s"), > oid_to_hex(&commit->object.oid)); > diff --git a/list-objects.h b/list-objects.h > index a952680e46..ab946d34db 100644 > --- a/list-objects.h > +++ b/list-objects.h > @@ -6,7 +6,7 @@ struct object; > struct rev_info; > > typedef void (*show_commit_fn)(struct commit *, void *); > -typedef void (*show_object_fn)(struct object *, const char *, void *); > +typedef void (*show_object_fn)(struct object *, const char *, void *, void *); > void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); > > typedef void (*show_edge_fn)(struct commit *); > diff --git a/object.c b/object.c > index 14188453c5..6b1ce2fcde 100644 > --- a/object.c > +++ b/object.c > @@ -322,9 +322,10 @@ void object_list_free(struct object_list **list) > */ > static char object_array_slopbuf[1]; > > -void add_object_array_with_path(struct object *obj, const char *name, > - struct object_array *array, > - unsigned mode, const char *path) > +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, > + struct object_array *array, > + unsigned mode, const char *path, > + struct object *referred_commit) > { > unsigned nr = array->nr; > unsigned alloc = array->alloc; > @@ -339,6 +340,7 @@ void add_object_array_with_path(struct object *obj, const char *name, > } > entry = &objects[nr]; > entry->item = obj; > + entry->referred_commit = referred_commit; > if (!name) > entry->name = NULL; > else if (!*name) > @@ -354,6 +356,13 @@ void add_object_array_with_path(struct object *obj, const char *name, > array->nr = ++nr; > } > > +void add_object_array_with_path(struct object *obj, const char *name, > + struct object_array *array, > + unsigned mode, const char *path) > +{ > + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); > +} > + > void add_object_array(struct object *obj, const char *name, struct object_array *array) > { > add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); > diff --git a/object.h b/object.h > index 87a6da47c8..de9f15b97d 100644 > --- a/object.h > +++ b/object.h > @@ -43,6 +43,7 @@ struct object_array { > unsigned int alloc; > struct object_array_entry { > struct object *item; > + struct object *referred_commit; > /* > * name or NULL. If non-NULL, the memory pointed to > * is owned by this object *except* if it points at > @@ -157,6 +158,9 @@ void object_list_free(struct object_list **list); > /* Object array handling .. */ > void add_object_array(struct object *obj, const char *name, struct object_array *array); > void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); > +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, > + unsigned mode, const char *path, > + struct object *referred_commit); > > /* > * Returns NULL if the array is empty. Otherwise, returns the last object > diff --git a/pack-bitmap.c b/pack-bitmap.c > index 3ed15431cd..516eb235da 100644 > --- a/pack-bitmap.c > +++ b/pack-bitmap.c > @@ -459,9 +459,9 @@ struct bitmap_show_data { > struct bitmap *base; > }; > > -static void show_object(struct object *object, const char *name, void *data_) > +static void show_object(struct object *object, const char *name, void *show_data, void *carry_data) > { > - struct bitmap_show_data *data = data_; > + struct bitmap_show_data *data = show_data; > int bitmap_pos; > > bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); > @@ -1268,9 +1268,9 @@ struct bitmap_test_data { > }; > > static void test_show_object(struct object *object, const char *name, > - void *data) > + void *show_data, void *carry_data) > { > - struct bitmap_test_data *tdata = data; > + struct bitmap_test_data *tdata = show_data; > int bitmap_pos; > > bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); > diff --git a/reachable.c b/reachable.c > index 77a60c70a5..ebd817c446 100644 > --- a/reachable.c > +++ b/reachable.c > @@ -47,14 +47,14 @@ static int add_one_ref(const char *path, const struct object_id *oid, > * The traversal will have already marked us as SEEN, so we > * only need to handle any progress reporting here. > */ > -static void mark_object(struct object *obj, const char *name, void *data) > +static void mark_object(struct object *obj, const char *name, void *show_data, void *carry_data) > { > - update_progress(data); > + update_progress(show_data); > } > > -static void mark_commit(struct commit *c, void *data) > +static void mark_commit(struct commit *c, void *show_data) > { > - mark_object(&c->object, NULL, data); > + mark_object(&c->object, NULL, show_data, NULL); > } > > struct recent_data { > diff --git a/revision.c b/revision.c > index 4853c85d0b..da0ce0e3f2 100644 > --- a/revision.c > +++ b/revision.c > @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) > commit_stack_clear(&pending); > } > > -static void add_pending_object_with_path(struct rev_info *revs, > - struct object *obj, > - const char *name, unsigned mode, > - const char *path) > +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, > + struct object *obj, > + const char *name, unsigned mode, > + const char *path, > + struct object *referred_commit) > { > struct interpret_branch_name_options options = { 0 }; > if (!obj) > @@ -326,20 +327,36 @@ static void add_pending_object_with_path(struct rev_info *revs, > strbuf_release(&buf); > return; /* do not add the commit itself */ > } > - add_object_array_with_path(obj, name, &revs->pending, mode, path); > + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); > +} > + > +static void add_pending_object_with_path(struct rev_info *revs, > + struct object *obj, > + const char *name, unsigned mode, > + const char *path) { > + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); > } > > static void add_pending_object_with_mode(struct rev_info *revs, > struct object *obj, > - const char *name, unsigned mode) > + const char *name, unsigned mode, > + struct object *referred_commit) > { > - add_pending_object_with_path(revs, obj, name, mode, NULL); > + > + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); > +} > + > +void add_pending_object_with_referred_commit(struct rev_info *revs, > + struct object *obj, const char *name, > + struct object *referred_commit) > +{ > + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); > } > > void add_pending_object(struct rev_info *revs, > struct object *obj, const char *name) > { > - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); > + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); > } > > void add_head_to_pending(struct rev_info *revs) > @@ -2764,7 +2781,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s > continue; > } > > - > if (handle_revision_arg(arg, revs, flags, revarg_opt)) { > int j; > if (seen_dashdash || *arg == '^') > @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s > if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) > diagnose_missing_default(revs->def); > object = get_reference(revs, revs->def, &oid, 0); > - add_pending_object_with_mode(revs, object, revs->def, oc.mode); > + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); > } > > /* Did the user ask for any diff output? Run the diff! */ > diff --git a/revision.h b/revision.h > index a24f72dcd1..8a632e3587 100644 > --- a/revision.h > +++ b/revision.h > @@ -424,6 +424,10 @@ void show_object_with_name(FILE *, struct object *, const char *); > void add_pending_object(struct rev_info *revs, > struct object *obj, const char *name); > > +void add_pending_object_with_referred_commit(struct rev_info *revs, > + struct object *obj, const char *name, > + struct object *referred_commit); > + > void add_pending_oid(struct rev_info *revs, > const char *name, const struct object_id *oid, > unsigned int flags); > diff --git a/upload-pack.c b/upload-pack.c > index 5c1cd19612..d26fb351a3 100644 > --- a/upload-pack.c > +++ b/upload-pack.c > @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, > strbuf_addstr(value, " packfile-uris"); > free(str); > } > + > + if (!repo_config_get_string(the_repository, > + "uploadpack.excludeobject", > + &str) && str) { > + strbuf_addstr(value, " packfile-uris"); > + free(str); > + } > } > > return 1; ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 1/3] packfile-uris: support for excluding commit objects 2021-07-26 18:15 ` Junio C Hamano @ 2021-07-26 19:45 ` Felipe Contreras 2021-08-11 1:44 ` Teng Long 1 sibling, 0 replies; 72+ messages in thread From: Felipe Contreras @ 2021-07-26 19:45 UTC (permalink / raw) To: Junio C Hamano, Teng Long; +Cc: git, jonathantanmy, avarab Junio C Hamano wrote: > Teng Long <dyroneteng@gmail.com> writes: > > > On the server, more sophisticated means of excluding objects should be > > supported, such as commit object. This commit introduces a new > > configuration `uploadpack.excludeobject` for this. > > Please avoid adjectives that express subjective values, like > "sophisticated". The word "sophisticated" is not necessarily subjective, it can easily mean "complex". https://www.merriam-webster.com/dictionary/sophisticated -- Felipe Contreras ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 1/3] packfile-uris: support for excluding commit objects 2021-07-26 18:15 ` Junio C Hamano 2021-07-26 19:45 ` Felipe Contreras @ 2021-08-11 1:44 ` Teng Long 1 sibling, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 1:44 UTC (permalink / raw) To: gitster; +Cc: avarab, dyroneteng, git, jonathantanmy >> Please avoid adjectives that express subjective values, like >> "sophisticated". Readers will expect a lot more sophistication than >> your code actually offers and will be disappointed ("wow, that would >> be wonderful if we can say 'exclude commits made by bots, and those >> older than 3 months'---eh, you cannot do that? where is your >> sophistication then?"). I use it("sophisticated") from "packfile-uri.txt", but i agree with you. Documentation will also remove/replace the subjective word in the next patch. >> Please avoid "should" without first describing the background for >> "why it should". It would help if you briefly describe what we >> currently have and its limitation before this first paragraph >> (i.e. your "we can already exclude only blob objects" would become >> major part of the explanation, but you'd need to present in what >> situations it would help to be able to exclude other types). Agree. Commit message will be appended with backgroud description. >> This commit is probalby doing too many things at once. For example, >> refactoring like creation of match_packfile_uri_exclusions() helper >> function out of existing code (there probably are others) can and >> should be done as separate preparatory steps before the API gets >> modified (e.g. process-object callbacks gain an e xtra parameter) in >> tree-wide way. >> >> And by slimming the primary step that introduces the new feature, >> there will be a space to also add documentation and test in the same >> step, which would help reviewers. With the current structure of the >> series, with a code dump in the first step with only a vague promiss >> of "sophistication" without documentation updates, reviewers cannot >> even tell how the "commit object" is used easily. Agree. The current commit will be splitted for more clear reponsibilities, documentation and tests ditto. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v3 2/3] t5702: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long 2021-07-26 9:46 ` [PATCH v3 1/3] packfile-uris: support for excluding commit objects Teng Long @ 2021-07-26 9:46 ` Teng Long 2021-07-26 15:03 ` Ævar Arnfjörð Bjarmason 2021-07-26 9:46 ` [PATCH v3 3/3] packfile-uri.txt: " Teng Long ` (2 subsequent siblings) 4 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-07-26 9:46 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 166 +++++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 33 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..bcf21e1445 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -753,7 +753,7 @@ test_expect_success 'ls-remote with v2 http sends only one POST' ' ' test_expect_success 'push with http:// and a config of v2 does not request v2' ' - test_when_finished "rm -f log" && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && # Till v2 for push is designed, make sure that if a client has # protocol.version configured to use v2, that the client instead falls # back and uses v0. @@ -776,7 +776,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' ' test_expect_success 'when server sends "ready", expect DELIM' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -796,7 +796,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' ' test_expect_success 'when server does not send "ready", expect FLUSH' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -824,17 +824,44 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + objt="$1" + P="$2" + version="$3" + + oldc="uploadpack.blobpackfileuri" + newc="uploadpack.excludeobject" + configkey="" + if test "$version" = "0" + then + configkey="$oldc" + else + configkey="$newc" + fi + + if test "$objt" = "blob" + then + git -C "$P" hash-object "$3" >objh && + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + elif test "$objt" = "commit" || test "$objt" = "tag" + then + echo "$3" >objh + git -C "$2" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "unsupported object type in configure_exclusion (got $objt)" + fi } test_expect_success 'part of packfile response provided as URI' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -843,10 +870,10 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob 0 >h && + configure_exclusion blob "$P" other-blob 0 >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -881,18 +908,40 @@ test_expect_success 'part of packfile response provided as URI' ' test_line_count = 6 filelist ' -test_expect_success 'packfile URIs with fetch instead of clone' ' +test_expect_success 'blobs packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && + + configure_exclusion blob "$P" my-blob >h && + + git init http_child && + + GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch "$HTTPD_URL/smart/http_parent" +' + +test_expect_success 'blobs packfile URIs(Compatible with the old) with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + # with the old "uploadpack.blobpackfileuri" configure + configure_exclusion blob "$P" my-blob 0 >h && git init http_child && @@ -902,9 +951,60 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' fetch "$HTTPD_URL/smart/http_parent" ' +test_expect_success 'commits packfile URIs with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + + mycommit=$(git -C "$P" rev-parse A) && + echo other-blob >"$P/other-blob" && + git -C "$P" add other-blob && + test_commit -C "$P" B && + othercommit=$(git -C "$P" rev-parse B) && + + configure_exclusion commit "$P" "$mycommit" >h2 && + configure_exclusion commit "$P" "$othercommit" >h2 && + + git init http_child && + + GIT_TRACE=1 GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch "$HTTPD_URL/smart/http_parent" +' + +test_expect_success 'tags packfile URIs with fetch instead of clone' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + git -C "$P" tag -a -m "annotated_tag" tagA && + tagObj=$(git -C "$P" rev-parse tagA) && + + configure_exclusion tag "$P" "$tagObj" >h2 && + + git init http_child && + + GIT_TRACE=1 GIT_TRACE_PACKET=1 GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch --tags "$HTTPD_URL/smart/http_parent" +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -913,9 +1013,9 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -923,7 +1023,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" hash-object other-blob >objh && git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && git -C "$P" config --add \ - "uploadpack.blobpackfileuri" \ + "uploadpack.excludeobject" \ "$(cat objh) $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && test_must_fail env GIT_TEST_SIDEBAND_ALL=1 \ @@ -933,18 +1033,18 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' test_i18ngrep "pack downloaded from.*does not match expected hash" err ' + test_expect_success 'packfile-uri with transfer.fsckobjects' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -959,7 +1059,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -976,9 +1076,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -989,7 +1089,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child && + test_when_finished "rm -rf \"$P\" http_child" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1000,7 +1100,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1015,7 +1115,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodules separate from tree is invalid' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child err && + test_when_finished "rm -rf \"$P\" http_child err" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1024,9 +1124,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul echo "path = include/foo" >>"$P/.gitmodules" && echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -- 2.31.1.443.g55c63af4c9.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v3 2/3] t5702: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 2/3] t5702: " Teng Long @ 2021-07-26 15:03 ` Ævar Arnfjörð Bjarmason 2021-08-11 1:46 ` [PATCH v3 1/3] packfile-uris: " Teng Long 0 siblings, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-07-26 15:03 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy On Mon, Jul 26 2021, Teng Long wrote: > Signed-off-by: Teng Long <dyroneteng@gmail.com> > --- > t/t5702-protocol-v2.sh | 166 +++++++++++++++++++++++++++++++++-------- > 1 file changed, 133 insertions(+), 33 deletions(-) > > diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh > index 2e1243ca40..bcf21e1445 100755 > --- a/t/t5702-protocol-v2.sh > +++ b/t/t5702-protocol-v2.sh > @@ -753,7 +753,7 @@ test_expect_success 'ls-remote with v2 http sends only one POST' ' > ' > > test_expect_success 'push with http:// and a config of v2 does not request v2' ' > - test_when_finished "rm -f log" && > + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && > # Till v2 for push is designed, make sure that if a client has > # protocol.version configured to use v2, that the client instead falls > # back and uses v0. > @@ -776,7 +776,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' > ' > > test_expect_success 'when server sends "ready", expect DELIM' ' > - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && > + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child" && > > git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && > @@ -796,7 +796,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' > ' > > test_expect_success 'when server does not send "ready", expect FLUSH' ' > - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && > + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && > > git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && > @@ -824,17 +824,44 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' > ' This looks like a good cleanup, but should be split into another cleanup commit. It looks unrelated. > configure_exclusion () { > - git -C "$1" hash-object "$2" >objh && > - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && > - git -C "$1" config --add \ > - "uploadpack.blobpackfileuri" \ > - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > - cat objh > + objt="$1" > + P="$2" > + version="$3" > + > + oldc="uploadpack.blobpackfileuri" > + newc="uploadpack.excludeobject" > + configkey="" > + if test "$version" = "0" > + then > + configkey="$oldc" > + else > + configkey="$newc" > + fi You've got all sorts of mixed space/tab indent here. > + if test "$objt" = "blob" > + then > + git -C "$P" hash-object "$3" >objh && > + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && > + git -C "$P" config --add \ > + "$configkey" \ > + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > + cat objh > + elif test "$objt" = "commit" || test "$objt" = "tag" > + then > + echo "$3" >objh > + git -C "$2" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh > + git -C "$P" config --add \ > + "$configkey" \ > + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && > + cat objh > + else > + echo "unsupported object type in configure_exclusion (got $objt)" > + fi > } > > test_expect_success 'part of packfile response provided as URI' ' > P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > - rm -rf "$P" http_child log && > + test_when_finished "rm -rf \"$P\" http_child log" && > > git init "$P" && > git -C "$P" config "uploadpack.allowsidebandall" "true" && > @@ -843,10 +870,10 @@ test_expect_success 'part of packfile response provided as URI' ' > git -C "$P" add my-blob && > echo other-blob >"$P/other-blob" && > git -C "$P" add other-blob && > - git -C "$P" commit -m x && > + test_commit -C "$P" A && > > - configure_exclusion "$P" my-blob >h && > - configure_exclusion "$P" other-blob >h2 && > + configure_exclusion blob "$P" my-blob 0 >h && > + configure_exclusion blob "$P" other-blob 0 >h2 && > > GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ > git -c protocol.version=2 \ > @@ -881,18 +908,40 @@ test_expect_success 'part of packfile response provided as URI' ' > test_line_count = 6 filelist > ' > > -test_expect_success 'packfile URIs with fetch instead of clone' ' > +test_expect_success 'blobs packfile URIs with fetch instead of clone' ' > P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && > - rm -rf "$P" http_child log && > + test_when_finished "rm -rf \"$P\" http_child log" && > > git init "$P" && > git -C "$P" config "uploadpack.allowsidebandall" "true" && > > echo my-blob >"$P/my-blob" && > git -C "$P" add my-blob && > - git -C "$P" commit -m x && > + test_commit -C "$P" A && > + > + configure_exclusion blob "$P" my-blob >h && > + > + git init http_child && > + > + GIT_TEST_SIDEBAND_ALL=1 \ > + git -C http_child -c protocol.version=2 \ > + -c fetch.uriprotocols=http,https \ Isn't accepting http and https the default? Is this guarding against config leak from a previous test? Ditto some later changes. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 1/3] packfile-uris: support for excluding commit objects 2021-07-26 15:03 ` Ævar Arnfjörð Bjarmason @ 2021-08-11 1:46 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 1:46 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, jonathantanmy >>This looks like a good cleanup, but should be split into another cleanup >>commit. It looks unrelated. Agree. Will split up in next patchset. >>You've got all sorts of mixed space/tab indent here. Yes. Will fix wrong indents in next patchset. >>Isn't accepting http and https the default? I think it's NOT after I took a view at function `fetch_pack_config`. This may be optimized in another patch I think and also will listen to some other suggestions. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v3 3/3] packfile-uri.txt: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long 2021-07-26 9:46 ` [PATCH v3 1/3] packfile-uris: support for excluding commit objects Teng Long 2021-07-26 9:46 ` [PATCH v3 2/3] t5702: " Teng Long @ 2021-07-26 9:46 ` Teng Long 2021-07-26 20:52 ` Junio C Hamano 2021-07-26 12:34 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Ævar Arnfjörð Bjarmason 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long 4 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-07-26 9:46 UTC (permalink / raw) To: git; +Cc: jonathantanmy, avarab, Teng Long Signed-off-by: Teng Long <dyroneteng@gmail.com> --- Documentation/technical/packfile-uri.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index f7eabc6c76..2532db0e99 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -35,13 +35,16 @@ include some sort of non-trivial implementation in the Minimum Viable Product, at least so that we can test the client. This is the implementation: a feature, marked experimental, that allows the -server to be configured by one or more `uploadpack.blobPackfileUri=<sha1> -<uri>` entries. Whenever the list of objects to be sent is assembled, all such -blobs are excluded, replaced with URIs. As noted in "Future work" below, the -server can evolve in the future to support excluding other objects (or other -implementations of servers could be made that support excluding other objects) -without needing a protocol change, so clients should not expect that packfiles -downloaded in this way only contain single blobs. +server to be configured by one or more entries with the format: + + uploadpack.excludeobject=<object-hash> <recursively> <pack-hash> <uri> + +Value <object-hash> is the key of entry, and the object type can be a blob +or commit. Whenever the list of objects to be sent is assembled, all such +objects are excluded, replaced with URIs. At the same time, for the old +configuration `uploadpack.blobPackfileUri=<sha1> <pack-hash> <uri>` is +still compatible for now, but this configuration only supports the +exclusion of blob objects. Client design ------------- @@ -65,9 +68,6 @@ The protocol design allows some evolution of the server and client without any need for protocol changes, so only a small-scoped design is included here to form the MVP. For example, the following can be done: - * On the server, more sophisticated means of excluding objects (e.g. by - specifying a commit to represent that commit and all objects that it - references). * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more -- 2.31.1.443.g55c63af4c9.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v3 3/3] packfile-uri.txt: support for excluding commit objects 2021-07-26 9:46 ` [PATCH v3 3/3] packfile-uri.txt: " Teng Long @ 2021-07-26 20:52 ` Junio C Hamano 2021-08-11 1:47 ` Teng Long 0 siblings, 1 reply; 72+ messages in thread From: Junio C Hamano @ 2021-07-26 20:52 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy, avarab Teng Long <dyroneteng@gmail.com> writes: > +++ b/Documentation/technical/packfile-uri.txt > @@ -35,13 +35,16 @@ include some sort of non-trivial implementation in the Minimum Viable Product, > at least so that we can test the client. > > This is the implementation: a feature, marked experimental, that allows the > +server to be configured by one or more entries with the format: > + > + uploadpack.excludeobject=<object-hash> <recursively> <pack-hash> <uri> > + > +Value <object-hash> is the key of entry, and the object type can be a blob > +or commit. Whenever the list of objects to be sent is assembled, all such > +objects are excluded, replaced with URIs. At the same time, for the old > +configuration `uploadpack.blobPackfileUri=<sha1> <pack-hash> <uri>` is > +still compatible for now, but this configuration only supports the > +exclusion of blob objects. Do not hint deprecation and future removal with "still" and "for now", before seeing a concensus that it should be deprecated and removed. The new thing, <recursively>, deserves some explanation. What are the acceptable values (yes/no? spatial/time/both? infinitely/limited?) and what do these values mean? Why is this limited to only <blob> and <commit>? There isn't a fundamental reason why I shouldn't be able to say "v2.32.0" instead of ebf3c04b262aa27fbb97f8a0156c2347fecafafb (or "v2.32.0~0") to say "I want anything reachable from v2.32.0 (in other words, that version and everything before it)", is there? For that matter, "everything reachable from this tree object" may also be a reasonable way to specify which set of objects are offloaded to an out-of-band URI. Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 3/3] packfile-uri.txt: support for excluding commit objects 2021-07-26 20:52 ` Junio C Hamano @ 2021-08-11 1:47 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 1:47 UTC (permalink / raw) To: gitster; +Cc: avarab, dyroneteng, git, jonathantanmy >>Do not hint deprecation and future removal with "still" and "for >>now", before seeing a concensus that it should be deprecated and >>removed. Agree. Will remove. >>The new thing, <recursively>, deserves some explanation. What are >>the acceptable values (yes/no? spatial/time/both? infinitely/limited?) >>and what do these values mean? More expanation. I think over about <recursively> and consider to remove it in next patch because offer a pack only contains commit or tree object individually may not make much sense, so <recursively> will remove(as default on tree and commit object) in next patch. >>Why is this limited to only <blob> and <commit>? Will support tree but not tag(maybe furture work) in next patch. >>There isn't a fundamental reason why I shouldn't be able to say >>"v2.32.0" instead of ebf3c04b262aa27fbb97f8a0156c2347fecafafb (or >>"v2.32.0~0") to say "I want anything reachable from v2.32.0 (in >>other words, that version and everything before it)", is there? >>For that matter, "everything reachable from this tree object" may >>also be a reasonable way to specify which set of objects are >>offloaded to an out-of-band URI. Agree. Will provide more detailed instuctions in next patch. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 0/3] packfile-uris: commit objects exclusio 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long ` (2 preceding siblings ...) 2021-07-26 9:46 ` [PATCH v3 3/3] packfile-uri.txt: " Teng Long @ 2021-07-26 12:34 ` Ævar Arnfjörð Bjarmason 2021-08-11 1:48 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long 4 siblings, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-07-26 12:34 UTC (permalink / raw) To: Teng Long; +Cc: git, jonathantanmy On Mon, Jul 26 2021, Teng Long wrote: > Range-diff against v2: > -: ---------- > 1: 91dce385f6 packfile-uris: support for excluding commit objects > -: ---------- > 2: 92def8c72b t5702: support for excluding commit objects > -: ---------- > 3: 01ab2cbb34 packfile-uri.txt: support for excluding commit objects It looks like you provided the wrong base for the --range-diff (likely master?), so it's not a diff against v2, just whatever you used as a base. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v3 0/3] packfile-uris: commit objects exclusio 2021-07-26 12:34 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Ævar Arnfjörð Bjarmason @ 2021-08-11 1:48 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 1:48 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, jonathantanmy >>It looks like you provided the wrong base for the --range-diff (likely >>master?), so it's not a diff against v2, just whatever you used as a >>base. Agree. Sorry about that, the first use made a mistake. Maybe corrected next time :) Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v4 0/7] packfile-uris: commits and trees exclusion 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long ` (3 preceding siblings ...) 2021-07-26 12:34 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Ævar Arnfjörð Bjarmason @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 1/7] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long ` (7 more replies) 4 siblings, 8 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Changes since v4: * Remove subjective words in commit message. * Add background descriptions in commit message. * Big commit split. * Fix `t/t5702-protocol-v2.sh` indent problems. * Test commit split(cleanup and new test case). * Remove hint deprecation words in documentation. * Support tree object exclusion. * Add details about recursive exclusion of commits and trees in documentation. Teng Long (7): pack-objects.c: introduce new method `match_packfile_uri_exclusions` Add new parameter "carry_data" for "show_object" function packfile-uri: support for excluding commit objects packfile-uri: support for excluding tree objects packfile-uri.txt: support for excluding commits and trees t5702: replace with "test_when_finished" for cleanup t5702: support for excluding commit objects Documentation/technical/packfile-uri.txt | 32 ++- builtin/describe.c | 4 +- builtin/pack-objects.c | 104 +++++--- builtin/rev-list.c | 2 +- list-objects.c | 41 +-- list-objects.h | 2 +- object.c | 19 +- object.h | 15 +- pack-bitmap.c | 8 +- reachable.c | 8 +- revision.c | 34 ++- revision.h | 3 + t/t5702-protocol-v2.sh | 312 ++++++++++++++++++++--- upload-pack.c | 7 + 14 files changed, 466 insertions(+), 125 deletions(-) Range-diff against v3: -: ---------- > 1: 73a5b4ccc1 pack-objects.c: introduce new method `match_packfile_uri_exclusions` -: ---------- > 2: bc8fea97e3 Add new parameter "carry_data" for "show_object" function 1: f324359ec8 ! 3: f71b310842 packfile-uris: support for excluding commit objects @@ Metadata Author: Teng Long <dyroneteng@gmail.com> ## Commit message ## - packfile-uris: support for excluding commit objects + packfile-uri: support for excluding commit objects - On the server, more sophisticated means of excluding objects should be - supported, such as commit object. This commit introduces a new - configuration `uploadpack.excludeobject` for this. + Currently packfile-uri supports the exclusion of blob objects, but in + some scenarios, users may wish to exclude more types of objects, such as + commit and tree objects, not only because packfile itself supports + storing these object types, but also on the other hand, to make + configuration items maintainable and simpler. + + This commit is used to support the recursive exclusion of a commit + object, which means that if the exclusion of a commit is configured as + packfile-uri, the commit itself and all the objects it contains will + also be recursively excluded. In addition, to support this feature, a + new configuration `uploadpack.excludeobject` is introduced. The reason for bringing a new configuration is for two considerations. First, the old configuration supports a single object type (blob), which @@ Commit message Signed-off-by: Teng Long <dyroneteng@gmail.com> - ## builtin/describe.c ## -@@ builtin/describe.c: static void process_commit(struct commit *commit, void *data) - pcd->current_commit = commit->object.oid; - } - --static void process_object(struct object *obj, const char *path, void *data) -+static void process_object(struct object *obj, const char *path, void *show_data, void *carry_data) - { -- struct process_commit_data *pcd = data; -+ struct process_commit_data *pcd = show_data; - - if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { - reset_revision_walk(); - ## builtin/pack-objects.c ## -@@ builtin/pack-objects.c: static int have_duplicate_entry(const struct object_id *oid, - return 1; - } - -+static int match_packfile_uri_exclusions(struct configured_exclusion *ex) -+{ -+ int i; -+ const char *p; -+ -+ if (ex) { -+ for (i = 0; i < uri_protocols.nr; i++) { -+ if (skip_prefix(ex->uri, -+ uri_protocols.items[i].string, -+ &p) && -+ *p == ':') -+ return 1; -+ -+ } -+ } -+ return 0; -+} -+ - static int want_found_object(const struct object_id *oid, int exclude, - struct packed_git *p) - { @@ builtin/pack-objects.c: static int want_object_in_pack_one(struct packed_git *p, static int want_object_in_pack(const struct object_id *oid, int exclude, @@ builtin/pack-objects.c: static int want_object_in_pack_one(struct packed_git *p, struct multi_pack_index *m; + struct configured_exclusion *ex; + struct configured_exclusion *referred_ex; -+ if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ builtin/pack-objects.c: static int want_object_in_pack(const struct object_id *o if (uri_protocols.nr) { - struct configured_exclusion *ex = - oidmap_get(&configured_exclusions, oid); -- int i; -- const char *p; -- -- if (ex) { -- for (i = 0; i < uri_protocols.nr; i++) { -- if (skip_prefix(ex->uri, -- uri_protocols.items[i].string, -- &p) && -- *p == ':') { -- oidset_insert(&excluded_by_config, oid); -- return 0; -- } -- } + if (referred_commit) { + referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); + if (referred_ex && match_packfile_uri_exclusions(referred_ex)) + return 0; + } -+ ex = oidmap_get(&configured_exclusions, oid); -+ if (ex && match_packfile_uri_exclusions(ex)) { -+ oidset_insert(&excluded_by_config, oid); -+ return 0; - } - } ++ ex = oidmap_get(&configured_exclusions, oid); + if (ex && match_packfile_uri_exclusions(ex)) { + oidset_insert(&excluded_by_config, oid); + return 0; @@ builtin/pack-objects.c: static const char no_closure_warning[] = N_( ); @@ builtin/pack-objects.c: static int git_pack_config(const char *k, const char *v, parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " -- "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); -+ die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " -+ "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); ++ die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " + "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) - die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); -+ die(_("object already configured by an earlier " -+ "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); ++ die(_("object already configured by an earlier " ++ "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); @@ builtin/pack-objects.c: static int add_object_entry_from_pack(const struct objec return 0; oi.typep = &type; -@@ builtin/pack-objects.c: static void show_commit_pack_hint(struct commit *commit, void *_data) - } - - static void show_object_pack_hint(struct object *object, const char *name, -- void *_data) -+ void *show_data, void *carry_data) - { - struct object_entry *oe = packlist_find(&to_pack, &object->oid); - if (!oe) @@ builtin/pack-objects.c: static void read_object_list_from_stdin(void) die(_("expected object ID, got garbage:\n %s"), line); @@ builtin/pack-objects.c: static void read_object_list_from_stdin(void) if (write_bitmap_index) @@ builtin/pack-objects.c: static void show_commit(struct commit *commit, void *data) - propagate_island_marks(commit); - } --static void show_object(struct object *obj, const char *name, void *data) -+static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) + static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { + struct object *referred_commit = carry_data; add_preferred_base_object(name); @@ builtin/pack-objects.c: static void show_commit(struct commit *commit, void *dat obj->flags |= OBJECT_ADDED; if (use_delta_islands) { -@@ builtin/pack-objects.c: static void show_object(struct object *obj, const char *name, void *data) - } - } - --static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) -+static void show_object__ma_allow_any(struct object *obj, const char *name, void *show_data, void *carry_data) - { - assert(arg_missing_action == MA_ALLOW_ANY); - -@@ builtin/pack-objects.c: static void show_object__ma_allow_any(struct object *obj, const char *name, void - if (!has_object(the_repository, &obj->oid, 0)) - return; - -- show_object(obj, name, data); -+ show_object(obj, name, show_data, carry_data); - } - --static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) -+static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *show_data, void *carry_data) - { - assert(arg_missing_action == MA_ALLOW_PROMISOR); - -@@ builtin/pack-objects.c: static void show_object__ma_allow_promisor(struct object *obj, const char *name, - if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) - return; - -- show_object(obj, name, data); -+ show_object(obj, name, show_data, carry_data); - } - - static int option_parse_missing_action(const struct option *opt, @@ builtin/pack-objects.c: static void add_objects_in_unpacked_packs(void) QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { @@ builtin/pack-objects.c: static int add_loose_object(const struct object_id *oid, return 0; } -@@ builtin/pack-objects.c: static int get_object_list_from_bitmap(struct rev_info *revs) - - static void record_recent_object(struct object *obj, - const char *name, -- void *data) -+ void *show_data, -+ void *carry_data) - { - oid_array_append(&recent_objects, &obj->oid); - } @@ builtin/pack-objects.c: int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject or " -+ "uploadpack.blobpackfileuri with this protocol")), ++ "uploadpack.blobpackfileuri with this protocol")), OPT_END(), }; - ## builtin/rev-list.c ## -@@ builtin/rev-list.c: static int finish_object(struct object *obj, const char *name, void *cb_data) - return 0; - } - --static void show_object(struct object *obj, const char *name, void *cb_data) -+static void show_object(struct object *obj, const char *name, void *cb_data, void *carry_data) - { - struct rev_list_info *info = cb_data; - struct rev_info *revs = info->revs; - - ## fetch-pack.c ## -@@ - #include "fetch-negotiator.h" - #include "fsck.h" - #include "shallow.h" -+#include "strmap.h" - - static int transfer_unpack_limit = -1; - static int fetch_unpack_limit = -1; -@@ fetch-pack.c: static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, - struct string_list packfile_uris = STRING_LIST_INIT_DUP; - int i; - struct strvec index_pack_args = STRVEC_INIT; -+ struct strset uris; - - negotiator = &negotiator_alloc; - fetch_negotiator_init(r, negotiator); -@@ fetch-pack.c: static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, - } - } - -+ strset_init(&uris); - for (i = 0; i < packfile_uris.nr; i++) { - int j; - struct child_process cmd = CHILD_PROCESS_INIT; -@@ fetch-pack.c: static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, - const char *uri = packfile_uris.items[i].string + - the_hash_algo->hexsz + 1; - -+ if (!strset_add(&uris, uri)) -+ continue; - strvec_push(&cmd.args, "http-fetch"); - strvec_pushf(&cmd.args, "--packfile=%.*s", - (int) the_hash_algo->hexsz, -@@ fetch-pack.c: static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, - get_object_directory(), - packname)); - } -+ strset_clear(&uris); - string_list_clear(&packfile_uris, 0); - strvec_clear(&index_pack_args); - - ## list-objects.c ## @@ list-objects.c: struct traversal_context { static void process_blob(struct traversal_context *ctx, @@ list-objects.c: static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) -- ctx->show_object(obj, path->buf, ctx->show_data); +- ctx->show_object(obj, path->buf, ctx->show_data, NULL); + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); strbuf_setlen(path, pathlen); } @@ list-objects.c: static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) -- ctx->show_object(obj, base->buf, ctx->show_data); +- ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); if (base->len) strbuf_addch(base, '/'); @@ list-objects.c: static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) -- ctx->show_object(obj, base->buf, ctx->show_data); +- ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); strbuf_setlen(base, baselen); @@ list-objects.c: void mark_edges_uninteresting(struct rev_info *revs, } -static void add_pending_tree(struct rev_info *revs, struct tree *tree) -+static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) ++static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) { - add_pending_object(revs, &tree->object, ""); + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); @@ list-objects.c: static void traverse_trees_and_blobs(struct traversal_context *c continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; -- ctx->show_object(obj, name, ctx->show_data); +- ctx->show_object(obj, name, ctx->show_data, NULL); + ctx->show_object(obj, name, ctx->show_data, referred_commit); continue; } @@ list-objects.c: static void do_traverse(struct traversal_context *ctx) die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); - ## list-objects.h ## -@@ list-objects.h: struct object; - struct rev_info; - - typedef void (*show_commit_fn)(struct commit *, void *); --typedef void (*show_object_fn)(struct object *, const char *, void *); -+typedef void (*show_object_fn)(struct object *, const char *, void *, void *); - void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); - - typedef void (*show_edge_fn)(struct commit *); - ## object.c ## @@ object.c: void object_list_free(struct object_list **list) */ @@ object.c: void add_object_array_with_path(struct object *obj, const char *name, ## object.h ## @@ object.h: struct object_array { - unsigned int alloc; - struct object_array_entry { - struct object *item; + char *name; + char *path; + unsigned mode; + struct object *referred_commit; - /* - * name or NULL. If non-NULL, the memory pointed to - * is owned by this object *except* if it points at + } *objects; + }; + @@ object.h: void object_list_free(struct object_list **list); /* Object array handling .. */ void add_object_array(struct object *obj, const char *name, struct object_array *array); void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); +- +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, -+ unsigned mode, const char *path, -+ struct object *referred_commit); - ++ unsigned mode, const char *path, struct object *referred_commit); /* * Returns NULL if the array is empty. Otherwise, returns the last object - - ## pack-bitmap.c ## -@@ pack-bitmap.c: struct bitmap_show_data { - struct bitmap *base; - }; - --static void show_object(struct object *object, const char *name, void *data_) -+static void show_object(struct object *object, const char *name, void *show_data, void *carry_data) - { -- struct bitmap_show_data *data = data_; -+ struct bitmap_show_data *data = show_data; - int bitmap_pos; - - bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); -@@ pack-bitmap.c: struct bitmap_test_data { - }; - - static void test_show_object(struct object *object, const char *name, -- void *data) -+ void *show_data, void *carry_data) - { -- struct bitmap_test_data *tdata = data; -+ struct bitmap_test_data *tdata = show_data; - int bitmap_pos; - - bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); - - ## reachable.c ## -@@ reachable.c: static int add_one_ref(const char *path, const struct object_id *oid, - * The traversal will have already marked us as SEEN, so we - * only need to handle any progress reporting here. - */ --static void mark_object(struct object *obj, const char *name, void *data) -+static void mark_object(struct object *obj, const char *name, void *show_data, void *carry_data) - { -- update_progress(data); -+ update_progress(show_data); - } - --static void mark_commit(struct commit *c, void *data) -+static void mark_commit(struct commit *c, void *show_data) - { -- mark_object(&c->object, NULL, data); -+ mark_object(&c->object, NULL, show_data, NULL); - } - - struct recent_data { + * after removing its entry from the array. Other resources associated ## revision.c ## @@ revision.c: void mark_parents_uninteresting(struct commit *commit) @@ revision.c: static void add_pending_object_with_path(struct rev_info *revs, } - add_object_array_with_path(obj, name, &revs->pending, mode, path); + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); -+} -+ + } + +static void add_pending_object_with_path(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, -+ const char *path) { ++ const char *path) ++{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); - } - ++} static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, - const char *name, unsigned mode) + const char *name, unsigned mode, + struct object *referred_commit) - { -- add_pending_object_with_path(revs, obj, name, mode, NULL); -+ ++{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); +} + +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit) -+{ + { +- add_pending_object_with_path(revs, obj, name, mode, NULL); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); } @@ revision.c: static void add_pending_object_with_path(struct rev_info *revs, } void add_head_to_pending(struct rev_info *revs) -@@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s - continue; - } - -- - if (handle_revision_arg(arg, revs, flags, revarg_opt)) { - int j; - if (seen_dashdash || *arg == '^') @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) diagnose_missing_default(revs->def); @@ revision.c: int setup_revisions(int argc, const char **argv, struct rev_info *re ## revision.h ## @@ revision.h: void show_object_with_name(FILE *, struct object *, const char *); + */ void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); - +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit); -+ + void add_pending_oid(struct rev_info *revs, const char *name, const struct object_id *oid, - unsigned int flags); ## upload-pack.c ## @@ upload-pack.c: int upload_pack_advertise(struct repository *r, 2: 7ce99a0f31 < -: ---------- t5702: support for excluding commit objects -: ---------- > 4: bbb0413cc4 packfile-uri: support for excluding tree objects 3: 36b9a92132 ! 5: 8e5bf4010c packfile-uri.txt: support for excluding commit objects @@ Metadata Author: Teng Long <dyroneteng@gmail.com> ## Commit message ## - packfile-uri.txt: support for excluding commit objects + packfile-uri.txt: support for excluding commits and trees Signed-off-by: Teng Long <dyroneteng@gmail.com> @@ Documentation/technical/packfile-uri.txt: include some sort of non-trivial imple -downloaded in this way only contain single blobs. +server to be configured by one or more entries with the format: + -+ uploadpack.excludeobject=<object-hash> <recursively> <pack-hash> <uri> ++ uploadpack.excludeobject=<object-hash> <pack-hash> <uri> + -+Value <object-hash> is the key of entry, and the object type can be a blob -+or commit. Whenever the list of objects to be sent is assembled, all such -+objects are excluded, replaced with URIs. At the same time, for the old -+configuration `uploadpack.blobPackfileUri=<sha1> <pack-hash> <uri>` is -+still compatible for now, but this configuration only supports the -+exclusion of blob objects. ++Value <object-hash> is the key of entry, and the object type can be a blob, ++tree, or commit. The exclusion of tree and commit is recursive by default, ++which means that when a tree or commit object is excluded, the object itself ++and all reachable objects of the object will be excluded recursively. Whenever ++the list of objects to be sent is assembled, all such objects are excluded, ++replaced with URIs. ++ ++Configuration compatibility ++------------- ++ ++The old configuration of packfile-uri: ++ ++ `uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri>` ++ ++For the old configuration is compatible with the new one, but it only ++supports the exclusion of blob objects. Client design ------------- @@ Documentation/technical/packfile-uri.txt: The protocol design allows some evolut * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more +@@ Documentation/technical/packfile-uri.txt: There are some possible features that will require a change in protocol: + + * Additional HTTP headers (e.g. authentication) + * Byte range support +- * Different file formats referenced by URIs (e.g. raw object) ++ * Different file formats referenced by URIs (e.g. raw object) + \ No newline at end of file -: ---------- > 6: f3b1cba7e1 t5702: replace with "test_when_finished" for cleanup -: ---------- > 7: 3b5f9732b8 t5702: support for excluding commit objects -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v4 1/7] pack-objects.c: introduce new method `match_packfile_uri_exclusions` 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 2/7] Add new parameter "carry_data" for "show_object" function Teng Long ` (6 subsequent siblings) 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..31556e7396 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1188,6 +1188,24 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int match_packfile_uri_exclusions(struct configured_exclusion *ex) +{ + int i; + const char *p; + + if (ex) { + for (i = 0; i < uri_protocols.nr; i++) { + if (skip_prefix(ex->uri, + uri_protocols.items[i].string, + &p) && + *p == ':') + return 1; + + } + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1335,19 +1353,10 @@ static int want_object_in_pack(const struct object_id *oid, if (uri_protocols.nr) { struct configured_exclusion *ex = oidmap_get(&configured_exclusions, oid); - int i; - const char *p; - if (ex) { - for (i = 0; i < uri_protocols.nr; i++) { - if (skip_prefix(ex->uri, - uri_protocols.items[i].string, - &p) && - *p == ':') { - oidset_insert(&excluded_by_config, oid); - return 0; - } - } + if (ex && match_packfile_uri_exclusions(ex)) { + oidset_insert(&excluded_by_config, oid); + return 0; } } -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v4 2/7] Add new parameter "carry_data" for "show_object" function 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long 2021-08-11 7:45 ` [PATCH v4 1/7] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 3/7] packfile-uri: support for excluding commit objects Teng Long ` (5 subsequent siblings) 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy During the pack-objects process, "show_object" function will be called to find the object and show the process("show_object_fn" in "list-object.h"), the function definition contains three parameters: 1. struct object *obj(contains object type, flags, and oid). 2. const char *name(the object name). 3. void *show_data(function to show progress info). This commit adds a new parameter: "void *carry_data", the reason is mainly based on scalability and performance considerations when showing an object, space for time, avoid costly temporary calculations in the "show" phase. For example, carry the ownership relationship between blob or tree object and the referred commit to avoid redundant and expensive calculations. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/describe.c | 4 ++-- builtin/pack-objects.c | 15 ++++++++------- builtin/rev-list.c | 2 +- list-objects.c | 8 ++++---- list-objects.h | 2 +- pack-bitmap.c | 8 ++++---- reachable.c | 8 ++++---- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 40482d8e9f..045da79b5c 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -485,9 +485,9 @@ static void process_commit(struct commit *commit, void *data) pcd->current_commit = commit->object.oid; } -static void process_object(struct object *obj, const char *path, void *data) +static void process_object(struct object *obj, const char *path, void *show_data, void *carry_data) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = show_data; if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { reset_revision_walk(); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 31556e7396..5f9ec3566f 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3068,7 +3068,7 @@ static void show_commit_pack_hint(struct commit *commit, void *_data) } static void show_object_pack_hint(struct object *object, const char *name, - void *_data) + void *show_data, void *carry_dataa) { struct object_entry *oe = packlist_find(&to_pack, &object->oid); if (!oe) @@ -3252,7 +3252,7 @@ static void show_commit(struct commit *commit, void *data) propagate_island_marks(commit); } -static void show_object(struct object *obj, const char *name, void *data) +static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { add_preferred_base_object(name); add_object_entry(&obj->oid, obj->type, name, 0); @@ -3274,7 +3274,7 @@ static void show_object(struct object *obj, const char *name, void *data) } } -static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_any(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_ANY); @@ -3285,10 +3285,10 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void if (!has_object(the_repository, &obj->oid, 0)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } -static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_PROMISOR); @@ -3299,7 +3299,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } static int option_parse_missing_action(const struct option *opt, @@ -3547,7 +3547,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs) static void record_recent_object(struct object *obj, const char *name, - void *data) + void *show_data, + void *carry_data) { oid_array_append(&recent_objects, &obj->oid); } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index b4d8ea0a35..1cad33d9e8 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -266,7 +266,7 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) return 0; } -static void show_object(struct object *obj, const char *name, void *cb_data) +static void show_object(struct object *obj, const char *name, void *cb_data, void *carry_data) { struct rev_list_info *info = cb_data; struct rev_info *revs = info->revs; diff --git a/list-objects.c b/list-objects.c index e19589baa0..427228a3ba 100644 --- a/list-objects.c +++ b/list-objects.c @@ -60,7 +60,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data); + ctx->show_object(obj, path->buf, ctx->show_data, NULL); strbuf_setlen(path, pathlen); } @@ -191,7 +191,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, NULL); if (base->len) strbuf_addch(base, '/'); @@ -207,7 +207,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, NULL); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -335,7 +335,7 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data); + ctx->show_object(obj, name, ctx->show_data, NULL); continue; } if (!path) diff --git a/list-objects.h b/list-objects.h index a952680e46..ab946d34db 100644 --- a/list-objects.h +++ b/list-objects.h @@ -6,7 +6,7 @@ struct object; struct rev_info; typedef void (*show_commit_fn)(struct commit *, void *); -typedef void (*show_object_fn)(struct object *, const char *, void *); +typedef void (*show_object_fn)(struct object *, const char *, void *, void *); void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); typedef void (*show_edge_fn)(struct commit *); diff --git a/pack-bitmap.c b/pack-bitmap.c index 3ed15431cd..516eb235da 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -459,9 +459,9 @@ struct bitmap_show_data { struct bitmap *base; }; -static void show_object(struct object *object, const char *name, void *data_) +static void show_object(struct object *object, const char *name, void *show_data, void *carry_data) { - struct bitmap_show_data *data = data_; + struct bitmap_show_data *data = show_data; int bitmap_pos; bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); @@ -1268,9 +1268,9 @@ struct bitmap_test_data { }; static void test_show_object(struct object *object, const char *name, - void *data) + void *show_data, void *carry_data) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); diff --git a/reachable.c b/reachable.c index 77a60c70a5..521b39edef 100644 --- a/reachable.c +++ b/reachable.c @@ -47,14 +47,14 @@ static int add_one_ref(const char *path, const struct object_id *oid, * The traversal will have already marked us as SEEN, so we * only need to handle any progress reporting here. */ -static void mark_object(struct object *obj, const char *name, void *data) +static void mark_object(struct object *obj, const char *name, void *show_data, void *carry_data) { - update_progress(data); + update_progress(show_data); } -static void mark_commit(struct commit *c, void *data) +static void mark_commit(struct commit *c, void *show_data) { - mark_object(&c->object, NULL, data); + mark_object(&c->object, NULL, show_data, NULL); } struct recent_data { -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v4 3/7] packfile-uri: support for excluding commit objects 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long 2021-08-11 7:45 ` [PATCH v4 1/7] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long 2021-08-11 7:45 ` [PATCH v4 2/7] Add new parameter "carry_data" for "show_object" function Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 4/7] packfile-uri: support for excluding tree objects Teng Long ` (4 subsequent siblings) 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Currently packfile-uri supports the exclusion of blob objects, but in some scenarios, users may wish to exclude more types of objects, such as commit and tree objects, not only because packfile itself supports storing these object types, but also on the other hand, to make configuration items maintainable and simpler. This commit is used to support the recursive exclusion of a commit object, which means that if the exclusion of a commit is configured as packfile-uri, the commit itself and all the objects it contains will also be recursively excluded. In addition, to support this feature, a new configuration `uploadpack.excludeobject` is introduced. The reason for bringing a new configuration is for two considerations. First, the old configuration supports a single object type (blob), which limits the use of this feature. Secondly, the name of the old configuration is not abstract enough, this make extension difficult. If different object types use different configuration names, the configuration items will be bloated and difficult to maintain, so the new configuration is more abstract in name and easy to extend. Although a new configuration has been introduced, the old one is still available and compatible with the new configuration. The old configuration `uploadpack.blobpackfileuri` only supports excluding blobs. The new configuration `uploadpack.excludeobject` not only supports excluding blob objects, but also supports excluding commit objects, as well as recursively excluding tree objects and blob objects they contain. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 50 +++++++++++++++++++++++++----------------- list-objects.c | 37 +++++++++++++++++-------------- object.c | 15 ++++++++++--- object.h | 4 +++- revision.c | 34 ++++++++++++++++++++-------- revision.h | 3 +++ upload-pack.c | 7 ++++++ 7 files changed, 101 insertions(+), 49 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 5f9ec3566f..63f3aed70a 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1311,11 +1311,14 @@ static int want_object_in_pack_one(struct packed_git *p, static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + struct object *referred_commit) { int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *ex; + struct configured_exclusion *referred_ex; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1351,9 +1354,13 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - struct configured_exclusion *ex = - oidmap_get(&configured_exclusions, oid); + if (referred_commit) { + referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); + if (referred_ex && match_packfile_uri_exclusions(referred_ex)) + return 0; + } + ex = oidmap_get(&configured_exclusions, oid); if (ex && match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; @@ -1393,7 +1400,8 @@ static const char no_closure_warning[] = N_( ); static int add_object_entry(const struct object_id *oid, enum object_type type, - const char *name, int exclude) + const char *name, int exclude, + struct object *referred_commit) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1403,7 +1411,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1429,7 +1437,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, if (have_duplicate_entry(oid, 0)) return 0; - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) return 0; create_object_entry(oid, type, name_hash, 0, 0, pack, offset); @@ -1569,7 +1577,7 @@ static void add_pbase_object(struct tree_desc *tree, if (name[cmplen] != '/') { add_object_entry(&entry.oid, object_type(entry.mode), - fullname, 1); + fullname, 1, NULL); return; } if (S_ISDIR(entry.mode)) { @@ -1637,7 +1645,7 @@ static void add_preferred_base_object(const char *name) cmplen = name_cmp_len(name); for (it = pbase_tree; it; it = it->next) { if (cmplen == 0) { - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); } else { struct tree_desc tree; @@ -2839,7 +2847,7 @@ static void add_tag_chain(const struct object_id *oid) die(_("unable to pack objects reachable from tag %s"), oid_to_hex(oid)); - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); if (tag->tagged->type != OBJ_TAG) return; @@ -2994,7 +3002,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.flags &= ~WRITE_REV; return 0; } - if (!strcmp(k, "uploadpack.blobpackfileuri")) { + if (!strcmp(k, "uploadpack.excludeobject") || !strcmp(k, "uploadpack.blobpackfileuri")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); const char *oid_end, *pack_end; /* @@ -3007,11 +3015,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) *oid_end != ' ' || parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " + die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) - die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); + die(_("object already configured by an earlier " + "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); @@ -3040,7 +3048,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; ofs = nth_packed_object_offset(p, pos); - if (!want_object_in_pack(oid, 0, &p, &ofs)) + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) return 0; oi.typep = &type; @@ -3233,7 +3241,7 @@ static void read_object_list_from_stdin(void) die(_("expected object ID, got garbage:\n %s"), line); add_preferred_base_object(p + 1); - add_object_entry(&oid, OBJ_NONE, p + 1, 0); + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); } } @@ -3242,7 +3250,7 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, void *data) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) @@ -3254,8 +3262,9 @@ static void show_commit(struct commit *commit, void *data) static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { + struct object *referred_commit = carry_data; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0); + add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { @@ -3406,7 +3415,7 @@ static void add_objects_in_unpacked_packs(void) QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; - add_object_entry(&o->oid, o->type, "", 0); + add_object_entry(&o->oid, o->type, "", 0, NULL); } } free(in_pack.array); @@ -3422,7 +3431,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, return 0; } - add_object_entry(oid, type, "", 0); + add_object_entry(oid, type, "", 0, NULL); return 0; } @@ -3841,7 +3850,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject or " + "uploadpack.blobpackfileuri with this protocol")), OPT_END(), }; diff --git a/list-objects.c b/list-objects.c index 427228a3ba..968d842ceb 100644 --- a/list-objects.c +++ b/list-objects.c @@ -24,7 +24,8 @@ struct traversal_context { static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &blob->object; size_t pathlen; @@ -60,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data, NULL); + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); strbuf_setlen(path, pathlen); } @@ -97,11 +98,13 @@ static void process_gitlink(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name); + const char *name, + struct object *referred_commit); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, - struct strbuf *base) + struct strbuf *base, + struct object *referred_commit) { struct tree_desc desc; struct name_entry entry; @@ -129,7 +132,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path); + process_tree(ctx, t, base, entry.path, referred_commit); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -142,7 +145,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path); + process_blob(ctx, b, base, entry.path, referred_commit); } } } @@ -150,7 +153,8 @@ static void process_tree_contents(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -191,14 +195,14 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); if (base->len) strbuf_addch(base, '/'); if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base); + process_tree_contents(ctx, tree, base, referred_commit); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -207,7 +211,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -314,9 +318,9 @@ void mark_edges_uninteresting(struct rev_info *revs, } } -static void add_pending_tree(struct rev_info *revs, struct tree *tree) +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) { - add_pending_object(revs, &tree->object, ""); + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); } static void traverse_trees_and_blobs(struct traversal_context *ctx, @@ -329,23 +333,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; + struct object *referred_commit = pending->referred_commit; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data, NULL); + ctx->show_object(obj, name, ctx->show_data, referred_commit); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path); + process_tree(ctx, (struct tree *)obj, base, path, referred_commit); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path); + process_blob(ctx, (struct blob *)obj, base, path, referred_commit); continue; } die("unknown pending object %s (%s)", @@ -370,7 +375,7 @@ static void do_traverse(struct traversal_context *ctx) else if (get_commit_tree(commit)) { struct tree *tree = get_commit_tree(commit); tree->object.flags |= NOT_USER_GIVEN; - add_pending_tree(ctx->revs, tree); + add_pending_tree(ctx->revs, tree, &commit->object); } else if (commit->object.parsed) { die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); diff --git a/object.c b/object.c index 14188453c5..6b1ce2fcde 100644 --- a/object.c +++ b/object.c @@ -322,9 +322,10 @@ void object_list_free(struct object_list **list) */ static char object_array_slopbuf[1]; -void add_object_array_with_path(struct object *obj, const char *name, - struct object_array *array, - unsigned mode, const char *path) +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path, + struct object *referred_commit) { unsigned nr = array->nr; unsigned alloc = array->alloc; @@ -339,6 +340,7 @@ void add_object_array_with_path(struct object *obj, const char *name, } entry = &objects[nr]; entry->item = obj; + entry->referred_commit = referred_commit; if (!name) entry->name = NULL; else if (!*name) @@ -354,6 +356,13 @@ void add_object_array_with_path(struct object *obj, const char *name, array->nr = ++nr; } +void add_object_array_with_path(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path) +{ + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); +} + void add_object_array(struct object *obj, const char *name, struct object_array *array) { add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); diff --git a/object.h b/object.h index 87a6da47c8..d63819ab91 100644 --- a/object.h +++ b/object.h @@ -52,6 +52,7 @@ struct object_array { char *name; char *path; unsigned mode; + struct object *referred_commit; } *objects; }; @@ -157,7 +158,8 @@ void object_list_free(struct object_list **list); /* Object array handling .. */ void add_object_array(struct object *obj, const char *name, struct object_array *array); void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); - +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, + unsigned mode, const char *path, struct object *referred_commit); /* * Returns NULL if the array is empty. Otherwise, returns the last object * after removing its entry from the array. Other resources associated diff --git a/revision.c b/revision.c index 4853c85d0b..65e0926d25 100644 --- a/revision.c +++ b/revision.c @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) commit_stack_clear(&pending); } -static void add_pending_object_with_path(struct rev_info *revs, - struct object *obj, - const char *name, unsigned mode, - const char *path) +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path, + struct object *referred_commit) { struct interpret_branch_name_options options = { 0 }; if (!obj) @@ -326,20 +327,35 @@ static void add_pending_object_with_path(struct rev_info *revs, strbuf_release(&buf); return; /* do not add the commit itself */ } - add_object_array_with_path(obj, name, &revs->pending, mode, path); + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); } +static void add_pending_object_with_path(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); +} static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, - const char *name, unsigned mode) + const char *name, unsigned mode, + struct object *referred_commit) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); +} + +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit) { - add_pending_object_with_path(revs, obj, name, mode, NULL); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); } void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); } void add_head_to_pending(struct rev_info *revs) @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) diagnose_missing_default(revs->def); object = get_reference(revs, revs->def, &oid, 0); - add_pending_object_with_mode(revs, object, revs->def, oc.mode); + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); } /* Did the user ask for any diff output? Run the diff! */ diff --git a/revision.h b/revision.h index a24f72dcd1..f9c9628ed8 100644 --- a/revision.h +++ b/revision.h @@ -423,6 +423,9 @@ void show_object_with_name(FILE *, struct object *, const char *); */ void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit); void add_pending_oid(struct rev_info *revs, const char *name, const struct object_id *oid, diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..d26fb351a3 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, strbuf_addstr(value, " packfile-uris"); free(str); } + + if (!repo_config_get_string(the_repository, + "uploadpack.excludeobject", + &str) && str) { + strbuf_addstr(value, " packfile-uris"); + free(str); + } } return 1; -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v4 4/7] packfile-uri: support for excluding tree objects 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long ` (2 preceding siblings ...) 2021-08-11 7:45 ` [PATCH v4 3/7] packfile-uri: support for excluding commit objects Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees Teng Long ` (3 subsequent siblings) 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy This commit supports the use of `uploadpack.excludeobject` to exclude tree objects, which means that when a type object is configured as packfile-uri, the tree object itself and all objects contains will be recursively excluded. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 30 ++++++++++++++++++++---------- list-objects.c | 32 ++++++++++++++++++-------------- object.c | 6 +++++- object.h | 13 ++++++++++++- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 63f3aed70a..4ff12ec525 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1312,13 +1312,14 @@ static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, off_t *found_offset, - struct object *referred_commit) + struct referred_objects *referred_objs) { int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *commit_ex; + struct configured_exclusion *tree_ex; struct configured_exclusion *ex; - struct configured_exclusion *referred_ex; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1354,14 +1355,23 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - if (referred_commit) { - referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); - if (referred_ex && match_packfile_uri_exclusions(referred_ex)) + if (referred_objs && referred_objs->commit) { + commit_ex = oidmap_get(&configured_exclusions, &referred_objs->commit->oid); + if (match_packfile_uri_exclusions(commit_ex)) return 0; } + if (referred_objs && referred_objs->trees) { + struct object_list *p; + for (p = referred_objs->trees; p; p = p->next) { + tree_ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(tree_ex)) + return 0; + } + } + ex = oidmap_get(&configured_exclusions, oid); - if (ex && match_packfile_uri_exclusions(ex)) { + if (match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; } @@ -1401,7 +1411,7 @@ static const char no_closure_warning[] = N_( static int add_object_entry(const struct object_id *oid, enum object_type type, const char *name, int exclude, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1411,7 +1421,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_objs)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -3262,9 +3272,9 @@ static void show_commit(struct commit *commit, void *data) static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { - struct object *referred_commit = carry_data; + struct referred_objects *referred_objs = carry_data; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); + add_object_entry(&obj->oid, obj->type, name, 0, referred_objs); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { diff --git a/list-objects.c b/list-objects.c index 968d842ceb..49f177cb56 100644 --- a/list-objects.c +++ b/list-objects.c @@ -25,7 +25,7 @@ static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, const char *name, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct object *obj = &blob->object; size_t pathlen; @@ -61,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, path->buf, ctx->show_data, referred_objs); strbuf_setlen(path, pathlen); } @@ -99,19 +99,22 @@ static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, const char *name, - struct object *referred_commit); + struct referred_objects *referred_objs); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct tree_desc desc; struct name_entry entry; enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ? all_entries_interesting : entry_not_interesting; + struct referred_objects *referred_buf; init_tree_desc(&desc, tree->buffer, tree->size); + referred_buf = xmemdupz(referred_objs, sizeof(struct referred_objects)); + object_list_insert(&tree->object, &referred_buf->trees); while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { @@ -132,7 +135,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path, referred_commit); + process_tree(ctx, t, base, entry.path, referred_buf); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -145,16 +148,17 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path, referred_commit); + process_blob(ctx, b, base, entry.path, referred_buf); } } + free(referred_buf); } static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, const char *name, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -195,14 +199,14 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, base->buf, ctx->show_data, referred_objs); if (base->len) strbuf_addch(base, '/'); if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base, referred_commit); + process_tree_contents(ctx, tree, base, referred_objs); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -211,7 +215,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, base->buf, ctx->show_data, referred_objs); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -333,24 +337,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; - struct object *referred_commit = pending->referred_commit; + struct referred_objects *referred_objs = pending->referred_objects; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data, referred_commit); + ctx->show_object(obj, name, ctx->show_data, referred_objs); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path, referred_commit); + process_tree(ctx, (struct tree *)obj, base, path, referred_objs); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path, referred_commit); + process_blob(ctx, (struct blob *)obj, base, path, referred_objs); continue; } die("unknown pending object %s (%s)", diff --git a/object.c b/object.c index 6b1ce2fcde..69ba0baf95 100644 --- a/object.c +++ b/object.c @@ -331,6 +331,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch unsigned alloc = array->alloc; struct object_array_entry *objects = array->objects; struct object_array_entry *entry; + struct referred_objects *referred_objs = xmalloc(sizeof(struct referred_objects)); if (nr >= alloc) { alloc = (alloc + 32) * 2; @@ -338,9 +339,11 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch array->alloc = alloc; array->objects = objects; } + referred_objs->commit = referred_commit; + referred_objs->trees = NULL; entry = &objects[nr]; entry->item = obj; - entry->referred_commit = referred_commit; + entry->referred_objects = referred_objs; if (!name) entry->name = NULL; else if (!*name) @@ -377,6 +380,7 @@ static void object_array_release_entry(struct object_array_entry *ent) if (ent->name != object_array_slopbuf) free(ent->name); free(ent->path); + free(ent->referred_objects); } struct object *object_array_pop(struct object_array *array) diff --git a/object.h b/object.h index d63819ab91..3785546adf 100644 --- a/object.h +++ b/object.h @@ -52,12 +52,23 @@ struct object_array { char *name; char *path; unsigned mode; - struct object *referred_commit; + /* + * referred_objects or NULL. If non-NULL, it will + * temporary storage the referred commit and trees when + * traversing the specified object. Space for time, + * reduce related computing costs (such as packfile-uri + * exclusion), clean up when the traversal is over. + */ + struct referred_objects *referred_objects; } *objects; }; #define OBJECT_ARRAY_INIT { 0, 0, NULL } +struct referred_objects{ + struct object *commit; + struct object_list *trees; +}; /* * object flag allocation: * revision.h: 0---------10 15 23------26 -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long ` (3 preceding siblings ...) 2021-08-11 7:45 ` [PATCH v4 4/7] packfile-uri: support for excluding tree objects Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 9:59 ` Bagas Sanjaya 2021-08-11 7:45 ` [PATCH v4 6/7] t5702: replace with "test_when_finished" for cleanup Teng Long ` (2 subsequent siblings) 7 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- Documentation/technical/packfile-uri.txt | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index f7eabc6c76..c3e4873956 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -35,13 +35,26 @@ include some sort of non-trivial implementation in the Minimum Viable Product, at least so that we can test the client. This is the implementation: a feature, marked experimental, that allows the -server to be configured by one or more `uploadpack.blobPackfileUri=<sha1> -<uri>` entries. Whenever the list of objects to be sent is assembled, all such -blobs are excluded, replaced with URIs. As noted in "Future work" below, the -server can evolve in the future to support excluding other objects (or other -implementations of servers could be made that support excluding other objects) -without needing a protocol change, so clients should not expect that packfiles -downloaded in this way only contain single blobs. +server to be configured by one or more entries with the format: + + uploadpack.excludeobject=<object-hash> <pack-hash> <uri> + +Value <object-hash> is the key of entry, and the object type can be a blob, +tree, or commit. The exclusion of tree and commit is recursive by default, +which means that when a tree or commit object is excluded, the object itself +and all reachable objects of the object will be excluded recursively. Whenever +the list of objects to be sent is assembled, all such objects are excluded, +replaced with URIs. + +Configuration compatibility +------------- + +The old configuration of packfile-uri: + + `uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri>` + +For the old configuration is compatible with the new one, but it only +supports the exclusion of blob objects. Client design ------------- @@ -65,9 +78,6 @@ The protocol design allows some evolution of the server and client without any need for protocol changes, so only a small-scoped design is included here to form the MVP. For example, the following can be done: - * On the server, more sophisticated means of excluding objects (e.g. by - specifying a commit to represent that commit and all objects that it - references). * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more @@ -78,4 +88,4 @@ There are some possible features that will require a change in protocol: * Additional HTTP headers (e.g. authentication) * Byte range support - * Different file formats referenced by URIs (e.g. raw object) + * Different file formats referenced by URIs (e.g. raw object) \ No newline at end of file -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees 2021-08-11 7:45 ` [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees Teng Long @ 2021-08-11 9:59 ` Bagas Sanjaya 0 siblings, 0 replies; 72+ messages in thread From: Bagas Sanjaya @ 2021-08-11 9:59 UTC (permalink / raw) To: Teng Long; +Cc: avarab, git, jonathantanmy On 11/08/21 14.45, Teng Long wrote: > +The old configuration of packfile-uri: > + > + `uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri>` > + > +For the old configuration is compatible with the new one, but it only > +supports the exclusion of blob objects. I think better say "The old configuration of packfile-uri ... is compatible with the new one, but it only supports exclusion of blobs". -- An old man doll... just what I always wanted! - Clara ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v4 6/7] t5702: replace with "test_when_finished" for cleanup 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long ` (4 preceding siblings ...) 2021-08-11 7:45 ` [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 7/7] t5702: support for excluding commit objects Teng Long 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..e6314b53b0 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -753,7 +753,7 @@ test_expect_success 'ls-remote with v2 http sends only one POST' ' ' test_expect_success 'push with http:// and a config of v2 does not request v2' ' - test_when_finished "rm -f log" && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && # Till v2 for push is designed, make sure that if a client has # protocol.version configured to use v2, that the client instead falls # back and uses v0. @@ -776,7 +776,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' ' test_expect_success 'when server sends "ready", expect DELIM' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -796,7 +796,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' ' test_expect_success 'when server does not send "ready", expect FLUSH' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -834,7 +834,7 @@ configure_exclusion () { test_expect_success 'part of packfile response provided as URI' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -883,7 +883,7 @@ test_expect_success 'part of packfile response provided as URI' ' test_expect_success 'packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -904,7 +904,7 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -935,7 +935,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' test_expect_success 'packfile-uri with transfer.fsckobjects' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -959,7 +959,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -989,7 +989,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child && + test_when_finished "rm -rf \"$P\" http_child" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1015,7 +1015,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodules separate from tree is invalid' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child err && + test_when_finished "rm -rf \"$P\" http_child err" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1038,4 +1038,4 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul # DO NOT add non-httpd-specific tests here, because the last part of this # test script is only executed when httpd is available and enabled. -test_done +test_done \ No newline at end of file -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v4 7/7] t5702: support for excluding commit objects 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long ` (5 preceding siblings ...) 2021-08-11 7:45 ` [PATCH v4 6/7] t5702: replace with "test_when_finished" for cleanup Teng Long @ 2021-08-11 7:45 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long 7 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-11 7:45 UTC (permalink / raw) To: dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 292 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 266 insertions(+), 26 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e6314b53b0..5ad52e0cee 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -824,17 +824,47 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + objt="$1" + P="$2" + oid="$3" + version="$4" + + oldc="uploadpack.blobpackfileuri" + newc="uploadpack.excludeobject" + configkey="" + + if test "$version" = "old" + then + configkey="$oldc" + else + configkey="$newc" + fi + + if test "$objt" = "blob" + then + git -C "$P" hash-object "$oid" >objh && + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + elif test "$objt" = "commit" || test "$objt" = "tree" || test "$objt" = "tag" + then + echo "$oid" >objh + git -C "$P" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "unsupported object type in configure_exclusion (got $objt)" + fi } -test_expect_success 'part of packfile response provided as URI' ' +part_of_packfile_response_verify() { + config="$1" P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - test_when_finished "rm -rf \"$P\" http_child log" && + test_when_finished "rm -rf \"$P\" http_child log *found" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -843,10 +873,10 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob config >h && + configure_exclusion blob "$P" other-blob config >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -879,9 +909,11 @@ test_expect_success 'part of packfile response provided as URI' ' ls http_child/.git/objects/pack/*.pack \ http_child/.git/objects/pack/*.idx >filelist && test_line_count = 6 filelist -' +} + +blobpackfileuri_fetch () { + config="$1" -test_expect_success 'packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_when_finished "rm -rf \"$P\" http_child log" && @@ -890,9 +922,9 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob $config >h && git init http_child && @@ -900,6 +932,215 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' git -C http_child -c protocol.version=2 \ -c fetch.uriprotocols=http,https \ fetch "$HTTPD_URL/smart/http_parent" +} + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): part of packfile response provided as URI' ' + part_of_packfile_response_verify old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): part of packfile response provided as URI' ' + part_of_packfile_response_verify new +' + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch new +' + +test_expect_success 'tree-exclusion: part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + # Dir struct + # . + # |-- A.t + # |-- my-tree + # | `-- my-blob + # `-- other-tree + # |-- other-blob + # `-- sub-tree + # `-- sub-blob + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + mkdir "$P"/other-tree/sub-tree && + echo sub-blob >"$P"/other-tree/sub-tree/sub-blob && + git -C "$P" add other-tree && + test_commit -C "$P" A && + + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree HEAD other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD other-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + subblobh=$(git -C "$P" hash-object other-tree/sub-tree/sub-blob) && + + configure_exclusion tree "$P" "$mytreeh" config >h && + configure_exclusion tree "$P" "$othertreeh" config >h2 && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 3 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi + elif test_line_count = 2 out.objectlist + then + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + elif test_line_count = 4 out.objectlist + then + if grep $othertreeh out + then + >othertreehfound + fi && + if grep $otherblobh out + then + >otherblobhfound + fi + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f othertreehfound && + test -f otherblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 6 filelist +' + +test_expect_success 'commit-exclusion: part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/my-tree/sub-tree && + echo sub-blob >"$P"/my-tree/sub-tree/sub-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD my-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + subblobh=$(git -C "$P" hash-object my-tree/sub-tree/sub-blob) && + + configure_exclusion commit "$P" "$commith" >h && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 7 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi && + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + + # Ensure that there are exactly 2 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist ' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' @@ -913,9 +1154,9 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -923,7 +1164,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" hash-object other-blob >objh && git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && git -C "$P" config --add \ - "uploadpack.blobpackfileuri" \ + "uploadpack.excludeobject" \ "$(cat objh) $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && test_must_fail env GIT_TEST_SIDEBAND_ALL=1 \ @@ -942,9 +1183,8 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -976,9 +1216,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1000,7 +1240,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1024,9 +1264,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul echo "path = include/foo" >>"$P/.gitmodules" && echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -- 2.31.1.449.gb2aa5456a8.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long ` (6 preceding siblings ...) 2021-08-11 7:45 ` [PATCH v4 7/7] t5702: support for excluding commit objects Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 01/14] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long ` (14 more replies) 7 siblings, 15 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Changes since v5: * Support tag objects exclusion (configurable but will repeat download object data in previous patch) * Tests and docs modification for tag exclusion feature * Abstraction of some reusable methods Teng Long (14): pack-objects.c: introduce new method `match_packfile_uri_exclusions` Add new parameter "carry_data" for "show_object" function packfile-uri: support for excluding commit objects packfile-uri: support for excluding tree objects packfile-uri.txt: support for excluding commits and trees t5702: replace with "test_when_finished" for cleanup t5702: support for excluding commit objects Add new parameter "carry_data" for "show_commit function commit.h: add wrapped tags in commit struct object.h: add referred tags in `referred_objects` struct packfile-uri: support for excluding tag objects packfile-uri.txt: support for excluding tag objects t5702: add tag exclusion test case pack-objects.c: introduce `want_exclude_object` function Documentation/technical/packfile-uri.txt | 38 ++- builtin/describe.c | 8 +- builtin/pack-objects.c | 128 ++++++--- builtin/rev-list.c | 6 +- bundle.c | 4 +- commit.h | 5 + list-objects.c | 50 ++-- list-objects.h | 4 +- object.c | 20 +- object.h | 16 +- pack-bitmap.c | 14 +- reachable.c | 8 +- revision.c | 42 ++- revision.h | 3 + shallow.c | 4 +- t/t5702-protocol-v2.sh | 330 ++++++++++++++++++++--- upload-pack.c | 7 + 17 files changed, 542 insertions(+), 145 deletions(-) Range-diff against v4: -: ---------- > 1: 73a5b4ccc1 pack-objects.c: introduce new method `match_packfile_uri_exclusions` -: ---------- > 2: bc8fea97e3 Add new parameter "carry_data" for "show_object" function -: ---------- > 3: f71b310842 packfile-uri: support for excluding commit objects -: ---------- > 4: bbb0413cc4 packfile-uri: support for excluding tree objects -: ---------- > 5: 8e5bf4010c packfile-uri.txt: support for excluding commits and trees -: ---------- > 6: f3b1cba7e1 t5702: replace with "test_when_finished" for cleanup -: ---------- > 7: 3b5f9732b8 t5702: support for excluding commit objects 1: 19f7670384 = 8: 19f7670384 Add new parameter "carry_data" for "show_commit function 2: 011e5eaea3 = 9: 011e5eaea3 commit.h: add wrapped tags in commit struct 3: 824844499f = 10: 824844499f object.h: add referred tags in `referred_objects` struct 4: 43aa811b65 = 11: 43aa811b65 packfile-uri: support for excluding tag objects 5: c83db0055c = 12: c83db0055c packfile-uri.txt: support for excluding tag objects 6: 29a52b7a0d = 13: 29a52b7a0d t5702: add tag exclusion test case 7: 1a7c4c5894 = 14: 1a7c4c5894 pack-objects.c: introduce `want_exclude_object` function -- 2.31.1.456.gec51e24953 ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 01/14] pack-objects.c: introduce new method `match_packfile_uri_exclusions` 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function Teng Long ` (13 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..31556e7396 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1188,6 +1188,24 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int match_packfile_uri_exclusions(struct configured_exclusion *ex) +{ + int i; + const char *p; + + if (ex) { + for (i = 0; i < uri_protocols.nr; i++) { + if (skip_prefix(ex->uri, + uri_protocols.items[i].string, + &p) && + *p == ':') + return 1; + + } + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1335,19 +1353,10 @@ static int want_object_in_pack(const struct object_id *oid, if (uri_protocols.nr) { struct configured_exclusion *ex = oidmap_get(&configured_exclusions, oid); - int i; - const char *p; - if (ex) { - for (i = 0; i < uri_protocols.nr; i++) { - if (skip_prefix(ex->uri, - uri_protocols.items[i].string, - &p) && - *p == ':') { - oidset_insert(&excluded_by_config, oid); - return 0; - } - } + if (ex && match_packfile_uri_exclusions(ex)) { + oidset_insert(&excluded_by_config, oid); + return 0; } } -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long 2021-08-25 2:21 ` [PATCH v5 01/14] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-26 20:45 ` Junio C Hamano 2021-08-25 2:21 ` [PATCH v5 03/14] packfile-uri: support for excluding commit objects Teng Long ` (12 subsequent siblings) 14 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy During the pack-objects process, "show_object" function will be called to find the object and show the process("show_object_fn" in "list-object.h"), the function definition contains three parameters: 1. struct object *obj(contains object type, flags, and oid). 2. const char *name(the object name). 3. void *show_data(function to show progress info). This commit adds a new parameter: "void *carry_data", the reason is mainly based on scalability and performance considerations when showing an object, space for time, avoid costly temporary calculations in the "show" phase. For example, carry the ownership relationship between blob or tree object and the referred commit to avoid redundant and expensive calculations. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/describe.c | 4 ++-- builtin/pack-objects.c | 15 ++++++++------- builtin/rev-list.c | 2 +- list-objects.c | 8 ++++---- list-objects.h | 2 +- pack-bitmap.c | 8 ++++---- reachable.c | 8 ++++---- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 40482d8e9f..045da79b5c 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -485,9 +485,9 @@ static void process_commit(struct commit *commit, void *data) pcd->current_commit = commit->object.oid; } -static void process_object(struct object *obj, const char *path, void *data) +static void process_object(struct object *obj, const char *path, void *show_data, void *carry_data) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = show_data; if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { reset_revision_walk(); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 31556e7396..5f9ec3566f 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3068,7 +3068,7 @@ static void show_commit_pack_hint(struct commit *commit, void *_data) } static void show_object_pack_hint(struct object *object, const char *name, - void *_data) + void *show_data, void *carry_dataa) { struct object_entry *oe = packlist_find(&to_pack, &object->oid); if (!oe) @@ -3252,7 +3252,7 @@ static void show_commit(struct commit *commit, void *data) propagate_island_marks(commit); } -static void show_object(struct object *obj, const char *name, void *data) +static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { add_preferred_base_object(name); add_object_entry(&obj->oid, obj->type, name, 0); @@ -3274,7 +3274,7 @@ static void show_object(struct object *obj, const char *name, void *data) } } -static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_any(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_ANY); @@ -3285,10 +3285,10 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void if (!has_object(the_repository, &obj->oid, 0)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } -static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *show_data, void *carry_data) { assert(arg_missing_action == MA_ALLOW_PROMISOR); @@ -3299,7 +3299,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) return; - show_object(obj, name, data); + show_object(obj, name, show_data, carry_data); } static int option_parse_missing_action(const struct option *opt, @@ -3547,7 +3547,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs) static void record_recent_object(struct object *obj, const char *name, - void *data) + void *show_data, + void *carry_data) { oid_array_append(&recent_objects, &obj->oid); } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index b4d8ea0a35..1cad33d9e8 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -266,7 +266,7 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) return 0; } -static void show_object(struct object *obj, const char *name, void *cb_data) +static void show_object(struct object *obj, const char *name, void *cb_data, void *carry_data) { struct rev_list_info *info = cb_data; struct rev_info *revs = info->revs; diff --git a/list-objects.c b/list-objects.c index e19589baa0..427228a3ba 100644 --- a/list-objects.c +++ b/list-objects.c @@ -60,7 +60,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data); + ctx->show_object(obj, path->buf, ctx->show_data, NULL); strbuf_setlen(path, pathlen); } @@ -191,7 +191,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, NULL); if (base->len) strbuf_addch(base, '/'); @@ -207,7 +207,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, ctx->show_data, NULL); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -335,7 +335,7 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data); + ctx->show_object(obj, name, ctx->show_data, NULL); continue; } if (!path) diff --git a/list-objects.h b/list-objects.h index a952680e46..ab946d34db 100644 --- a/list-objects.h +++ b/list-objects.h @@ -6,7 +6,7 @@ struct object; struct rev_info; typedef void (*show_commit_fn)(struct commit *, void *); -typedef void (*show_object_fn)(struct object *, const char *, void *); +typedef void (*show_object_fn)(struct object *, const char *, void *, void *); void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); typedef void (*show_edge_fn)(struct commit *); diff --git a/pack-bitmap.c b/pack-bitmap.c index 3ed15431cd..516eb235da 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -459,9 +459,9 @@ struct bitmap_show_data { struct bitmap *base; }; -static void show_object(struct object *object, const char *name, void *data_) +static void show_object(struct object *object, const char *name, void *show_data, void *carry_data) { - struct bitmap_show_data *data = data_; + struct bitmap_show_data *data = show_data; int bitmap_pos; bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); @@ -1268,9 +1268,9 @@ struct bitmap_test_data { }; static void test_show_object(struct object *object, const char *name, - void *data) + void *show_data, void *carry_data) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); diff --git a/reachable.c b/reachable.c index 77a60c70a5..521b39edef 100644 --- a/reachable.c +++ b/reachable.c @@ -47,14 +47,14 @@ static int add_one_ref(const char *path, const struct object_id *oid, * The traversal will have already marked us as SEEN, so we * only need to handle any progress reporting here. */ -static void mark_object(struct object *obj, const char *name, void *data) +static void mark_object(struct object *obj, const char *name, void *show_data, void *carry_data) { - update_progress(data); + update_progress(show_data); } -static void mark_commit(struct commit *c, void *data) +static void mark_commit(struct commit *c, void *show_data) { - mark_object(&c->object, NULL, data); + mark_object(&c->object, NULL, show_data, NULL); } struct recent_data { -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function 2021-08-25 2:21 ` [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function Teng Long @ 2021-08-26 20:45 ` Junio C Hamano 2021-09-02 11:08 ` Teng Long 0 siblings, 1 reply; 72+ messages in thread From: Junio C Hamano @ 2021-08-26 20:45 UTC (permalink / raw) To: Teng Long; +Cc: avarab, git, jonathantanmy Teng Long <dyroneteng@gmail.com> writes: > Subject: Re: [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function Since this lacks <area>: prefix, "git shortlog" readers will have a hard time guessing which show_object() function this commit is about. > During the pack-objects process, "show_object" function will be called > to find the object and show the process("show_object_fn" in > "list-object.h"), the function definition contains three parameters: > > 1. struct object *obj(contains object type, flags, and oid). > 2. const char *name(the object name). > 3. void *show_data(function to show progress info). > > This commit adds a new parameter: "void *carry_data", the reason is > mainly based on scalability and performance considerations when showing > an object, space for time, avoid costly temporary calculations in the > "show" phase. For example, carry the ownership relationship between > blob or tree object and the referred commit to avoid redundant and > expensive calculations. The above explains what we want to carry around extra data for (i.e. compute something in one place, and use it later somewhere else) But it does not quite explain why we need another parameter to do so, which involves changing the function signature of many functions, instead of making show_data to point at a new structure type that holds the original data show_data used to carry plus another single void * member (or the set of members you'd be carrying into these functions using this new parameter). I also find "carry_data" a meaningless name for the parameter. All in-parameters into functions are used to carry some data into it after all. The existing "show_data" at least makes a bit more sense; it contains data necessary for showing the object in these code paths. If the purpose this new thing was introduced is to cache ownership relationship data, perhaps ownership_cache would be a more descriptive and understandable name (be it a new parameter to added to many functions, or a member to the new structure that replaces show_data). Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function 2021-08-26 20:45 ` Junio C Hamano @ 2021-09-02 11:08 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 11:08 UTC (permalink / raw) To: gitster; +Cc: avarab, dyroneteng, git, jonathantanmy > Since this lacks <area>: prefix, "git shortlog" readers will have a > hard time guessing which show_object() function this commit is > about. Sorry for the late reply. Agree, it will be fixed in next patch. > But it does not quite explain why we need another parameter to do > so, which involves changing the function signature of many > functions, instead of making show_data to point at a new structure > type that holds the original data show_data used to carry plus > another single void * member (or the set of members you'd be > carrying into these functions using this new parameter). > > I also find "carry_data" a meaningless name for the parameter. All > in-parameters into functions are used to carry some data into it > after all. The existing "show_data" at least makes a bit more > sense; it contains data necessary for showing the object in these > code paths. If the purpose this new thing was introduced is to > cache ownership relationship data, perhaps ownership_cache would be > a more descriptive and understandable name (be it a new parameter to > added to many functions, or a member to the new structure that > replaces show_data). Agree. I think "show_data to point at a new structure" is a better idea. I will follow the idea and optimize the related code. By the way, the naming about "ownership_cache" will be introduced in the next patch too, unless I can find a better one t(-_-t). Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 03/14] packfile-uri: support for excluding commit objects 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long 2021-08-25 2:21 ` [PATCH v5 01/14] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long 2021-08-25 2:21 ` [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 23:49 ` Ævar Arnfjörð Bjarmason 2021-08-26 20:56 ` Junio C Hamano 2021-08-25 2:21 ` [PATCH v5 04/14] packfile-uri: support for excluding tree objects Teng Long ` (11 subsequent siblings) 14 siblings, 2 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Currently packfile-uri supports the exclusion of blob objects, but in some scenarios, users may wish to exclude more types of objects, such as commit and tree objects, not only because packfile itself supports storing these object types, but also on the other hand, to make configuration items maintainable and simpler. This commit is used to support the recursive exclusion of a commit object, which means that if the exclusion of a commit is configured as packfile-uri, the commit itself and all the objects it contains will also be recursively excluded. In addition, to support this feature, a new configuration `uploadpack.excludeobject` is introduced. The reason for bringing a new configuration is for two considerations. First, the old configuration supports a single object type (blob), which limits the use of this feature. Secondly, the name of the old configuration is not abstract enough, this make extension difficult. If different object types use different configuration names, the configuration items will be bloated and difficult to maintain, so the new configuration is more abstract in name and easy to extend. Although a new configuration has been introduced, the old one is still available and compatible with the new configuration. The old configuration `uploadpack.blobpackfileuri` only supports excluding blobs. The new configuration `uploadpack.excludeobject` not only supports excluding blob objects, but also supports excluding commit objects, as well as recursively excluding tree objects and blob objects they contain. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 50 +++++++++++++++++++++++++----------------- list-objects.c | 37 +++++++++++++++++-------------- object.c | 15 ++++++++++--- object.h | 4 +++- revision.c | 34 ++++++++++++++++++++-------- revision.h | 3 +++ upload-pack.c | 7 ++++++ 7 files changed, 101 insertions(+), 49 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 5f9ec3566f..63f3aed70a 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1311,11 +1311,14 @@ static int want_object_in_pack_one(struct packed_git *p, static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + struct object *referred_commit) { int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *ex; + struct configured_exclusion *referred_ex; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1351,9 +1354,13 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - struct configured_exclusion *ex = - oidmap_get(&configured_exclusions, oid); + if (referred_commit) { + referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); + if (referred_ex && match_packfile_uri_exclusions(referred_ex)) + return 0; + } + ex = oidmap_get(&configured_exclusions, oid); if (ex && match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; @@ -1393,7 +1400,8 @@ static const char no_closure_warning[] = N_( ); static int add_object_entry(const struct object_id *oid, enum object_type type, - const char *name, int exclude) + const char *name, int exclude, + struct object *referred_commit) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1403,7 +1411,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1429,7 +1437,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, if (have_duplicate_entry(oid, 0)) return 0; - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) return 0; create_object_entry(oid, type, name_hash, 0, 0, pack, offset); @@ -1569,7 +1577,7 @@ static void add_pbase_object(struct tree_desc *tree, if (name[cmplen] != '/') { add_object_entry(&entry.oid, object_type(entry.mode), - fullname, 1); + fullname, 1, NULL); return; } if (S_ISDIR(entry.mode)) { @@ -1637,7 +1645,7 @@ static void add_preferred_base_object(const char *name) cmplen = name_cmp_len(name); for (it = pbase_tree; it; it = it->next) { if (cmplen == 0) { - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); } else { struct tree_desc tree; @@ -2839,7 +2847,7 @@ static void add_tag_chain(const struct object_id *oid) die(_("unable to pack objects reachable from tag %s"), oid_to_hex(oid)); - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); if (tag->tagged->type != OBJ_TAG) return; @@ -2994,7 +3002,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) pack_idx_opts.flags &= ~WRITE_REV; return 0; } - if (!strcmp(k, "uploadpack.blobpackfileuri")) { + if (!strcmp(k, "uploadpack.excludeobject") || !strcmp(k, "uploadpack.blobpackfileuri")) { struct configured_exclusion *ex = xmalloc(sizeof(*ex)); const char *oid_end, *pack_end; /* @@ -3007,11 +3015,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) *oid_end != ' ' || parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " + die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) - die(_("object already configured in another " - "uploadpack.blobpackfileuri (got '%s')"), v); + die(_("object already configured by an earlier " + "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); @@ -3040,7 +3048,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; ofs = nth_packed_object_offset(p, pos); - if (!want_object_in_pack(oid, 0, &p, &ofs)) + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) return 0; oi.typep = &type; @@ -3233,7 +3241,7 @@ static void read_object_list_from_stdin(void) die(_("expected object ID, got garbage:\n %s"), line); add_preferred_base_object(p + 1); - add_object_entry(&oid, OBJ_NONE, p + 1, 0); + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); } } @@ -3242,7 +3250,7 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, void *data) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) @@ -3254,8 +3262,9 @@ static void show_commit(struct commit *commit, void *data) static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { + struct object *referred_commit = carry_data; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0); + add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { @@ -3406,7 +3415,7 @@ static void add_objects_in_unpacked_packs(void) QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; - add_object_entry(&o->oid, o->type, "", 0); + add_object_entry(&o->oid, o->type, "", 0, NULL); } } free(in_pack.array); @@ -3422,7 +3431,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, return 0; } - add_object_entry(oid, type, "", 0); + add_object_entry(oid, type, "", 0, NULL); return 0; } @@ -3841,7 +3850,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject or " + "uploadpack.blobpackfileuri with this protocol")), OPT_END(), }; diff --git a/list-objects.c b/list-objects.c index 427228a3ba..968d842ceb 100644 --- a/list-objects.c +++ b/list-objects.c @@ -24,7 +24,8 @@ struct traversal_context { static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &blob->object; size_t pathlen; @@ -60,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data, NULL); + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); strbuf_setlen(path, pathlen); } @@ -97,11 +98,13 @@ static void process_gitlink(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name); + const char *name, + struct object *referred_commit); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, - struct strbuf *base) + struct strbuf *base, + struct object *referred_commit) { struct tree_desc desc; struct name_entry entry; @@ -129,7 +132,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path); + process_tree(ctx, t, base, entry.path, referred_commit); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -142,7 +145,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path); + process_blob(ctx, b, base, entry.path, referred_commit); } } } @@ -150,7 +153,8 @@ static void process_tree_contents(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name) + const char *name, + struct object *referred_commit) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -191,14 +195,14 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); if (base->len) strbuf_addch(base, '/'); if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base); + process_tree_contents(ctx, tree, base, referred_commit); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -207,7 +211,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, NULL); + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -314,9 +318,9 @@ void mark_edges_uninteresting(struct rev_info *revs, } } -static void add_pending_tree(struct rev_info *revs, struct tree *tree) +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) { - add_pending_object(revs, &tree->object, ""); + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); } static void traverse_trees_and_blobs(struct traversal_context *ctx, @@ -329,23 +333,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; + struct object *referred_commit = pending->referred_commit; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data, NULL); + ctx->show_object(obj, name, ctx->show_data, referred_commit); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path); + process_tree(ctx, (struct tree *)obj, base, path, referred_commit); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path); + process_blob(ctx, (struct blob *)obj, base, path, referred_commit); continue; } die("unknown pending object %s (%s)", @@ -370,7 +375,7 @@ static void do_traverse(struct traversal_context *ctx) else if (get_commit_tree(commit)) { struct tree *tree = get_commit_tree(commit); tree->object.flags |= NOT_USER_GIVEN; - add_pending_tree(ctx->revs, tree); + add_pending_tree(ctx->revs, tree, &commit->object); } else if (commit->object.parsed) { die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); diff --git a/object.c b/object.c index 14188453c5..6b1ce2fcde 100644 --- a/object.c +++ b/object.c @@ -322,9 +322,10 @@ void object_list_free(struct object_list **list) */ static char object_array_slopbuf[1]; -void add_object_array_with_path(struct object *obj, const char *name, - struct object_array *array, - unsigned mode, const char *path) +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path, + struct object *referred_commit) { unsigned nr = array->nr; unsigned alloc = array->alloc; @@ -339,6 +340,7 @@ void add_object_array_with_path(struct object *obj, const char *name, } entry = &objects[nr]; entry->item = obj; + entry->referred_commit = referred_commit; if (!name) entry->name = NULL; else if (!*name) @@ -354,6 +356,13 @@ void add_object_array_with_path(struct object *obj, const char *name, array->nr = ++nr; } +void add_object_array_with_path(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path) +{ + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); +} + void add_object_array(struct object *obj, const char *name, struct object_array *array) { add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); diff --git a/object.h b/object.h index 87a6da47c8..d63819ab91 100644 --- a/object.h +++ b/object.h @@ -52,6 +52,7 @@ struct object_array { char *name; char *path; unsigned mode; + struct object *referred_commit; } *objects; }; @@ -157,7 +158,8 @@ void object_list_free(struct object_list **list); /* Object array handling .. */ void add_object_array(struct object *obj, const char *name, struct object_array *array); void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); - +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, + unsigned mode, const char *path, struct object *referred_commit); /* * Returns NULL if the array is empty. Otherwise, returns the last object * after removing its entry from the array. Other resources associated diff --git a/revision.c b/revision.c index 4853c85d0b..65e0926d25 100644 --- a/revision.c +++ b/revision.c @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) commit_stack_clear(&pending); } -static void add_pending_object_with_path(struct rev_info *revs, - struct object *obj, - const char *name, unsigned mode, - const char *path) +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path, + struct object *referred_commit) { struct interpret_branch_name_options options = { 0 }; if (!obj) @@ -326,20 +327,35 @@ static void add_pending_object_with_path(struct rev_info *revs, strbuf_release(&buf); return; /* do not add the commit itself */ } - add_object_array_with_path(obj, name, &revs->pending, mode, path); + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); } +static void add_pending_object_with_path(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); +} static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, - const char *name, unsigned mode) + const char *name, unsigned mode, + struct object *referred_commit) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); +} + +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit) { - add_pending_object_with_path(revs, obj, name, mode, NULL); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); } void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); } void add_head_to_pending(struct rev_info *revs) @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) diagnose_missing_default(revs->def); object = get_reference(revs, revs->def, &oid, 0); - add_pending_object_with_mode(revs, object, revs->def, oc.mode); + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); } /* Did the user ask for any diff output? Run the diff! */ diff --git a/revision.h b/revision.h index a24f72dcd1..f9c9628ed8 100644 --- a/revision.h +++ b/revision.h @@ -423,6 +423,9 @@ void show_object_with_name(FILE *, struct object *, const char *); */ void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct object *referred_commit); void add_pending_oid(struct rev_info *revs, const char *name, const struct object_id *oid, diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..d26fb351a3 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, strbuf_addstr(value, " packfile-uris"); free(str); } + + if (!repo_config_get_string(the_repository, + "uploadpack.excludeobject", + &str) && str) { + strbuf_addstr(value, " packfile-uris"); + free(str); + } } return 1; -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v5 03/14] packfile-uri: support for excluding commit objects 2021-08-25 2:21 ` [PATCH v5 03/14] packfile-uri: support for excluding commit objects Teng Long @ 2021-08-25 23:49 ` Ævar Arnfjörð Bjarmason 2021-09-02 12:26 ` Teng Long 2021-08-26 20:56 ` Junio C Hamano 1 sibling, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-08-25 23:49 UTC (permalink / raw) To: Teng Long; +Cc: gitster, git, jonathantanmy On Wed, Aug 25 2021, Teng Long wrote: > Currently packfile-uri supports the exclusion of blob objects, but in > some scenarios, users may wish to exclude more types of objects, such as > commit and tree objects, not only because packfile itself supports > storing these object types, but also on the other hand, to make > configuration items maintainable and simpler. > > This commit is used to support the recursive exclusion of a commit > object, which means that if the exclusion of a commit is configured as > packfile-uri, the commit itself and all the objects it contains will > also be recursively excluded. In addition, to support this feature, a > new configuration `uploadpack.excludeobject` is introduced. > > The reason for bringing a new configuration is for two considerations. > First, the old configuration supports a single object type (blob), which > limits the use of this feature. Secondly, the name of the old > configuration is not abstract enough, this make extension difficult. If > different object types use different configuration names, the > configuration items will be bloated and difficult to maintain, so the > new configuration is more abstract in name and easy to extend. > > Although a new configuration has been introduced, the old one is > still available and compatible with the new configuration. The old > configuration `uploadpack.blobpackfileuri` only supports excluding > blobs. The new configuration `uploadpack.excludeobject` not only > supports excluding blob objects, but also supports excluding commit > objects, as well as recursively excluding tree objects and blob objects > they contain. I was under the impression that with uploadpack.blobpackfileuri we already supported excluding non-blobs, it was just unfortunately named. Perhaps I'm conflating that with the protocol payload for packfile-uri, which I know doesn't only support excluding blobs. What we didn't support at all was a way to have the server-side mechanism in git.git recursively exclude anything, which I think is what you're adding here... > Signed-off-by: Teng Long <dyroneteng@gmail.com> > --- > builtin/pack-objects.c | 50 +++++++++++++++++++++++++----------------- > list-objects.c | 37 +++++++++++++++++-------------- > object.c | 15 ++++++++++--- > object.h | 4 +++- > revision.c | 34 ++++++++++++++++++++-------- > revision.h | 3 +++ > upload-pack.c | 7 ++++++ > 7 files changed, 101 insertions(+), 49 deletions(-) > > diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c > index 5f9ec3566f..63f3aed70a 100644 > --- a/builtin/pack-objects.c > +++ b/builtin/pack-objects.c > @@ -1311,11 +1311,14 @@ static int want_object_in_pack_one(struct packed_git *p, > static int want_object_in_pack(const struct object_id *oid, > int exclude, > struct packed_git **found_pack, > - off_t *found_offset) > + off_t *found_offset, > + struct object *referred_commit) > { > int want; > struct list_head *pos; > struct multi_pack_index *m; > + struct configured_exclusion *ex; > + struct configured_exclusion *referred_ex; > > if (!exclude && local && has_loose_object_nonlocal(oid)) > return 0; > @@ -1351,9 +1354,13 @@ static int want_object_in_pack(const struct object_id *oid, > } > > if (uri_protocols.nr) { > - struct configured_exclusion *ex = > - oidmap_get(&configured_exclusions, oid); > + if (referred_commit) { > + referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); > + if (referred_ex && match_packfile_uri_exclusions(referred_ex)) > + return 0; > + } > > + ex = oidmap_get(&configured_exclusions, oid); > if (ex && match_packfile_uri_exclusions(ex)) { > oidset_insert(&excluded_by_config, oid); > return 0; > @@ -1393,7 +1400,8 @@ static const char no_closure_warning[] = N_( > ); > > static int add_object_entry(const struct object_id *oid, enum object_type type, > - const char *name, int exclude) > + const char *name, int exclude, > + struct object *referred_commit) > { > struct packed_git *found_pack = NULL; > off_t found_offset = 0; > @@ -1403,7 +1411,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, > if (have_duplicate_entry(oid, exclude)) > return 0; > > - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { > + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { > /* The pack is missing an object, so it will not have closure */ > if (write_bitmap_index) { > if (write_bitmap_index != WRITE_BITMAP_QUIET) > @@ -1429,7 +1437,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, > if (have_duplicate_entry(oid, 0)) > return 0; > > - if (!want_object_in_pack(oid, 0, &pack, &offset)) > + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) > return 0; > > create_object_entry(oid, type, name_hash, 0, 0, pack, offset); > @@ -1569,7 +1577,7 @@ static void add_pbase_object(struct tree_desc *tree, > if (name[cmplen] != '/') { > add_object_entry(&entry.oid, > object_type(entry.mode), > - fullname, 1); > + fullname, 1, NULL); > return; > } > if (S_ISDIR(entry.mode)) { > @@ -1637,7 +1645,7 @@ static void add_preferred_base_object(const char *name) > cmplen = name_cmp_len(name); > for (it = pbase_tree; it; it = it->next) { > if (cmplen == 0) { > - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); > + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); > } > else { > struct tree_desc tree; > @@ -2839,7 +2847,7 @@ static void add_tag_chain(const struct object_id *oid) > die(_("unable to pack objects reachable from tag %s"), > oid_to_hex(oid)); > > - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); > + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); > > if (tag->tagged->type != OBJ_TAG) > return; > @@ -2994,7 +3002,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) > pack_idx_opts.flags &= ~WRITE_REV; > return 0; > } > - if (!strcmp(k, "uploadpack.blobpackfileuri")) { > + if (!strcmp(k, "uploadpack.excludeobject") || !strcmp(k, "uploadpack.blobpackfileuri")) { > struct configured_exclusion *ex = xmalloc(sizeof(*ex)); > const char *oid_end, *pack_end; > /* > @@ -3007,11 +3015,11 @@ static int git_pack_config(const char *k, const char *v, void *cb) > *oid_end != ' ' || > parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || > *pack_end != ' ') > - die(_("value of uploadpack.blobpackfileuri must be " > + die(_("value of uploadpack.excludeobject or uploadpack.blobpackfileuri must be " > "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); > if (oidmap_get(&configured_exclusions, &ex->e.oid)) > - die(_("object already configured in another " > - "uploadpack.blobpackfileuri (got '%s')"), v); > + die(_("object already configured by an earlier " > + "uploadpack.excludeobject or uploadpack.blobpackfileuri (got '%s')"), v); > ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); > memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); > ex->uri = xstrdup(pack_end + 1); > @@ -3040,7 +3048,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, > return 0; > > ofs = nth_packed_object_offset(p, pos); > - if (!want_object_in_pack(oid, 0, &p, &ofs)) > + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) > return 0; > > oi.typep = &type; > @@ -3233,7 +3241,7 @@ static void read_object_list_from_stdin(void) > die(_("expected object ID, got garbage:\n %s"), line); > > add_preferred_base_object(p + 1); > - add_object_entry(&oid, OBJ_NONE, p + 1, 0); > + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); > } > } > > @@ -3242,7 +3250,7 @@ static void read_object_list_from_stdin(void) > > static void show_commit(struct commit *commit, void *data) > { > - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); > + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); > commit->object.flags |= OBJECT_ADDED; > > if (write_bitmap_index) > @@ -3254,8 +3262,9 @@ static void show_commit(struct commit *commit, void *data) > > static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) > { > + struct object *referred_commit = carry_data; > add_preferred_base_object(name); > - add_object_entry(&obj->oid, obj->type, name, 0); > + add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); > obj->flags |= OBJECT_ADDED; > > if (use_delta_islands) { > @@ -3406,7 +3415,7 @@ static void add_objects_in_unpacked_packs(void) > QSORT(in_pack.array, in_pack.nr, ofscmp); > for (i = 0; i < in_pack.nr; i++) { > struct object *o = in_pack.array[i].object; > - add_object_entry(&o->oid, o->type, "", 0); > + add_object_entry(&o->oid, o->type, "", 0, NULL); > } > } > free(in_pack.array); > @@ -3422,7 +3431,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, > return 0; > } > > - add_object_entry(oid, type, "", 0); > + add_object_entry(oid, type, "", 0, NULL); > return 0; > } > > @@ -3841,7 +3850,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) > N_("respect islands during delta compression")), > OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, > N_("protocol"), > - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), > + N_("exclude any configured uploadpack.excludeobject or " > + "uploadpack.blobpackfileuri with this protocol")), > OPT_END(), > }; > > diff --git a/list-objects.c b/list-objects.c > index 427228a3ba..968d842ceb 100644 > --- a/list-objects.c > +++ b/list-objects.c > @@ -24,7 +24,8 @@ struct traversal_context { > static void process_blob(struct traversal_context *ctx, > struct blob *blob, > struct strbuf *path, > - const char *name) > + const char *name, > + struct object *referred_commit) > { > struct object *obj = &blob->object; > size_t pathlen; > @@ -60,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, path->buf, ctx->show_data, NULL); > + ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); > strbuf_setlen(path, pathlen); > } > > @@ -97,11 +98,13 @@ static void process_gitlink(struct traversal_context *ctx, > static void process_tree(struct traversal_context *ctx, > struct tree *tree, > struct strbuf *base, > - const char *name); > + const char *name, > + struct object *referred_commit); > > static void process_tree_contents(struct traversal_context *ctx, > struct tree *tree, > - struct strbuf *base) > + struct strbuf *base, > + struct object *referred_commit) > { > struct tree_desc desc; > struct name_entry entry; > @@ -129,7 +132,7 @@ static void process_tree_contents(struct traversal_context *ctx, > entry.path, oid_to_hex(&tree->object.oid)); > } > t->object.flags |= NOT_USER_GIVEN; > - process_tree(ctx, t, base, entry.path); > + process_tree(ctx, t, base, entry.path, referred_commit); > } > else if (S_ISGITLINK(entry.mode)) > process_gitlink(ctx, entry.oid.hash, > @@ -142,7 +145,7 @@ static void process_tree_contents(struct traversal_context *ctx, > entry.path, oid_to_hex(&tree->object.oid)); > } > b->object.flags |= NOT_USER_GIVEN; > - process_blob(ctx, b, base, entry.path); > + process_blob(ctx, b, base, entry.path, referred_commit); > } > } > } > @@ -150,7 +153,8 @@ static void process_tree_contents(struct traversal_context *ctx, > static void process_tree(struct traversal_context *ctx, > struct tree *tree, > struct strbuf *base, > - const char *name) > + const char *name, > + struct object *referred_commit) > { > struct object *obj = &tree->object; > struct rev_info *revs = ctx->revs; > @@ -191,14 +195,14 @@ static void process_tree(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, base->buf, ctx->show_data, NULL); > + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); > if (base->len) > strbuf_addch(base, '/'); > > if (r & LOFR_SKIP_TREE) > trace_printf("Skipping contents of tree %s...\n", base->buf); > else if (!failed_parse) > - process_tree_contents(ctx, tree, base); > + process_tree_contents(ctx, tree, base, referred_commit); > > r = list_objects_filter__filter_object(ctx->revs->repo, > LOFS_END_TREE, obj, > @@ -207,7 +211,7 @@ static void process_tree(struct traversal_context *ctx, > if (r & LOFR_MARK_SEEN) > obj->flags |= SEEN; > if (r & LOFR_DO_SHOW) > - ctx->show_object(obj, base->buf, ctx->show_data, NULL); > + ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); > > strbuf_setlen(base, baselen); > free_tree_buffer(tree); > @@ -314,9 +318,9 @@ void mark_edges_uninteresting(struct rev_info *revs, > } > } > > -static void add_pending_tree(struct rev_info *revs, struct tree *tree) > +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct object *referred_commit) > { > - add_pending_object(revs, &tree->object, ""); > + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); > } > > static void traverse_trees_and_blobs(struct traversal_context *ctx, > @@ -329,23 +333,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, > for (i = 0; i < ctx->revs->pending.nr; i++) { > struct object_array_entry *pending = ctx->revs->pending.objects + i; > struct object *obj = pending->item; > + struct object *referred_commit = pending->referred_commit; > const char *name = pending->name; > const char *path = pending->path; > if (obj->flags & (UNINTERESTING | SEEN)) > continue; > if (obj->type == OBJ_TAG) { > obj->flags |= SEEN; > - ctx->show_object(obj, name, ctx->show_data, NULL); > + ctx->show_object(obj, name, ctx->show_data, referred_commit); > continue; > } > if (!path) > path = ""; > if (obj->type == OBJ_TREE) { > - process_tree(ctx, (struct tree *)obj, base, path); > + process_tree(ctx, (struct tree *)obj, base, path, referred_commit); > continue; > } > if (obj->type == OBJ_BLOB) { > - process_blob(ctx, (struct blob *)obj, base, path); > + process_blob(ctx, (struct blob *)obj, base, path, referred_commit); > continue; > } > die("unknown pending object %s (%s)", > @@ -370,7 +375,7 @@ static void do_traverse(struct traversal_context *ctx) > else if (get_commit_tree(commit)) { > struct tree *tree = get_commit_tree(commit); > tree->object.flags |= NOT_USER_GIVEN; > - add_pending_tree(ctx->revs, tree); > + add_pending_tree(ctx->revs, tree, &commit->object); > } else if (commit->object.parsed) { > die(_("unable to load root tree for commit %s"), > oid_to_hex(&commit->object.oid)); > diff --git a/object.c b/object.c > index 14188453c5..6b1ce2fcde 100644 > --- a/object.c > +++ b/object.c > @@ -322,9 +322,10 @@ void object_list_free(struct object_list **list) > */ > static char object_array_slopbuf[1]; > > -void add_object_array_with_path(struct object *obj, const char *name, > - struct object_array *array, > - unsigned mode, const char *path) > +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, > + struct object_array *array, > + unsigned mode, const char *path, > + struct object *referred_commit) > { > unsigned nr = array->nr; > unsigned alloc = array->alloc; > @@ -339,6 +340,7 @@ void add_object_array_with_path(struct object *obj, const char *name, > } > entry = &objects[nr]; > entry->item = obj; > + entry->referred_commit = referred_commit; > if (!name) > entry->name = NULL; > else if (!*name) > @@ -354,6 +356,13 @@ void add_object_array_with_path(struct object *obj, const char *name, > array->nr = ++nr; > } > > +void add_object_array_with_path(struct object *obj, const char *name, > + struct object_array *array, > + unsigned mode, const char *path) > +{ > + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); > +} > + > void add_object_array(struct object *obj, const char *name, struct object_array *array) > { > add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); > diff --git a/object.h b/object.h > index 87a6da47c8..d63819ab91 100644 > --- a/object.h > +++ b/object.h > @@ -52,6 +52,7 @@ struct object_array { > char *name; > char *path; > unsigned mode; > + struct object *referred_commit; > } *objects; > }; > > @@ -157,7 +158,8 @@ void object_list_free(struct object_list **list); > /* Object array handling .. */ > void add_object_array(struct object *obj, const char *name, struct object_array *array); > void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); > - > +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, > + unsigned mode, const char *path, struct object *referred_commit); > /* > * Returns NULL if the array is empty. Otherwise, returns the last object > * after removing its entry from the array. Other resources associated > diff --git a/revision.c b/revision.c > index 4853c85d0b..65e0926d25 100644 > --- a/revision.c > +++ b/revision.c > @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) > commit_stack_clear(&pending); > } > > -static void add_pending_object_with_path(struct rev_info *revs, > - struct object *obj, > - const char *name, unsigned mode, > - const char *path) > +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, > + struct object *obj, > + const char *name, unsigned mode, > + const char *path, > + struct object *referred_commit) > { > struct interpret_branch_name_options options = { 0 }; > if (!obj) > @@ -326,20 +327,35 @@ static void add_pending_object_with_path(struct rev_info *revs, > strbuf_release(&buf); > return; /* do not add the commit itself */ > } > - add_object_array_with_path(obj, name, &revs->pending, mode, path); > + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); > } > > +static void add_pending_object_with_path(struct rev_info *revs, > + struct object *obj, > + const char *name, unsigned mode, > + const char *path) > +{ > + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); > +} > static void add_pending_object_with_mode(struct rev_info *revs, > struct object *obj, > - const char *name, unsigned mode) > + const char *name, unsigned mode, > + struct object *referred_commit) > +{ > + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); > +} > + > +void add_pending_object_with_referred_commit(struct rev_info *revs, > + struct object *obj, const char *name, > + struct object *referred_commit) > { > - add_pending_object_with_path(revs, obj, name, mode, NULL); > + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); > } > > void add_pending_object(struct rev_info *revs, > struct object *obj, const char *name) > { > - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); > + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); > } > > void add_head_to_pending(struct rev_info *revs) > @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s > if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) > diagnose_missing_default(revs->def); > object = get_reference(revs, revs->def, &oid, 0); > - add_pending_object_with_mode(revs, object, revs->def, oc.mode); > + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); > } > > /* Did the user ask for any diff output? Run the diff! */ > diff --git a/revision.h b/revision.h > index a24f72dcd1..f9c9628ed8 100644 > --- a/revision.h > +++ b/revision.h > @@ -423,6 +423,9 @@ void show_object_with_name(FILE *, struct object *, const char *); > */ > void add_pending_object(struct rev_info *revs, > struct object *obj, const char *name); > +void add_pending_object_with_referred_commit(struct rev_info *revs, > + struct object *obj, const char *name, > + struct object *referred_commit); > > void add_pending_oid(struct rev_info *revs, > const char *name, const struct object_id *oid, > diff --git a/upload-pack.c b/upload-pack.c > index 5c1cd19612..d26fb351a3 100644 > --- a/upload-pack.c > +++ b/upload-pack.c > @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, > strbuf_addstr(value, " packfile-uris"); > free(str); > } > + > + if (!repo_config_get_string(the_repository, > + "uploadpack.excludeobject", > + &str) && str) { > + strbuf_addstr(value, " packfile-uris"); > + free(str); > + } > } > > return 1; ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 03/14] packfile-uri: support for excluding commit objects 2021-08-25 23:49 ` Ævar Arnfjörð Bjarmason @ 2021-09-02 12:26 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 12:26 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, gitster, jonathantanmy Ævar Arnfjörð Bjarmason wrote: > I was under the impression that with uploadpack.blobpackfileuri we > already supported excluding non-blobs, it was just unfortunately > named. Perhaps I'm conflating that with the protocol payload for > packfile-uri, which I know doesn't only support excluding blobs. > > What we didn't support at all was a way to have the server-side > mechanism in git.git recursively exclude anything, which I think is what > you're adding here... > Agree. You are absolutely right(ಥ_ಥ ). The description of the commit is inaccurate, I will fix this problem in the next patch. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 03/14] packfile-uri: support for excluding commit objects 2021-08-25 2:21 ` [PATCH v5 03/14] packfile-uri: support for excluding commit objects Teng Long 2021-08-25 23:49 ` Ævar Arnfjörð Bjarmason @ 2021-08-26 20:56 ` Junio C Hamano 2021-09-02 12:51 ` Teng Long 1 sibling, 1 reply; 72+ messages in thread From: Junio C Hamano @ 2021-08-26 20:56 UTC (permalink / raw) To: Teng Long; +Cc: avarab, git, jonathantanmy Teng Long <dyroneteng@gmail.com> writes: > This commit is used to support the recursive exclusion of a commit > object, which means that if the exclusion of a commit is configured as > packfile-uri, the commit itself and all the objects it contains will > also be recursively excluded. Whenever you say "which means", e.g. "We do X, which means we do Y", think twice to see if you do not even have to say X. In this particular sentence, I think you can simplify the description greatly and you do not even have to use the word "recursive". Also, because this "exclusion by a commit" does not work like the usual "reachability" relationship Git users are familiar with, it would help to highlight what is special that is done here to the readers. Taking the above together, along the lines of ... When a commit is specified to be excluded as packfile-uri, exclude all trees and blobs contained in its top-level tree, as well as the commit itself, but not the ancestors of the commit and objects that are reachable by them. or something like that, perhaps. > diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c > index 5f9ec3566f..63f3aed70a 100644 > --- a/builtin/pack-objects.c > +++ b/builtin/pack-objects.c > @@ -1311,11 +1311,14 @@ static int want_object_in_pack_one(struct packed_git *p, > static int want_object_in_pack(const struct object_id *oid, > int exclude, > struct packed_git **found_pack, > - off_t *found_offset) > + off_t *found_offset, > + struct object *referred_commit) As the caller is limited to pass commit and no other types of object, the new parameter should be of type "struct commit", no? ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 03/14] packfile-uri: support for excluding commit objects 2021-08-26 20:56 ` Junio C Hamano @ 2021-09-02 12:51 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 12:51 UTC (permalink / raw) To: gitster; +Cc: avarab, dyroneteng, git, jonathantanmy Junio C Hamano wrote: > Whenever you say "which means", e.g. "We do X, which means we do Y", > think twice to see if you do not even have to say X. In this > particular sentence, I think you can simplify the description > greatly and you do not even have to use the word "recursive". Forgive my English for another accident. Will be fixed in the next patch. > Also, because this "exclusion by a commit" does not work like the > usual "reachability" relationship Git users are familiar with, it > would help to highlight what is special that is done here to the > readers. > > Taking the above together, along the lines of ... > > When a commit is specified to be excluded as packfile-uri, > exclude all trees and blobs contained in its top-level tree, as > well as the commit itself, but not the ancestors of the commit > and objects that are reachable by them. > > or something like that, perhaps. Agree. I will use your suggestion in the next patch (may be slightly modified). In the next patch, I originally planned to introduce the exclusion of the commit and with all it's ancestor objects. The problems in the current patch will also be fixed in the next patch. Thanks. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 04/14] packfile-uri: support for excluding tree objects 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (2 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 03/14] packfile-uri: support for excluding commit objects Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees Teng Long ` (10 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy This commit supports the use of `uploadpack.excludeobject` to exclude tree objects, which means that when a type object is configured as packfile-uri, the tree object itself and all objects contains will be recursively excluded. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 30 ++++++++++++++++++++---------- list-objects.c | 32 ++++++++++++++++++-------------- object.c | 6 +++++- object.h | 13 ++++++++++++- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 63f3aed70a..4ff12ec525 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1312,13 +1312,14 @@ static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, off_t *found_offset, - struct object *referred_commit) + struct referred_objects *referred_objs) { int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *commit_ex; + struct configured_exclusion *tree_ex; struct configured_exclusion *ex; - struct configured_exclusion *referred_ex; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1354,14 +1355,23 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - if (referred_commit) { - referred_ex = oidmap_get(&configured_exclusions, &referred_commit->oid); - if (referred_ex && match_packfile_uri_exclusions(referred_ex)) + if (referred_objs && referred_objs->commit) { + commit_ex = oidmap_get(&configured_exclusions, &referred_objs->commit->oid); + if (match_packfile_uri_exclusions(commit_ex)) return 0; } + if (referred_objs && referred_objs->trees) { + struct object_list *p; + for (p = referred_objs->trees; p; p = p->next) { + tree_ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(tree_ex)) + return 0; + } + } + ex = oidmap_get(&configured_exclusions, oid); - if (ex && match_packfile_uri_exclusions(ex)) { + if (match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; } @@ -1401,7 +1411,7 @@ static const char no_closure_warning[] = N_( static int add_object_entry(const struct object_id *oid, enum object_type type, const char *name, int exclude, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1411,7 +1421,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_commit)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_objs)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -3262,9 +3272,9 @@ static void show_commit(struct commit *commit, void *data) static void show_object(struct object *obj, const char *name, void *show_data, void *carry_data) { - struct object *referred_commit = carry_data; + struct referred_objects *referred_objs = carry_data; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0, referred_commit); + add_object_entry(&obj->oid, obj->type, name, 0, referred_objs); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { diff --git a/list-objects.c b/list-objects.c index 968d842ceb..49f177cb56 100644 --- a/list-objects.c +++ b/list-objects.c @@ -25,7 +25,7 @@ static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, const char *name, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct object *obj = &blob->object; size_t pathlen; @@ -61,7 +61,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, path->buf, ctx->show_data, referred_objs); strbuf_setlen(path, pathlen); } @@ -99,19 +99,22 @@ static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, const char *name, - struct object *referred_commit); + struct referred_objects *referred_objs); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct tree_desc desc; struct name_entry entry; enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ? all_entries_interesting : entry_not_interesting; + struct referred_objects *referred_buf; init_tree_desc(&desc, tree->buffer, tree->size); + referred_buf = xmemdupz(referred_objs, sizeof(struct referred_objects)); + object_list_insert(&tree->object, &referred_buf->trees); while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { @@ -132,7 +135,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path, referred_commit); + process_tree(ctx, t, base, entry.path, referred_buf); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -145,16 +148,17 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path, referred_commit); + process_blob(ctx, b, base, entry.path, referred_buf); } } + free(referred_buf); } static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, const char *name, - struct object *referred_commit) + struct referred_objects *referred_objs) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -195,14 +199,14 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, base->buf, ctx->show_data, referred_objs); if (base->len) strbuf_addch(base, '/'); if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base, referred_commit); + process_tree_contents(ctx, tree, base, referred_objs); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -211,7 +215,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data, referred_commit); + ctx->show_object(obj, base->buf, ctx->show_data, referred_objs); strbuf_setlen(base, baselen); free_tree_buffer(tree); @@ -333,24 +337,24 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; - struct object *referred_commit = pending->referred_commit; + struct referred_objects *referred_objs = pending->referred_objects; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data, referred_commit); + ctx->show_object(obj, name, ctx->show_data, referred_objs); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path, referred_commit); + process_tree(ctx, (struct tree *)obj, base, path, referred_objs); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path, referred_commit); + process_blob(ctx, (struct blob *)obj, base, path, referred_objs); continue; } die("unknown pending object %s (%s)", diff --git a/object.c b/object.c index 6b1ce2fcde..69ba0baf95 100644 --- a/object.c +++ b/object.c @@ -331,6 +331,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch unsigned alloc = array->alloc; struct object_array_entry *objects = array->objects; struct object_array_entry *entry; + struct referred_objects *referred_objs = xmalloc(sizeof(struct referred_objects)); if (nr >= alloc) { alloc = (alloc + 32) * 2; @@ -338,9 +339,11 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch array->alloc = alloc; array->objects = objects; } + referred_objs->commit = referred_commit; + referred_objs->trees = NULL; entry = &objects[nr]; entry->item = obj; - entry->referred_commit = referred_commit; + entry->referred_objects = referred_objs; if (!name) entry->name = NULL; else if (!*name) @@ -377,6 +380,7 @@ static void object_array_release_entry(struct object_array_entry *ent) if (ent->name != object_array_slopbuf) free(ent->name); free(ent->path); + free(ent->referred_objects); } struct object *object_array_pop(struct object_array *array) diff --git a/object.h b/object.h index d63819ab91..3785546adf 100644 --- a/object.h +++ b/object.h @@ -52,12 +52,23 @@ struct object_array { char *name; char *path; unsigned mode; - struct object *referred_commit; + /* + * referred_objects or NULL. If non-NULL, it will + * temporary storage the referred commit and trees when + * traversing the specified object. Space for time, + * reduce related computing costs (such as packfile-uri + * exclusion), clean up when the traversal is over. + */ + struct referred_objects *referred_objects; } *objects; }; #define OBJECT_ARRAY_INIT { 0, 0, NULL } +struct referred_objects{ + struct object *commit; + struct object_list *trees; +}; /* * object flag allocation: * revision.h: 0---------10 15 23------26 -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (3 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 04/14] packfile-uri: support for excluding tree objects Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 23:52 ` Ævar Arnfjörð Bjarmason 2021-08-25 2:21 ` [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup Teng Long ` (9 subsequent siblings) 14 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- Documentation/technical/packfile-uri.txt | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index f7eabc6c76..c3e4873956 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -35,13 +35,26 @@ include some sort of non-trivial implementation in the Minimum Viable Product, at least so that we can test the client. This is the implementation: a feature, marked experimental, that allows the -server to be configured by one or more `uploadpack.blobPackfileUri=<sha1> -<uri>` entries. Whenever the list of objects to be sent is assembled, all such -blobs are excluded, replaced with URIs. As noted in "Future work" below, the -server can evolve in the future to support excluding other objects (or other -implementations of servers could be made that support excluding other objects) -without needing a protocol change, so clients should not expect that packfiles -downloaded in this way only contain single blobs. +server to be configured by one or more entries with the format: + + uploadpack.excludeobject=<object-hash> <pack-hash> <uri> + +Value <object-hash> is the key of entry, and the object type can be a blob, +tree, or commit. The exclusion of tree and commit is recursive by default, +which means that when a tree or commit object is excluded, the object itself +and all reachable objects of the object will be excluded recursively. Whenever +the list of objects to be sent is assembled, all such objects are excluded, +replaced with URIs. + +Configuration compatibility +------------- + +The old configuration of packfile-uri: + + `uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri>` + +For the old configuration is compatible with the new one, but it only +supports the exclusion of blob objects. Client design ------------- @@ -65,9 +78,6 @@ The protocol design allows some evolution of the server and client without any need for protocol changes, so only a small-scoped design is included here to form the MVP. For example, the following can be done: - * On the server, more sophisticated means of excluding objects (e.g. by - specifying a commit to represent that commit and all objects that it - references). * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more @@ -78,4 +88,4 @@ There are some possible features that will require a change in protocol: * Additional HTTP headers (e.g. authentication) * Byte range support - * Different file formats referenced by URIs (e.g. raw object) + * Different file formats referenced by URIs (e.g. raw object) \ No newline at end of file -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees 2021-08-25 2:21 ` [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees Teng Long @ 2021-08-25 23:52 ` Ævar Arnfjörð Bjarmason 2021-09-02 11:23 ` Teng Long 0 siblings, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-08-25 23:52 UTC (permalink / raw) To: Teng Long; +Cc: gitster, git, jonathantanmy On Wed, Aug 25 2021, Teng Long wrote: > Client design > ------------- > @@ -65,9 +78,6 @@ The protocol design allows some evolution of the server and client without any > need for protocol changes, so only a small-scoped design is included here to > form the MVP. For example, the following can be done: > > - * On the server, more sophisticated means of excluding objects (e.g. by > - specifying a commit to represent that commit and all objects that it > - references). > * On the client, resumption of clone. If a clone is interrupted, information > could be recorded in the repository's config and a "clone-resume" command > can resume the clone in progress. (Resumption of subsequent fetches is more > @@ -78,4 +88,4 @@ There are some possible features that will require a change in protocol: > > * Additional HTTP headers (e.g. authentication) > * Byte range support > - * Different file formats referenced by URIs (e.g. raw object) > + * Different file formats referenced by URIs (e.g. raw object) > \ No newline at end of file Newline churn? ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees 2021-08-25 23:52 ` Ævar Arnfjörð Bjarmason @ 2021-09-02 11:23 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 11:23 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, gitster, jonathantanmy > Newline churn? Agree. I have no impression why the NEWLINE was deleted, will be fixed in the next patch. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (4 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 23:55 ` Ævar Arnfjörð Bjarmason 2021-08-25 2:21 ` [PATCH v5 07/14] t5702: support for excluding commit objects Teng Long ` (8 subsequent siblings) 14 siblings, 1 reply; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..e6314b53b0 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -753,7 +753,7 @@ test_expect_success 'ls-remote with v2 http sends only one POST' ' ' test_expect_success 'push with http:// and a config of v2 does not request v2' ' - test_when_finished "rm -f log" && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && # Till v2 for push is designed, make sure that if a client has # protocol.version configured to use v2, that the client instead falls # back and uses v0. @@ -776,7 +776,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' ' test_expect_success 'when server sends "ready", expect DELIM' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -796,7 +796,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' ' test_expect_success 'when server does not send "ready", expect FLUSH' ' - rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH/http_parent\" http_child log" && git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && @@ -834,7 +834,7 @@ configure_exclusion () { test_expect_success 'part of packfile response provided as URI' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -883,7 +883,7 @@ test_expect_success 'part of packfile response provided as URI' ' test_expect_success 'packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -904,7 +904,7 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -935,7 +935,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' test_expect_success 'packfile-uri with transfer.fsckobjects' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -959,7 +959,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -989,7 +989,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child && + test_when_finished "rm -rf \"$P\" http_child" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1015,7 +1015,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodules separate from tree is invalid' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child err && + test_when_finished "rm -rf \"$P\" http_child err" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1038,4 +1038,4 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul # DO NOT add non-httpd-specific tests here, because the last part of this # test script is only executed when httpd is available and enabled. -test_done +test_done \ No newline at end of file -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup 2021-08-25 2:21 ` [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup Teng Long @ 2021-08-25 23:55 ` Ævar Arnfjörð Bjarmason 2021-09-02 11:37 ` Teng Long 0 siblings, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-08-25 23:55 UTC (permalink / raw) To: Teng Long; +Cc: gitster, git, jonathantanmy On Wed, Aug 25 2021, Teng Long wrote: Thanks, much needed cleanup. I have an unsubmitted patch to do pretty much this, plus some: https://github.com/avar/git/commit/27b3543c6ed You might find the difference between the two interesting.. > -test_done > +test_done > \ No newline at end of file More newline churn. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup 2021-08-25 23:55 ` Ævar Arnfjörð Bjarmason @ 2021-09-02 11:37 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 11:37 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, gitster, jonathantanmy > Thanks, much needed cleanup. I have an unsubmitted patch to do pretty > much this, plus some: https://github.com/avar/git/commit/27b3543c6ed > > You might find the difference between the two interesting.. Cool. I had took a look at the commit. In comparision, I ignored some places that need to cleanup, I don't know if I got your meaning? If so, how to deal with this situation better, continue my work or rebase your commit to the current patchset? >> -test_done >> +test_done >> \ No newline at end of file > > More newline churn. Will be fixed in the next patch. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 07/14] t5702: support for excluding commit objects 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (5 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 08/14] Add new parameter "carry_data" for "show_commit function Teng Long ` (7 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 292 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 266 insertions(+), 26 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e6314b53b0..5ad52e0cee 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -824,17 +824,47 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + objt="$1" + P="$2" + oid="$3" + version="$4" + + oldc="uploadpack.blobpackfileuri" + newc="uploadpack.excludeobject" + configkey="" + + if test "$version" = "old" + then + configkey="$oldc" + else + configkey="$newc" + fi + + if test "$objt" = "blob" + then + git -C "$P" hash-object "$oid" >objh && + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + elif test "$objt" = "commit" || test "$objt" = "tree" || test "$objt" = "tag" + then + echo "$oid" >objh + git -C "$P" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "unsupported object type in configure_exclusion (got $objt)" + fi } -test_expect_success 'part of packfile response provided as URI' ' +part_of_packfile_response_verify() { + config="$1" P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - test_when_finished "rm -rf \"$P\" http_child log" && + test_when_finished "rm -rf \"$P\" http_child log *found" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -843,10 +873,10 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob config >h && + configure_exclusion blob "$P" other-blob config >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -879,9 +909,11 @@ test_expect_success 'part of packfile response provided as URI' ' ls http_child/.git/objects/pack/*.pack \ http_child/.git/objects/pack/*.idx >filelist && test_line_count = 6 filelist -' +} + +blobpackfileuri_fetch () { + config="$1" -test_expect_success 'packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_when_finished "rm -rf \"$P\" http_child log" && @@ -890,9 +922,9 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob $config >h && git init http_child && @@ -900,6 +932,215 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' git -C http_child -c protocol.version=2 \ -c fetch.uriprotocols=http,https \ fetch "$HTTPD_URL/smart/http_parent" +} + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): part of packfile response provided as URI' ' + part_of_packfile_response_verify old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): part of packfile response provided as URI' ' + part_of_packfile_response_verify new +' + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch new +' + +test_expect_success 'tree-exclusion: part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + # Dir struct + # . + # |-- A.t + # |-- my-tree + # | `-- my-blob + # `-- other-tree + # |-- other-blob + # `-- sub-tree + # `-- sub-blob + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + mkdir "$P"/other-tree/sub-tree && + echo sub-blob >"$P"/other-tree/sub-tree/sub-blob && + git -C "$P" add other-tree && + test_commit -C "$P" A && + + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree HEAD other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD other-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + subblobh=$(git -C "$P" hash-object other-tree/sub-tree/sub-blob) && + + configure_exclusion tree "$P" "$mytreeh" config >h && + configure_exclusion tree "$P" "$othertreeh" config >h2 && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 3 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi + elif test_line_count = 2 out.objectlist + then + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + elif test_line_count = 4 out.objectlist + then + if grep $othertreeh out + then + >othertreehfound + fi && + if grep $otherblobh out + then + >otherblobhfound + fi + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f othertreehfound && + test -f otherblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 6 filelist +' + +test_expect_success 'commit-exclusion: part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/my-tree/sub-tree && + echo sub-blob >"$P"/my-tree/sub-tree/sub-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD my-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + subblobh=$(git -C "$P" hash-object my-tree/sub-tree/sub-blob) && + + configure_exclusion commit "$P" "$commith" >h && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 7 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi && + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + + # Ensure that there are exactly 2 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist ' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' @@ -913,9 +1154,9 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -923,7 +1164,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" hash-object other-blob >objh && git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && git -C "$P" config --add \ - "uploadpack.blobpackfileuri" \ + "uploadpack.excludeobject" \ "$(cat objh) $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && test_must_fail env GIT_TEST_SIDEBAND_ALL=1 \ @@ -942,9 +1183,8 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -976,9 +1216,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1000,7 +1240,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo git -C "$P" add .gitmodules && git -C "$P" commit -m x && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ @@ -1024,9 +1264,9 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul echo "path = include/foo" >>"$P/.gitmodules" && echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" .gitmodules >h && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 08/14] Add new parameter "carry_data" for "show_commit function 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (6 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 07/14] t5702: support for excluding commit objects Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 09/14] commit.h: add wrapped tags in commit struct Teng Long ` (6 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/describe.c | 4 ++-- builtin/pack-objects.c | 6 +++--- builtin/rev-list.c | 4 ++-- bundle.c | 4 ++-- list-objects.c | 2 +- list-objects.h | 2 +- pack-bitmap.c | 6 +++--- reachable.c | 2 +- shallow.c | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 045da79b5c..8fb99bbda5 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -479,9 +479,9 @@ struct process_commit_data { struct rev_info *revs; }; -static void process_commit(struct commit *commit, void *data) +static void process_commit(struct commit *commit, void *show_data, void *carry_data) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = show_data; pcd->current_commit = commit->object.oid; } diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 4ff12ec525..d38b24e375 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3080,7 +3080,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; } -static void show_commit_pack_hint(struct commit *commit, void *_data) +static void show_commit_pack_hint(struct commit *commit, void *show_data, void *carry_data) { /* nothing to do; commits don't have a namehash */ } @@ -3258,7 +3258,7 @@ static void read_object_list_from_stdin(void) /* Remember to update object flag allocation in object.h */ #define OBJECT_ADDED (1u<<20) -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, void *show_data, void *carry_data) { add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); commit->object.flags |= OBJECT_ADDED; @@ -3572,7 +3572,7 @@ static void record_recent_object(struct object *obj, oid_array_append(&recent_objects, &obj->oid); } -static void record_recent_commit(struct commit *commit, void *data) +static void record_recent_commit(struct commit *commit, void *show_data, void *carry_data) { oid_array_append(&recent_objects, &commit->object.oid); } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 1cad33d9e8..b5e7ba6e83 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -94,9 +94,9 @@ static off_t get_object_disk_usage(struct object *obj) } static void finish_commit(struct commit *commit); -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, void *show_data, void *carry_data) { - struct rev_list_info *info = data; + struct rev_list_info *info = show_data; struct rev_info *revs = info->revs; display_progress(progress, ++progress_counter); diff --git a/bundle.c b/bundle.c index 693d619551..143e45ce0c 100644 --- a/bundle.c +++ b/bundle.c @@ -437,9 +437,9 @@ struct bundle_prerequisites_info { int fd; }; -static void write_bundle_prerequisites(struct commit *commit, void *data) +static void write_bundle_prerequisites(struct commit *commit, void *show_data, void *carry_data) { - struct bundle_prerequisites_info *bpi = data; + struct bundle_prerequisites_info *bpi = show_data; struct object *object; struct pretty_print_context ctx = { 0 }; struct strbuf buf = STRBUF_INIT; diff --git a/list-objects.c b/list-objects.c index 49f177cb56..2e53a01458 100644 --- a/list-objects.c +++ b/list-objects.c @@ -384,7 +384,7 @@ static void do_traverse(struct traversal_context *ctx) die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); } - ctx->show_commit(commit, ctx->show_data); + ctx->show_commit(commit, ctx->show_data, NULL); if (ctx->revs->tree_blobs_in_commit_order) /* diff --git a/list-objects.h b/list-objects.h index ab946d34db..838b8c78c9 100644 --- a/list-objects.h +++ b/list-objects.h @@ -5,7 +5,7 @@ struct commit; struct object; struct rev_info; -typedef void (*show_commit_fn)(struct commit *, void *); +typedef void (*show_commit_fn)(struct commit *, void *, void *); typedef void (*show_object_fn)(struct object *, const char *, void *, void *); void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); diff --git a/pack-bitmap.c b/pack-bitmap.c index 516eb235da..81cf14ef8e 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -473,7 +473,7 @@ static void show_object(struct object *object, const char *name, void *show_data bitmap_set(data->base, bitmap_pos); } -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, void *show_data, void *carry_data) { } @@ -1281,9 +1281,9 @@ static void test_show_object(struct object *object, const char *name, display_progress(tdata->prg, ++tdata->seen); } -static void test_show_commit(struct commit *commit, void *data) +static void test_show_commit(struct commit *commit, void *show_data, void *carry_data) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, diff --git a/reachable.c b/reachable.c index 521b39edef..d38c31ae45 100644 --- a/reachable.c +++ b/reachable.c @@ -52,7 +52,7 @@ static void mark_object(struct object *obj, const char *name, void *show_data, v update_progress(show_data); } -static void mark_commit(struct commit *c, void *show_data) +static void mark_commit(struct commit *c, void *show_data, void *carry_data) { mark_object(&c->object, NULL, show_data, NULL); } diff --git a/shallow.c b/shallow.c index 9ed18eb884..33f878565c 100644 --- a/shallow.c +++ b/shallow.c @@ -185,9 +185,9 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth, return result; } -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, void *show_data, void *carry_data) { - commit_list_insert(commit, data); + commit_list_insert(commit, show_data); } /* -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 09/14] commit.h: add wrapped tags in commit struct 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (7 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 08/14] Add new parameter "carry_data" for "show_commit function Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 23:58 ` Ævar Arnfjörð Bjarmason 2021-09-02 12:39 ` ZheNing Hu 2021-08-25 2:21 ` [PATCH v5 10/14] object.h: add referred tags in `referred_objects` struct Teng Long ` (5 subsequent siblings) 14 siblings, 2 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- commit.h | 5 +++++ revision.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/commit.h b/commit.h index df42eb434f..1e99e9ae8a 100644 --- a/commit.h +++ b/commit.h @@ -38,6 +38,11 @@ struct commit { */ struct tree *maybe_tree; unsigned int index; + /* + * wrapped tags or NULL. If the commit is peeled from tag(s), + * then save the wraps, otherwise will be NULL. + */ + struct object_list *wraps; }; extern int save_commit_buffer; diff --git a/revision.c b/revision.c index 65e0926d25..aecf493f46 100644 --- a/revision.c +++ b/revision.c @@ -416,14 +416,17 @@ static struct commit *handle_commit(struct rev_info *revs, const char *path = entry->path; unsigned int mode = entry->mode; unsigned long flags = object->flags; - + struct object_list *wraps = NULL; /* * Tag object? Look what it points to.. */ while (object->type == OBJ_TAG) { struct tag *tag = (struct tag *) object; - if (revs->tag_objects && !(flags & UNINTERESTING)) + if (revs->tag_objects && !(flags & UNINTERESTING)) { + object_list_insert(object, &wraps); add_pending_object(revs, object, tag->tag); + } + object = parse_object(revs->repo, get_tagged_oid(tag)); if (!object) { if (revs->ignore_missing_links || (flags & UNINTERESTING)) @@ -449,6 +452,7 @@ static struct commit *handle_commit(struct rev_info *revs, */ if (object->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)object; + commit->wraps = wraps; if (repo_parse_commit(revs->repo, commit) < 0) die("unable to parse commit %s", name); -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* Re: [PATCH v5 09/14] commit.h: add wrapped tags in commit struct 2021-08-25 2:21 ` [PATCH v5 09/14] commit.h: add wrapped tags in commit struct Teng Long @ 2021-08-25 23:58 ` Ævar Arnfjörð Bjarmason 2021-09-02 12:17 ` Teng Long 2021-09-02 12:39 ` ZheNing Hu 1 sibling, 1 reply; 72+ messages in thread From: Ævar Arnfjörð Bjarmason @ 2021-08-25 23:58 UTC (permalink / raw) To: Teng Long; +Cc: gitster, git, jonathantanmy On Wed, Aug 25 2021, Teng Long wrote: > Signed-off-by: Teng Long <dyroneteng@gmail.com> > --- > commit.h | 5 +++++ > revision.c | 8 ++++++-- > 2 files changed, 11 insertions(+), 2 deletions(-) > > diff --git a/commit.h b/commit.h > index df42eb434f..1e99e9ae8a 100644 > --- a/commit.h > +++ b/commit.h > @@ -38,6 +38,11 @@ struct commit { > */ > struct tree *maybe_tree; > unsigned int index; > + /* > + * wrapped tags or NULL. If the commit is peeled from tag(s), > + * then save the wraps, otherwise will be NULL. > + */ > + struct object_list *wraps; > }; > > extern int save_commit_buffer; > diff --git a/revision.c b/revision.c > index 65e0926d25..aecf493f46 100644 > --- a/revision.c > +++ b/revision.c > @@ -416,14 +416,17 @@ static struct commit *handle_commit(struct rev_info *revs, > const char *path = entry->path; > unsigned int mode = entry->mode; > unsigned long flags = object->flags; > - > + struct object_list *wraps = NULL; > /* > * Tag object? Look what it points to.. > */ > while (object->type == OBJ_TAG) { > struct tag *tag = (struct tag *) object; > - if (revs->tag_objects && !(flags & UNINTERESTING)) > + if (revs->tag_objects && !(flags & UNINTERESTING)) { > + object_list_insert(object, &wraps); > add_pending_object(revs, object, tag->tag); > + } > + > object = parse_object(revs->repo, get_tagged_oid(tag)); > if (!object) { > if (revs->ignore_missing_links || (flags & UNINTERESTING)) > @@ -449,6 +452,7 @@ static struct commit *handle_commit(struct rev_info *revs, > */ > if (object->type == OBJ_COMMIT) { > struct commit *commit = (struct commit *)object; > + commit->wraps = wraps; > > if (repo_parse_commit(revs->repo, commit) < 0) > die("unable to parse commit %s", name); Can't we store this info on the side between these two static functions somehow, instead of adding this "wraps" to all commit structs? ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 09/14] commit.h: add wrapped tags in commit struct 2021-08-25 23:58 ` Ævar Arnfjörð Bjarmason @ 2021-09-02 12:17 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 12:17 UTC (permalink / raw) To: avarab; +Cc: dyroneteng, git, gitster, jonathantanmy Ævar Arnfjörð Bjarmason wrote: > Can't we store this info on the side between these two static functions > somehow, instead of adding this "wraps" to all commit structs? > Thanks very much and I have some doubts. > ... instead of adding this "wraps" to all commit structs? I think "adding this "wraps" to all commit struct" is an easy but a little rough indeed. I didn't know if this is okay at the time. So I pushed the patch, hoping to ask some different opinions. > Can't we store this info on the side between these two static functions... Do you mean to use static storage to share the "wraps", or other way? I want to make sure that I understand your opinion accurately. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 09/14] commit.h: add wrapped tags in commit struct 2021-08-25 2:21 ` [PATCH v5 09/14] commit.h: add wrapped tags in commit struct Teng Long 2021-08-25 23:58 ` Ævar Arnfjörð Bjarmason @ 2021-09-02 12:39 ` ZheNing Hu 2021-09-02 13:01 ` Teng Long 1 sibling, 1 reply; 72+ messages in thread From: ZheNing Hu @ 2021-09-02 12:39 UTC (permalink / raw) To: Teng Long Cc: Junio C Hamano, Ævar Arnfjörð Bjarmason, Git List, Jonathan Tan Teng Long <dyroneteng@gmail.com> 于2021年8月25日周三 上午10:24写道: > > Signed-off-by: Teng Long <dyroneteng@gmail.com> > --- > commit.h | 5 +++++ > revision.c | 8 ++++++-- > 2 files changed, 11 insertions(+), 2 deletions(-) > > diff --git a/commit.h b/commit.h > index df42eb434f..1e99e9ae8a 100644 > --- a/commit.h > +++ b/commit.h > @@ -38,6 +38,11 @@ struct commit { > */ > struct tree *maybe_tree; > unsigned int index; > + /* > + * wrapped tags or NULL. If the commit is peeled from tag(s), > + * then save the wraps, otherwise will be NULL. > + */ > + struct object_list *wraps; > }; > > extern int save_commit_buffer; > diff --git a/revision.c b/revision.c > index 65e0926d25..aecf493f46 100644 > --- a/revision.c > +++ b/revision.c > @@ -416,14 +416,17 @@ static struct commit *handle_commit(struct rev_info *revs, > const char *path = entry->path; > unsigned int mode = entry->mode; > unsigned long flags = object->flags; > - > + struct object_list *wraps = NULL; > /* > * Tag object? Look what it points to.. > */ > while (object->type == OBJ_TAG) { > struct tag *tag = (struct tag *) object; > - if (revs->tag_objects && !(flags & UNINTERESTING)) > + if (revs->tag_objects && !(flags & UNINTERESTING)) { > + object_list_insert(object, &wraps); > add_pending_object(revs, object, tag->tag); > + } > + > object = parse_object(revs->repo, get_tagged_oid(tag)); > if (!object) { > if (revs->ignore_missing_links || (flags & UNINTERESTING)) > @@ -449,6 +452,7 @@ static struct commit *handle_commit(struct rev_info *revs, > */ > if (object->type == OBJ_COMMIT) { > struct commit *commit = (struct commit *)object; > + commit->wraps = wraps; > > if (repo_parse_commit(revs->repo, commit) < 0) > die("unable to parse commit %s", name); > -- > 2.31.1.456.gec51e24953 > /* * The size of this struct matters in full repo walk operations like * 'git clone' or 'git gc'. Consider using commit-slab to attach data * to a commit instead of adding new fields here. */ struct commit { struct object object; timestamp_t date; struct commit_list *parents; /* * If the commit is loaded from the commit-graph file, then this * member may be NULL. Only access it through repo_get_commit_tree() * or get_commit_tree_oid(). */ struct tree *maybe_tree; unsigned int index; }; According to the instructions above, I wonder if you should use "commit_slab" to store part of the data related to the commit object instead of modifying the member of struct commit itself? See: https://github.com/git/git/blob/master/commit-slab.h https://github.com/git/git/blob/master/commit-slab-impl.h https://github.com/git/git/blob/master/commit-slab-decl.h https://lore.kernel.org/git/CAOLTT8Q8BEKCVwPDypW1w66P9_xP7QC0T-CnLqamqAL4haGzwA@mail.gmail.com/ Thanks. -- ZheNing Hu ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH v5 09/14] commit.h: add wrapped tags in commit struct 2021-09-02 12:39 ` ZheNing Hu @ 2021-09-02 13:01 ` Teng Long 0 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-09-02 13:01 UTC (permalink / raw) To: adlternative; +Cc: avarab, dyroneteng, git, gitster, jonathantanmy ZheNing Hu wrote: > /* > * The size of this struct matters in full repo walk operations like > * 'git clone' or 'git gc'. Consider using commit-slab to attach data > * to a commit instead of adding new fields here. > */ > struct commit { > struct object object; > timestamp_t date; > struct commit_list *parents; > > /* > * If the commit is loaded from the commit-graph file, then this > * member may be NULL. Only access it through repo_get_commit_tree() > * or get_commit_tree_oid(). > */ > struct tree *maybe_tree; > unsigned int index; > }; > > According to the instructions above, I wonder if you should use "commit_slab" to > store part of the data related to the commit object instead of > modifying the member > of struct commit itself? > > See: > https://github.com/git/git/blob/master/commit-slab.h > https://github.com/git/git/blob/master/commit-slab-impl.h > https://github.com/git/git/blob/master/commit-slab-decl.h > https://lore.kernel.org/git/CAOLTT8Q8BEKCVwPDypW1w66P9_xP7QC0T-CnLqamqAL4haGzwA@mail.gmail.com/ Awesome! Maybe it's what I really need now, I will make a try. Thanks(比心). ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v5 10/14] object.h: add referred tags in `referred_objects` struct 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (8 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 09/14] commit.h: add wrapped tags in commit struct Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 11/14] packfile-uri: support for excluding tag objects Teng Long ` (4 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- object.c | 1 + object.h | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/object.c b/object.c index 69ba0baf95..b25b2e2919 100644 --- a/object.c +++ b/object.c @@ -341,6 +341,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch } referred_objs->commit = referred_commit; referred_objs->trees = NULL; + referred_objs->tags = NULL; entry = &objects[nr]; entry->item = obj; entry->referred_objects = referred_objs; diff --git a/object.h b/object.h index 3785546adf..bd59eaa6d9 100644 --- a/object.h +++ b/object.h @@ -54,8 +54,8 @@ struct object_array { unsigned mode; /* * referred_objects or NULL. If non-NULL, it will - * temporary storage the referred commit and trees when - * traversing the specified object. Space for time, + * temporary storage the referred commit, trees and tags + * when traversing the specified object. Space for time, * reduce related computing costs (such as packfile-uri * exclusion), clean up when the traversal is over. */ @@ -68,6 +68,7 @@ struct object_array { struct referred_objects{ struct object *commit; struct object_list *trees; + struct object_list *tags; }; /* * object flag allocation: -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 11/14] packfile-uri: support for excluding tag objects 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (9 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 10/14] object.h: add referred tags in `referred_objects` struct Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 12/14] packfile-uri.txt: " Teng Long ` (3 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy This commit supports the use of `uploadpack.excludeobject` to exclude tag objects, both lightweight tag and annotated tag are supported: -If a lightweight tag (such as a commit object) have been configured, the mechanism of exclusion is the same as the commit object (the commit object and all objects it contains will be recusively excluded). -If an annotated tag (created with -a, -s, or -u) have been configured, the annotated tag and all the objects that it contains will be excluded, For an example of the annotated tag: Create an annotated tag from HEAD: git tag -a A -m "tag A description" Output the SHA (<tag_oid>) of tag "A" : git rev-parse A^{object} Dereference <tag_oid>, output the SHA <commit_oid> of commit: git rev-parse A^{} In the above case, when the tag object (<tag_oid>) is configured with `uploadpack.excludeobject` which means <tag_oid>, the dereference commit object (<commit_oid>), and all the objects that <commit_oid> recursively contains (trees, blobs), will be excluded (using a packfile URI instead). Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 20 ++++++++++++++++++-- list-objects.c | 9 ++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index d38b24e375..d5e3f2c229 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1317,9 +1317,11 @@ static int want_object_in_pack(const struct object_id *oid, int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *tag_ex; struct configured_exclusion *commit_ex; struct configured_exclusion *tree_ex; struct configured_exclusion *ex; + struct object_list *p; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1355,14 +1357,27 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { + if (referred_objs && referred_objs->tags) { + for (p = referred_objs->tags; p; p = p->next) { + tag_ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(tag_ex)) + return 0; + } + } + if (referred_objs && referred_objs->commit) { commit_ex = oidmap_get(&configured_exclusions, &referred_objs->commit->oid); if (match_packfile_uri_exclusions(commit_ex)) return 0; + struct commit *commit = (struct commit*) referred_objs->commit; + for (p = commit->wraps; p; p = p->next) { + tag_ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(tag_ex)) + return 0; + } } if (referred_objs && referred_objs->trees) { - struct object_list *p; for (p = referred_objs->trees; p; p = p->next) { tree_ex = oidmap_get(&configured_exclusions, &p->item->oid); if (match_packfile_uri_exclusions(tree_ex)) @@ -3260,7 +3275,8 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, void *show_data, void *carry_data) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); + struct referred_objects *referred_objs = carry_data; + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, referred_objs); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) diff --git a/list-objects.c b/list-objects.c index 2e53a01458..52f38c9151 100644 --- a/list-objects.c +++ b/list-objects.c @@ -367,6 +367,7 @@ static void do_traverse(struct traversal_context *ctx) { struct commit *commit; struct strbuf csp; /* callee's scratch pad */ + struct referred_objects *referred_objs; strbuf_init(&csp, PATH_MAX); while ((commit = get_revision(ctx->revs)) != NULL) { @@ -384,7 +385,13 @@ static void do_traverse(struct traversal_context *ctx) die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); } - ctx->show_commit(commit, ctx->show_data, NULL); + referred_objs = xmalloc(sizeof(struct referred_objects)); + referred_objs->commit = NULL; + referred_objs->trees = NULL; + referred_objs->tags = commit->wraps; + + ctx->show_commit(commit, ctx->show_data, referred_objs); + free(referred_objs); if (ctx->revs->tree_blobs_in_commit_order) /* -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 12/14] packfile-uri.txt: support for excluding tag objects 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (10 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 11/14] packfile-uri: support for excluding tag objects Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 13/14] t5702: add tag exclusion test case Teng Long ` (2 subsequent siblings) 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- Documentation/technical/packfile-uri.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index c3e4873956..bf5939cb8d 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -39,12 +39,18 @@ server to be configured by one or more entries with the format: uploadpack.excludeobject=<object-hash> <pack-hash> <uri> -Value <object-hash> is the key of entry, and the object type can be a blob, -tree, or commit. The exclusion of tree and commit is recursive by default, -which means that when a tree or commit object is excluded, the object itself -and all reachable objects of the object will be excluded recursively. Whenever -the list of objects to be sent is assembled, all such objects are excluded, -replaced with URIs. +Value <object-hash> is the key of entry, and the object type can be blob, tree, +commit, or tag. When an object is configured with `uploadpack.excludeobject` which +means that whenever the list of objects to be sent is assembled, the object (also +include the related objects in some cases, the following will introduce) will be +excluded, replaced with URIS. The mechanism for exclusion is as follows: + + * blob: exclude blob object. + * tree: exclude tree object, blobs that the tree list, and recursive into sub-trees. + * commit: exclude commit object, and recursively exclude all the reachable trees + (ditto tree exclusion) and blobs it contains. + * tag: exclude tag object itself, and the dereference commit (ditto commit exclusion) + if the tag is annotated. Configuration compatibility ------------- -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 13/14] t5702: add tag exclusion test case 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (11 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 12/14] packfile-uri.txt: " Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 14/14] pack-objects.c: introduce `want_exclude_object` function Teng Long 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- t/t5702-protocol-v2.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 5ad52e0cee..09683ebfdc 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -1142,6 +1142,24 @@ test_expect_success 'commit-exclusion: part of packfile response provided as URI http_child/.git/objects/pack/*.idx >filelist && test_line_count = 4 filelist ' +test_expect_success 'tag-exclusion: part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + git -C "$P" tag -a -m "annotated_tag" tagA && + tagObj=$(git -C "$P" rev-parse tagA) && + configure_exclusion tag "$P" "$tagObj" >h2 && + git init http_child && + GIT_TRACE=1 GIT_TRACE_PACKET=`pwd`/log GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child \ + -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch --tags "$HTTPD_URL/smart/http_parent" +' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v5 14/14] pack-objects.c: introduce `want_exclude_object` function 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (12 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 13/14] t5702: add tag exclusion test case Teng Long @ 2021-08-25 2:21 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long 14 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-08-25 2:21 UTC (permalink / raw) To: gitster, dyroneteng; +Cc: avarab, git, jonathantanmy Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 52 ++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index d5e3f2c229..503f8a5746 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1206,6 +1206,21 @@ static int match_packfile_uri_exclusions(struct configured_exclusion *ex) return 0; } +static int want_exclude_object(struct object_list *objects) +{ + struct object_list *p; + struct configured_exclusion *ex; + + if (!objects) + return 0; + for (p = objects; p; p = p->next) { + ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(ex)) + return 1; + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1317,11 +1332,8 @@ static int want_object_in_pack(const struct object_id *oid, int want; struct list_head *pos; struct multi_pack_index *m; - struct configured_exclusion *tag_ex; struct configured_exclusion *commit_ex; - struct configured_exclusion *tree_ex; struct configured_exclusion *ex; - struct object_list *p; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1357,41 +1369,27 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - if (referred_objs && referred_objs->tags) { - for (p = referred_objs->tags; p; p = p->next) { - tag_ex = oidmap_get(&configured_exclusions, &p->item->oid); - if (match_packfile_uri_exclusions(tag_ex)) + if (referred_objs) { + if (referred_objs->commit) { + struct commit *commit = (struct commit *) referred_objs->commit; + commit_ex = oidmap_get(&configured_exclusions, &commit->object.oid); + if (match_packfile_uri_exclusions(commit_ex)) return 0; - } - } - - if (referred_objs && referred_objs->commit) { - commit_ex = oidmap_get(&configured_exclusions, &referred_objs->commit->oid); - if (match_packfile_uri_exclusions(commit_ex)) - return 0; - struct commit *commit = (struct commit*) referred_objs->commit; - for (p = commit->wraps; p; p = p->next) { - tag_ex = oidmap_get(&configured_exclusions, &p->item->oid); - if (match_packfile_uri_exclusions(tag_ex)) + if (want_exclude_object(commit->wraps)) return 0; } - } + if (referred_objs->tags && want_exclude_object(referred_objs->tags)) + return 0; - if (referred_objs && referred_objs->trees) { - for (p = referred_objs->trees; p; p = p->next) { - tree_ex = oidmap_get(&configured_exclusions, &p->item->oid); - if (match_packfile_uri_exclusions(tree_ex)) - return 0; - } + if (referred_objs->trees && want_exclude_object(referred_objs->trees)) + return 0; } - ex = oidmap_get(&configured_exclusions, oid); if (match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; } } - return 1; } -- 2.31.1.456.gec51e24953 ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 00/12] packfile-uri: support excluding multiple object types 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long ` (13 preceding siblings ...) 2021-08-25 2:21 ` [PATCH v5 14/14] pack-objects.c: introduce `want_exclude_object` function Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 01/12] objects.c: introduce `exclude_level` enum Teng Long ` (11 more replies) 14 siblings, 12 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long About This Patch: ----------------- This patch has almost no reuse of previous patch's commits, because this one redesigned the exclusion for various object types and reoganized the commits. Commit (1): objects.c: introduce `exclude_level` enum This commit introduce a new enum named `exclude_level` in object.c, it contains three enumerated values: "ET_SELF", "ET_INCLUDE" and "ET_REACHABLE". The commit only makes the definitions, without any implementations. Commit (2): Introduce function `match_packfile_uri_exclusions` This one move the codes used for matching the URI protocols from `want_found_object` to new function `match_packfile_uri_exclusions`. The purpose is to improve code readability related to the feature and make preparation for further extension about the matching and exclusion for multiple object types. Commit (3): Replace `show_data` with structure `show_info` There is no feature related codes in this commit. This commit modified the parameters in function `show_object` by replacing `show_data` with a new structure `show_info`, this is another way of implementation about the previous commit[1] in patch v5. Commit (4): Introduce `uploadpack.excludeobject` configuration This commit introduce a new and backward-compatible configuration named `uploadpack.excludeobject`, the diff between old and new: uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri> uploadpack.excludeobject=<object-hash> <level> <pack-hash> <uri> The <level> is correspond to the exclusion scope of the given object, and it's mentioned as `exclude_value` in object.c by "Commit (1)". Commit (6,8,10): Implementations for excluding commits, trees and tags Commit (7,9,11): Tests for excluding excluding commits, trees and tags Commit (12): Corresponding documentation modifications bundle-uri And packfile-uri ---------------------------- Ævar Arnfjörð Bjarmason post a new feature patchset[2] named "bundle-uri", it supports to let client download the full or incremental bundles directly without any negotiations with the server (full clone first and in a MVP progress now). I'm sorry if I misleading the meanings and please point it out. In "packfile-uri", different with "bundle-uri", happens in the span of packing objects during git-upload-pack on the server. This is an experimental feature, originally designed as a CDN for large BLOB objects, but it's not yet fully functional. I'm currently working on it for making it support other types of objects. I also noticed that some opinions about the two features are mentioned in the patch[2], so I cc to Stolee in this patch, I hope I did not disturb you. [1] https://public-inbox.org/git/xmqqlf4oc4u1.fsf@gitster.g/ [2] https://lore.kernel.org/git/RFC-cover-00.13-0000000000-20210805T150534Z-avarab@gmail.com/ Teng Long (12): objects.c: introduce `exclude_level` enum Introduce function `match_packfile_uri_exclusions` Replace `show_data` with structure `show_info` Introduce `uploadpack.excludeobject` configuration t5702: test cases for `uploadpack.excludeobject` packfile-uri: support for excluding commits t5702: test cases for excluding commits packfile-uri: support for excluding trees t5702: test cases for excluding trees packfile-uri: support for excluding tags t5702: test cases for excluding tags packfile-uri.txt: support multiple object types Documentation/technical/packfile-uri.txt | 74 +- builtin/describe.c | 9 +- builtin/pack-objects.c | 236 +++++-- builtin/rev-list.c | 11 +- bundle.c | 5 +- list-objects.c | 74 +- list-objects.h | 11 +- object.c | 21 +- object.h | 16 +- pack-bitmap.c | 16 +- reachable.c | 11 +- revision.c | 47 +- revision.h | 12 + shallow.c | 4 +- t/t5702-protocol-v2.sh | 856 +++++++++++++++++++++-- upload-pack.c | 7 + 16 files changed, 1253 insertions(+), 157 deletions(-) Range-diff against v5: 1: 3a885678c9 = 1: 3a885678c9 objects.c: introduce `exclude_level` enum 2: 36426b4d9f = 2: 36426b4d9f Introduce function `match_packfile_uri_exclusions` 3: dced036f89 = 3: dced036f89 Replace `show_data` with structure `show_info` 4: b1d779b26a = 4: b1d779b26a Introduce `uploadpack.excludeobject` configuration 5: f643db3c71 = 5: f643db3c71 t5702: test cases for `uploadpack.excludeobject` 6: c29efeac21 = 6: c29efeac21 packfile-uri: support for excluding commits 7: ca72efd22e = 7: ca72efd22e t5702: test cases for excluding commits 8: c7a885ebec = 8: c7a885ebec packfile-uri: support for excluding trees 9: 5fc79a9a32 = 9: 5fc79a9a32 t5702: test cases for excluding trees 10: 16c41c40a2 = 10: 16c41c40a2 packfile-uri: support for excluding tags 11: 171ece533b = 11: 171ece533b t5702: test cases for excluding tags 12: 79fc2c23cf = 12: 79fc2c23cf packfile-uri.txt: support multiple object types -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH v6 01/12] objects.c: introduce `exclude_level` enum 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 02/12] Introduce function `match_packfile_uri_exclusions` Teng Long ` (10 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> Currently packfile-uri supports the exclusion of blob objects, but in some scenarios, users may wish to exclude more types of objects, such as commits, trees and tags, the difference with blob is they are more complicated. In addition to the meaning of a single object itself, it may also represent a collection of the objects that it includes (trees and blob in a root-tree) or reaches (ancestors of a commit). The exclusion range is designed by an enum named `exclude_level` in "pack-objects.c" that enumerate three values, "ET_SELF", "ET_INCLUDE" and "ET_REACHABLE". Here are some explanations for their differences: - Scene 1: "ET_SELF" for excluding object itself. Reason to support the "ET_SELF" is because the definition of exclusion-level should be better to be consistent, no matter what the object type is. Excluding a single object itself has meaning for blobs, because blob is the smallest granularity among object types, and indeed, sometimes there are some frequently used big-size blobs in repository. If you want to exclude more ownership or reachable objects, it can be considered to use "ET_INCLUDE" or "ET_REACHABLE". - Scene 2: "ET_INCLUDE" for excluding object itself and objects it contains. When a commit is specified to be excluded as packfile-uri, more offen, it's hoped to exclude the trees and blobs contained in its top-level tree, as well as the commit itself, but not the ancestors of the commit. This applies to scenarios where we want to exclude a specified non-blob object that includes some big-size objects. Commit, tag and tree are suitable for this scenario. When a tag is specified, it will exclude the dereference commit, and all trees and blobs contained in its top-tree, as well as the tag itself if it's not a lightweight one. - Scene 3: "ET_REACHABLE" for excluding object itself, all the objects it contains, and its ancestors. For further exclusion range, the ancestors are needed to excluded together, for example, the clone scenes. This commit only defines the `exclude_level` enum type. The implementations of non-blob object types will be added in subsequent commits. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6d13cd3e1a..73b92a0c90 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -127,9 +127,52 @@ enum missing_action { }; static enum missing_action arg_missing_action; static show_object_fn fn_show_object; +/* + * exclude_level defines how to make the exclusion when the object matches + * a packfile-uri (uploadpack.excludeobject or uploadpack.blobpackfileuri) + * configuration. + * + * - ET_SELF; + * This type means only the object itself will be excluded, and all other + * objects it includes or reachable will not. For example, if object type is: + * - BLOB: The blob object will be excluded + * - TREE: The tree object will be excluded, the sub-trees and blobs it + * includes will not be excluded. + * - COMMIT: The commit object will be excluded, all the trees and blobs + * that be included in its top-level tree will not be excluded. + * - TAG: TAG object will be excluded, the referrenced commit object will + * not be excluded. + * - ET_INCLUDE; + * This type means that not only the object itself will be excluded, but + * also the objects it includes. For example, if object type is: + * - BLOB: Same with 'ET_SELF' + * - TREE: The tree object, and also the sub-trees and blobs that + * the object includes will be excluded. + * - COMMIT: The commit object, and also all the trees and blobs + * contained in its top-level tree will be excluded. + * - TAG: The TAG object will be excluded, and also the referrenced + * commit will be excluded (the referrenced commit exclusion will + * treat as a 'ET_INCLUDE' way). + * - ET_REACHABLE; + * This type means that not only the object and all the objects it includes + * will be excluded, but also the reachable objects. For exmple, if object + * type is: + * - BLOB: Same with 'ET_INCLUDE' + * - TREE: Same with 'ET_INCLUDE' + * - COMMIT: The Objects in the case of 'ET_INCLUDE' will be excluded, + * and also the ancestors of the commit will be excluded. + * - TAG: The Objects in the case of 'ET_INCLUDE' will be excluded, and + * also the ancestors of the referrenced commit will be excluded. + */ +enum exclude_level { + ET_SELF, + ET_INCLUDE, + ET_REACHABLE, +}; struct configured_exclusion { struct oidmap_entry e; + int level; char *pack_hash_hex; char *uri; }; @@ -3003,6 +3046,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) if (oidmap_get(&configured_exclusions, &ex->e.oid)) die(_("object already configured in another " "uploadpack.blobpackfileuri (got '%s')"), v); + ex->level = ET_SELF; ex->pack_hash_hex = xcalloc(1, pack_end - oid_end); memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1); ex->uri = xstrdup(pack_end + 1); -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 02/12] Introduce function `match_packfile_uri_exclusions` 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long 2021-10-19 11:38 ` [PATCH v6 01/12] objects.c: introduce `exclude_level` enum Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 03/12] Replace `show_data` with structure `show_info` Teng Long ` (9 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> The matching codes now placed in function `want_object_in_pack`, move it to a new function `match_packfile_uri_exclusions` to prevent subsequent modifications caused by its continuing expansion. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 73b92a0c90..17053dc85a 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1231,6 +1231,24 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int match_packfile_uri_exclusions(struct configured_exclusion *ex) +{ + int i; + const char *p; + + if (ex) { + for (i = 0; i < uri_protocols.nr; i++) { + if (skip_prefix(ex->uri, + uri_protocols.items[i].string, + &p) && + *p == ':') + return 1; + + } + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1378,19 +1396,10 @@ static int want_object_in_pack(const struct object_id *oid, if (uri_protocols.nr) { struct configured_exclusion *ex = oidmap_get(&configured_exclusions, oid); - int i; - const char *p; - if (ex) { - for (i = 0; i < uri_protocols.nr; i++) { - if (skip_prefix(ex->uri, - uri_protocols.items[i].string, - &p) && - *p == ':') { - oidset_insert(&excluded_by_config, oid); - return 0; - } - } + if (ex && match_packfile_uri_exclusions(ex)) { + oidset_insert(&excluded_by_config, oid); + return 0; } } -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 03/12] Replace `show_data` with structure `show_info` 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long 2021-10-19 11:38 ` [PATCH v6 01/12] objects.c: introduce `exclude_level` enum Teng Long 2021-10-19 11:38 ` [PATCH v6 02/12] Introduce function `match_packfile_uri_exclusions` Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 04/12] Introduce `uploadpack.excludeobject` configuration Teng Long ` (8 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> During the pack-objects process, "show_object" function will be called to find and show the object the function contains three parameters: 1. struct object *obj 2. const char *name 3. void *show_data This commit replace "show_data" with with a new structure `show_info`, it has two members: 1. void *show_data 2. void *show_cache The `show_data` in `show_info `is the same purpose with the original one, is the callback when showing the objects. The `show_cache` is the cache that ownership the relationship data. It stores around the extra data for showing the objects, for example, carry the ownership relationship between blob or tree objects and the referred commit to avoid redundant and expensive calculations. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/describe.c | 9 +++++---- builtin/pack-objects.c | 23 +++++++++++++---------- builtin/rev-list.c | 11 ++++++----- bundle.c | 5 +++-- list-objects.c | 29 +++++++++++++++++++++++------ list-objects.h | 11 ++++++++--- pack-bitmap.c | 16 +++++++++------- reachable.c | 11 +++++++---- shallow.c | 4 ++-- 9 files changed, 76 insertions(+), 43 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 40482d8e9f..a6a9e64fb0 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -479,15 +479,16 @@ struct process_commit_data { struct rev_info *revs; }; -static void process_commit(struct commit *commit, void *data) +static void process_commit(struct commit *commit, struct show_info *info) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = info->show_data; pcd->current_commit = commit->object.oid; } -static void process_object(struct object *obj, const char *path, void *data) +static void process_object(struct object *obj, const char *path, + struct show_info *info) { - struct process_commit_data *pcd = data; + struct process_commit_data *pcd = info->show_data; if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { reset_revision_walk(); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 17053dc85a..a41a0a3ea7 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3106,13 +3106,13 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; } -static void show_commit_pack_hint(struct commit *commit, void *_data) +static void show_commit_pack_hint(struct commit *commit, struct show_info *info) { /* nothing to do; commits don't have a namehash */ } static void show_object_pack_hint(struct object *object, const char *name, - void *_data) + struct show_info *info) { struct object_entry *oe = packlist_find(&to_pack, &object->oid); if (!oe) @@ -3284,7 +3284,7 @@ static void read_object_list_from_stdin(void) /* Remember to update object flag allocation in object.h */ #define OBJECT_ADDED (1u<<20) -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, struct show_info *info) { add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); commit->object.flags |= OBJECT_ADDED; @@ -3296,7 +3296,8 @@ static void show_commit(struct commit *commit, void *data) propagate_island_marks(commit); } -static void show_object(struct object *obj, const char *name, void *data) +static void show_object(struct object *obj, const char *name, + struct show_info *info) { add_preferred_base_object(name); add_object_entry(&obj->oid, obj->type, name, 0); @@ -3318,7 +3319,8 @@ static void show_object(struct object *obj, const char *name, void *data) } } -static void show_object__ma_allow_any(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_any(struct object *obj, const char *name, + struct show_info *info) { assert(arg_missing_action == MA_ALLOW_ANY); @@ -3329,10 +3331,11 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void if (!has_object(the_repository, &obj->oid, 0)) return; - show_object(obj, name, data); + show_object(obj, name, info); } -static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data) +static void show_object__ma_allow_promisor(struct object *obj, const char *name, + struct show_info *info) { assert(arg_missing_action == MA_ALLOW_PROMISOR); @@ -3343,7 +3346,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name, if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid)) return; - show_object(obj, name, data); + show_object(obj, name, info); } static int option_parse_missing_action(const struct option *opt, @@ -3591,12 +3594,12 @@ static int get_object_list_from_bitmap(struct rev_info *revs) static void record_recent_object(struct object *obj, const char *name, - void *data) + struct show_info *info) { oid_array_append(&recent_objects, &obj->oid); } -static void record_recent_commit(struct commit *commit, void *data) +static void record_recent_commit(struct commit *commit, struct show_info *info) { oid_array_append(&recent_objects, &commit->object.oid); } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index b4d8ea0a35..116d8d39f1 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -94,9 +94,9 @@ static off_t get_object_disk_usage(struct object *obj) } static void finish_commit(struct commit *commit); -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, struct show_info *s_info) { - struct rev_list_info *info = data; + struct rev_list_info *info = s_info->show_data; struct rev_info *revs = info->revs; display_progress(progress, ++progress_counter); @@ -266,12 +266,13 @@ static int finish_object(struct object *obj, const char *name, void *cb_data) return 0; } -static void show_object(struct object *obj, const char *name, void *cb_data) +static void show_object(struct object *obj, const char *name, + struct show_info *s_info) { - struct rev_list_info *info = cb_data; + struct rev_list_info *info = s_info->show_data; struct rev_info *revs = info->revs; - if (finish_object(obj, name, cb_data)) + if (finish_object(obj, name, info)) return; display_progress(progress, ++progress_counter); if (show_disk_usage) diff --git a/bundle.c b/bundle.c index 693d619551..d4c71ee2b4 100644 --- a/bundle.c +++ b/bundle.c @@ -437,9 +437,9 @@ struct bundle_prerequisites_info { int fd; }; -static void write_bundle_prerequisites(struct commit *commit, void *data) +static void write_bundle_prerequisites(struct commit *commit, struct show_info *info) { - struct bundle_prerequisites_info *bpi = data; + struct bundle_prerequisites_info *bpi = info->show_data; struct object *object; struct pretty_print_context ctx = { 0 }; struct strbuf buf = STRBUF_INIT; @@ -530,6 +530,7 @@ int create_bundle(struct repository *r, const char *path, die("revision walk setup failed"); bpi.fd = bundle_fd; bpi.pending = &revs_copy.pending; + traverse_commit_list(&revs, write_bundle_prerequisites, NULL, &bpi); object_array_remove_duplicates(&revs_copy.pending); diff --git a/list-objects.c b/list-objects.c index e19589baa0..bffce67dd8 100644 --- a/list-objects.c +++ b/list-objects.c @@ -29,6 +29,10 @@ static void process_blob(struct traversal_context *ctx, struct object *obj = &blob->object; size_t pathlen; enum list_objects_filter_result r; + struct show_info show_info; + + show_info.show_data = ctx->show_data; + show_info.show_cache = NULL; if (!ctx->revs->blob_objects) return; @@ -60,7 +64,7 @@ static void process_blob(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, path->buf, ctx->show_data); + ctx->show_object(obj, path->buf, &show_info); strbuf_setlen(path, pathlen); } @@ -154,10 +158,14 @@ static void process_tree(struct traversal_context *ctx, { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; + struct show_info show_info; int baselen = base->len; enum list_objects_filter_result r; int failed_parse; + show_info.show_data = ctx->show_data; + show_info.show_cache = NULL; + if (!revs->tree_objects) return; if (!obj) @@ -191,7 +199,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); + ctx->show_object(obj, base->buf, &show_info); if (base->len) strbuf_addch(base, '/'); @@ -207,8 +215,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) - ctx->show_object(obj, base->buf, ctx->show_data); - + ctx->show_object(obj, base->buf, &show_info); strbuf_setlen(base, baselen); free_tree_buffer(tree); } @@ -322,8 +329,12 @@ static void add_pending_tree(struct rev_info *revs, struct tree *tree) static void traverse_trees_and_blobs(struct traversal_context *ctx, struct strbuf *base) { + struct show_info show_info; int i; + show_info.show_data = ctx->show_data; + show_info.show_cache = NULL; + assert(base->len == 0); for (i = 0; i < ctx->revs->pending.nr; i++) { @@ -335,7 +346,7 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - ctx->show_object(obj, name, ctx->show_data); + ctx->show_object(obj, name, &show_info); continue; } if (!path) @@ -358,8 +369,13 @@ static void do_traverse(struct traversal_context *ctx) { struct commit *commit; struct strbuf csp; /* callee's scratch pad */ + struct show_info show_info; strbuf_init(&csp, PATH_MAX); + + show_info.show_data = ctx->show_data; + show_info.show_cache = NULL; + while ((commit = get_revision(ctx->revs)) != NULL) { /* * an uninteresting boundary commit may not have its tree @@ -375,7 +391,8 @@ static void do_traverse(struct traversal_context *ctx) die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); } - ctx->show_commit(commit, ctx->show_data); + + ctx->show_commit(commit, &show_info); if (ctx->revs->tree_blobs_in_commit_order) /* diff --git a/list-objects.h b/list-objects.h index a952680e46..c7b61e9e10 100644 --- a/list-objects.h +++ b/list-objects.h @@ -5,9 +5,14 @@ struct commit; struct object; struct rev_info; -typedef void (*show_commit_fn)(struct commit *, void *); -typedef void (*show_object_fn)(struct object *, const char *, void *); -void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *); +struct show_info { + void *show_data; /* the data necessary for showing the object */ + void *show_cache; /* the cache ownership relationship data for showing the object */ +}; + +typedef void (*show_commit_fn)(struct commit *, struct show_info *); +typedef void (*show_object_fn)(struct object *, const char *, struct show_info *); +void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *show_data); typedef void (*show_edge_fn)(struct commit *); void mark_edges_uninteresting(struct rev_info *revs, diff --git a/pack-bitmap.c b/pack-bitmap.c index 3ed15431cd..0dcfa5b50e 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -459,9 +459,10 @@ struct bitmap_show_data { struct bitmap *base; }; -static void show_object(struct object *object, const char *name, void *data_) +static void show_object(struct object *object, const char *name, + struct show_info *info) { - struct bitmap_show_data *data = data_; + struct bitmap_show_data *data = info->show_data; int bitmap_pos; bitmap_pos = bitmap_position(data->bitmap_git, &object->oid); @@ -473,7 +474,7 @@ static void show_object(struct object *object, const char *name, void *data_) bitmap_set(data->base, bitmap_pos); } -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, struct show_info *info) { } @@ -628,6 +629,7 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git, show_data.bitmap_git = bitmap_git; show_data.base = base; + traverse_commit_list_filtered(filter, revs, show_commit, show_object, &show_data, NULL); @@ -1268,9 +1270,9 @@ struct bitmap_test_data { }; static void test_show_object(struct object *object, const char *name, - void *data) + struct show_info *info) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = info->show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid); @@ -1281,9 +1283,9 @@ static void test_show_object(struct object *object, const char *name, display_progress(tdata->prg, ++tdata->seen); } -static void test_show_commit(struct commit *commit, void *data) +static void test_show_commit(struct commit *commit, struct show_info *info) { - struct bitmap_test_data *tdata = data; + struct bitmap_test_data *tdata = info->show_data; int bitmap_pos; bitmap_pos = bitmap_position(tdata->bitmap_git, diff --git a/reachable.c b/reachable.c index 77a60c70a5..4f78954c62 100644 --- a/reachable.c +++ b/reachable.c @@ -47,14 +47,15 @@ static int add_one_ref(const char *path, const struct object_id *oid, * The traversal will have already marked us as SEEN, so we * only need to handle any progress reporting here. */ -static void mark_object(struct object *obj, const char *name, void *data) +static void mark_object(struct object *obj, const char *name, + struct show_info *info) { - update_progress(data); + update_progress(info->show_data); } -static void mark_commit(struct commit *c, void *data) +static void mark_commit(struct commit *c, struct show_info *info) { - mark_object(&c->object, NULL, data); + mark_object(&c->object, NULL, info); } struct recent_data { @@ -230,6 +231,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog, return; } + /* * Set up the revision walk - this will move all commits * from the pending list to the commit walking list. @@ -244,6 +246,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog, die("unable to mark recent objects"); if (prepare_revision_walk(revs)) die("revision walk setup failed"); + traverse_commit_list(revs, mark_commit, mark_object, &cp); } diff --git a/shallow.c b/shallow.c index 9ed18eb884..ab1e49eba4 100644 --- a/shallow.c +++ b/shallow.c @@ -185,9 +185,9 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth, return result; } -static void show_commit(struct commit *commit, void *data) +static void show_commit(struct commit *commit, struct show_info *info) { - commit_list_insert(commit, data); + commit_list_insert(commit, info->show_data); } /* -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 04/12] Introduce `uploadpack.excludeobject` configuration 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (2 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 03/12] Replace `show_data` with structure `show_info` Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 05/12] t5702: test cases for `uploadpack.excludeobject` Teng Long ` (7 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> Background: The `uploadpack.blobpackfileuri` is made for the "packfile-uri" feature, the feature is similar to a CDN cache, it supports the client to download pack file by a URI directly, without or reducing the server load when make packing and transporting. Reasons: First reason, `uploadpack.blobpackfileuri` supports to exclude a single object, but actually the object type can be not only a blob, so the name is inaccurate currently. Secondly, the name of the old configuration is not abstract enough, this make the furthur extension difficult. If do not change its name, to let different object types use different configuration names, the configuration items will be bloated and difficult to maintain, so the new configuration is more abstract in name. Configuation format diff: old: uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri> new: uploadpack.excludeobject=<object-hash> <level> <pack-hash> <uri> The new configuration `uploadpack.excludeobject` not only supports to exclude a single object itself, but also to exclude related objects with it at once, the scope of exclusion is determined by the object type and the specified `<level>` value in the entry. -Compatibility: Although a new configuration has been introduced, the old one is available to use and compatible with the new configuration. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 33 ++++++++++++++++++++++++++++++++- upload-pack.c | 7 +++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index a41a0a3ea7..75461483c0 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3061,6 +3061,36 @@ static int git_pack_config(const char *k, const char *v, void *cb) ex->uri = xstrdup(pack_end + 1); oidmap_put(&configured_exclusions, ex); } + if (!strcmp(k, "uploadpack.excludeobject")) { + struct configured_exclusion *ex = xmalloc(sizeof(*ex)); + const char *oid_end, *pack_end, *type_end; + struct object_id pack_hash; + char type[2]; + int level; + + if (parse_oid_hex(v, &ex->e.oid, &oid_end) || + *oid_end != ' ' || + !strlcpy(type, oid_end + 1, sizeof(type)) || + parse_oid_hex(oid_end + 3, &pack_hash, &pack_end) || + *pack_end != ' ') + die(_("value of uploadpack.excludeobject must be " + "of the form '<object-hash> <level> <pack-hash> <uri>' (got '%s')"), v); + if (oidmap_get(&configured_exclusions, &ex->e.oid)) + die(_("object already configured by an earlier " + "uploadpack.excludeobject (got '%s')"), v); + + level = atoi(type); + if (level < ET_SELF || level > ET_REACHABLE) { + die(_("value of <level> must be 0 or 1 or 2 (got '%s')"), v); + } + ex->level = level; + type_end = oid_end + 2; + ex->pack_hash_hex = xcalloc(1, pack_end - type_end); + memcpy(ex->pack_hash_hex, type_end + 1, pack_end - type_end - 1); + ex->uri = xstrdup(pack_end + 1); + oidmap_put(&configured_exclusions, ex); + } + return git_default_config(k, v, cb); } @@ -3887,7 +3917,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("respect islands during delta compression")), OPT_STRING_LIST(0, "uri-protocol", &uri_protocols, N_("protocol"), - N_("exclude any configured uploadpack.blobpackfileuri with this protocol")), + N_("exclude any configured uploadpack.excludeobject or " + "uploadpack.blobpackfileuri with this protocol")), OPT_END(), }; diff --git a/upload-pack.c b/upload-pack.c index 5c1cd19612..d26fb351a3 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1751,6 +1751,13 @@ int upload_pack_advertise(struct repository *r, strbuf_addstr(value, " packfile-uris"); free(str); } + + if (!repo_config_get_string(the_repository, + "uploadpack.excludeobject", + &str) && str) { + strbuf_addstr(value, " packfile-uris"); + free(str); + } } return 1; -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 05/12] t5702: test cases for `uploadpack.excludeobject` 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (3 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 04/12] Introduce `uploadpack.excludeobject` configuration Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 06/12] packfile-uri: support for excluding commits Teng Long ` (6 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long This commit expends the function `configure_exclusion` to support new excluding type: commit, tree and tag. Signed-off-by: Teng Long <tenglong@alibaba-inc.com> --- t/t5702-protocol-v2.sh | 146 +++++++++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 48 deletions(-) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 2e1243ca40..ccd3678311 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -824,17 +824,63 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' ' configure_exclusion () { - git -C "$1" hash-object "$2" >objh && - git -C "$1" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && - git -C "$1" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - cat objh + objt="$1" + P="$2" + oid="$3" + version="$4" + excluding_type="$5" + + oldc="uploadpack.blobpackfileuri" + newc="uploadpack.excludeobject" + configkey="" + + if test "$version" = "old" + then + configkey="$oldc" + else + configkey="$newc" + fi + + if test "$objt" = "blob" + then + excluding_type="0" + git -C "$P" hash-object "$oid" >objh && + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && + if test "$version" = "old" + then + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" + else + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $excluding_type $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" + fi && + cat objh + elif test "$objt" = "commit" || test "$objt" = "tree" || test "$objt" = "tag" + then + echo "$oid" >objh && + if test "$excluding_type" = "0" + then + git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + else + git -C "$P" pack-objects --revs "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh + fi && + + git -C "$P" config --add \ + "$configkey" \ + "$(cat objh) $excluding_type $(cat packh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && + cat objh + else + echo "unsupported object type in configure_exclusion (got $objt)" + fi } -test_expect_success 'part of packfile response provided as URI' ' +part_of_packfile_response_verify() { + + config="$1" && P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log *found" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -843,10 +889,10 @@ test_expect_success 'part of packfile response provided as URI' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && - configure_exclusion "$P" other-blob >h2 && + configure_exclusion blob "$P" my-blob "$config" >h && + configure_exclusion blob "$P" other-blob "$config" >h2 && GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ @@ -879,20 +925,22 @@ test_expect_success 'part of packfile response provided as URI' ' ls http_child/.git/objects/pack/*.pack \ http_child/.git/objects/pack/*.idx >filelist && test_line_count = 6 filelist -' +} + +blobpackfileuri_fetch () { + config="$1" -test_expect_success 'packfile URIs with fetch instead of clone' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && + test_commit -C "$P" A && - configure_exclusion "$P" my-blob >h && + configure_exclusion blob "$P" my-blob $config >h && git init http_child && @@ -900,12 +948,28 @@ test_expect_success 'packfile URIs with fetch instead of clone' ' git -C http_child -c protocol.version=2 \ -c fetch.uriprotocols=http,https \ fetch "$HTTPD_URL/smart/http_parent" +} + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): part of packfile response provided as URI' ' + rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + part_of_packfile_response_verify old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): part of packfile response provided as URI' ' + part_of_packfile_response_verify new +' + +test_expect_success 'blob-exclusion (using uploadpack.blobpackfileuri): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch old +' + +test_expect_success 'blob-exclusion (using uploadpack.excludeobject): packfile URIs with fetch instead of clone' ' + blobpackfileuri_fetch new ' test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && - + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -913,9 +977,8 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" add my-blob && echo other-blob >"$P/other-blob" && git -C "$P" add other-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && # Configure a URL for other-blob. Just reuse the hash of the object as # the hash of the packfile, since the hash does not matter for this # test as long as it is not the hash of the pack, and it is of the @@ -923,9 +986,8 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -C "$P" hash-object other-blob >objh && git -C "$P" pack-objects "$HTTPD_DOCUMENT_ROOT_PATH/mypack" <objh >packh && git -C "$P" config --add \ - "uploadpack.blobpackfileuri" \ - "$(cat objh) $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && - + "uploadpack.excludeobject" \ + "$(cat objh) 0 $(cat objh) $HTTPD_URL/dumb/mypack-$(cat packh).pack" && test_must_fail env GIT_TEST_SIDEBAND_ALL=1 \ git -c protocol.version=2 \ -c fetch.uriprotocols=http,https \ @@ -935,17 +997,14 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' test_expect_success 'packfile-uri with transfer.fsckobjects' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && - + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && - + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ @@ -959,8 +1018,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects' ' test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child log && - + test_when_finished "rm -rf \"$P\" http_child log" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -976,10 +1034,8 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' echo my-blob >"$P/my-blob" && git -C "$P" add my-blob && - git -C "$P" commit -m x && - - configure_exclusion "$P" my-blob >h && - + test_commit -C "$P" A && + configure_exclusion blob "$P" my-blob >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ @@ -989,8 +1045,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child && - + test_when_finished "rm -rf \"$P\" http_child" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -999,9 +1054,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && git -C "$P" commit -m x && - - configure_exclusion "$P" .gitmodules >h && - + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ @@ -1015,8 +1068,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmo test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodules separate from tree is invalid' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && - rm -rf "$P" http_child err && - + test_when_finished "rm -rf \"$P\" http_child err" && git init "$P" && git -C "$P" config "uploadpack.allowsidebandall" "true" && @@ -1024,10 +1076,8 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul echo "path = include/foo" >>"$P/.gitmodules" && echo "url = git://example.com/git/lib.git" >>"$P/.gitmodules" && git -C "$P" add .gitmodules && - git -C "$P" commit -m x && - - configure_exclusion "$P" .gitmodules >h && - + test_commit -C "$P" A && + configure_exclusion blob "$P" .gitmodules >h && sane_unset GIT_TEST_SIDEBAND_ALL && test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ @@ -1038,4 +1088,4 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul # DO NOT add non-httpd-specific tests here, because the last part of this # test script is only executed when httpd is available and enabled. -test_done +test_done \ No newline at end of file -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 06/12] packfile-uri: support for excluding commits 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (4 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 05/12] t5702: test cases for `uploadpack.excludeobject` Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 07/12] t5702: test cases " Teng Long ` (5 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> This commit work on the exlusion of commit objects, and the Its excluding `level` can be configured as "ET_SELF", "ET_INCLUDE" or "ET_REACHABLE". Exclusion scope on different level: 1. When a commit is specified to be excluded with level "ET_SELF", only the commit object itself will be excluded. 2. When it's specified to be excluded with level "ET_INCLUDE", exclude all trees and blobs contained in its top-level tree, as well as the commit itself. 3. When it is specified with level "ET_REACHABLE", exclude its ancestors, as well as the objects need to be excluded under the level "ET_INCLUDED". Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 83 +++++++++++++++++++++++++++++++++--------- list-objects.c | 37 +++++++++++-------- object.c | 19 ++++++++-- object.h | 14 ++++++- revision.c | 34 ++++++++++++----- revision.h | 3 ++ 6 files changed, 144 insertions(+), 46 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 75461483c0..e7b27ef443 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -36,6 +36,7 @@ #include "trace2.h" #include "shallow.h" #include "promisor-remote.h" +#include "commit-reach.h" #define IN_PACK(obj) oe_in_pack(&to_pack, obj) #define SIZE(obj) oe_size(&to_pack, obj) @@ -1354,11 +1355,14 @@ static int want_object_in_pack_one(struct packed_git *p, static int want_object_in_pack(const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + struct referred_objects *referred_objs) { int want; struct list_head *pos; struct multi_pack_index *m; + struct configured_exclusion *ex; + struct configured_exclusion *commit_ex; if (!exclude && local && has_loose_object_nonlocal(oid)) return 0; @@ -1394,9 +1398,16 @@ static int want_object_in_pack(const struct object_id *oid, } if (uri_protocols.nr) { - struct configured_exclusion *ex = - oidmap_get(&configured_exclusions, oid); + if (referred_objs) { + struct commit *commit = referred_objs->commit; + if (commit) { + commit_ex = oidmap_get(&configured_exclusions, &commit->object.oid); + if (match_packfile_uri_exclusions(commit_ex) && commit_ex->level > ET_SELF) + return 0; + } + } + ex = oidmap_get(&configured_exclusions, oid); if (ex && match_packfile_uri_exclusions(ex)) { oidset_insert(&excluded_by_config, oid); return 0; @@ -1436,7 +1447,8 @@ static const char no_closure_warning[] = N_( ); static int add_object_entry(const struct object_id *oid, enum object_type type, - const char *name, int exclude) + const char *name, int exclude, + struct referred_objects *referred_objs) { struct packed_git *found_pack = NULL; off_t found_offset = 0; @@ -1446,7 +1458,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, if (have_duplicate_entry(oid, exclude)) return 0; - if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) { + if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset, referred_objs)) { /* The pack is missing an object, so it will not have closure */ if (write_bitmap_index) { if (write_bitmap_index != WRITE_BITMAP_QUIET) @@ -1472,7 +1484,7 @@ static int add_object_entry_from_bitmap(const struct object_id *oid, if (have_duplicate_entry(oid, 0)) return 0; - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack(oid, 0, &pack, &offset, NULL)) return 0; create_object_entry(oid, type, name_hash, 0, 0, pack, offset); @@ -1612,7 +1624,7 @@ static void add_pbase_object(struct tree_desc *tree, if (name[cmplen] != '/') { add_object_entry(&entry.oid, object_type(entry.mode), - fullname, 1); + fullname, 1, NULL); return; } if (S_ISDIR(entry.mode)) { @@ -1680,7 +1692,7 @@ static void add_preferred_base_object(const char *name) cmplen = name_cmp_len(name); for (it = pbase_tree; it; it = it->next) { if (cmplen == 0) { - add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1); + add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1, NULL); } else { struct tree_desc tree; @@ -2882,7 +2894,7 @@ static void add_tag_chain(const struct object_id *oid) die(_("unable to pack objects reachable from tag %s"), oid_to_hex(oid)); - add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0); + add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0, NULL); if (tag->tagged->type != OBJ_TAG) return; @@ -3050,8 +3062,6 @@ static int git_pack_config(const char *k, const char *v, void *cb) *oid_end != ' ' || parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) || *pack_end != ' ') - die(_("value of uploadpack.blobpackfileuri must be " - "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v); if (oidmap_get(&configured_exclusions, &ex->e.oid)) die(_("object already configured in another " "uploadpack.blobpackfileuri (got '%s')"), v); @@ -3114,7 +3124,7 @@ static int add_object_entry_from_pack(const struct object_id *oid, return 0; ofs = nth_packed_object_offset(p, pos); - if (!want_object_in_pack(oid, 0, &p, &ofs)) + if (!want_object_in_pack(oid, 0, &p, &ofs, NULL)) return 0; oi.typep = &type; @@ -3307,7 +3317,7 @@ static void read_object_list_from_stdin(void) die(_("expected object ID, got garbage:\n %s"), line); add_preferred_base_object(p + 1); - add_object_entry(&oid, OBJ_NONE, p + 1, 0); + add_object_entry(&oid, OBJ_NONE, p + 1, 0, NULL); } } @@ -3316,7 +3326,7 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, struct show_info *info) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0); + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) @@ -3329,8 +3339,9 @@ static void show_commit(struct commit *commit, struct show_info *info) static void show_object(struct object *obj, const char *name, struct show_info *info) { + struct referred_objects *referred_objs = info->show_cache; add_preferred_base_object(name); - add_object_entry(&obj->oid, obj->type, name, 0); + add_object_entry(&obj->oid, obj->type, name, 0, referred_objs); obj->flags |= OBJECT_ADDED; if (use_delta_islands) { @@ -3483,7 +3494,7 @@ static void add_objects_in_unpacked_packs(void) QSORT(in_pack.array, in_pack.nr, ofscmp); for (i = 0; i < in_pack.nr; i++) { struct object *o = in_pack.array[i].object; - add_object_entry(&o->oid, o->type, "", 0); + add_object_entry(&o->oid, o->type, "", 0, NULL); } } free(in_pack.array); @@ -3499,7 +3510,7 @@ static int add_loose_object(const struct object_id *oid, const char *path, return 0; } - add_object_entry(oid, type, "", 0); + add_object_entry(oid, type, "", 0, NULL); return 0; } @@ -3665,6 +3676,42 @@ static void mark_bitmap_preferred_tips(void) } } +static void reuse_exclusion_packfile(struct rev_info *revs) +{ + struct commit *commit; + struct oidmap_iter iter; + struct configured_exclusion *ex; + struct object_id ex_oid; + struct commit *ex_commit; + struct commit_list *list = revs->commits; + struct commit_list *newlist = NULL; + struct commit_list **p = &newlist; + + if (revs->limited) + return; + while (list) { + commit = pop_commit(&list); + if (commit_list_contains(commit, newlist)) { + continue; + } + p = commit_list_append(commit, p); + oidmap_iter_init(&configured_exclusions, &iter); + while ((ex = oidmap_iter_next(&iter)) && ex->level == ET_REACHABLE) { + ex_oid = ex->e.oid; + ex_commit = lookup_commit_reference(the_repository, &ex_oid); + if (!ex_commit) + die("Not a valid commit name %s", oid_to_hex(&ex_oid)); + if (!in_merge_bases(ex_commit, commit)) + continue; + oidset_insert(&excluded_by_config, &ex_oid); + ex_commit->object.flags |= UNINTERESTING; + p = commit_list_append(ex_commit, p); + break; + } + } + revs->commits = newlist; +} + static void get_object_list(int ac, const char **av) { struct rev_info revs; @@ -3726,6 +3773,8 @@ static void get_object_list(int ac, const char **av) die(_("revision walk setup failed")); mark_edges_uninteresting(&revs, show_edge, sparse); + reuse_exclusion_packfile(&revs); + if (!fn_show_object) fn_show_object = show_object; traverse_commit_list_filtered(&filter_options, &revs, diff --git a/list-objects.c b/list-objects.c index bffce67dd8..b32213ecf1 100644 --- a/list-objects.c +++ b/list-objects.c @@ -24,7 +24,8 @@ struct traversal_context { static void process_blob(struct traversal_context *ctx, struct blob *blob, struct strbuf *path, - const char *name) + const char *name, + struct referred_objects *referred_obj) { struct object *obj = &blob->object; size_t pathlen; @@ -32,7 +33,7 @@ static void process_blob(struct traversal_context *ctx, struct show_info show_info; show_info.show_data = ctx->show_data; - show_info.show_cache = NULL; + show_info.show_cache = referred_obj; if (!ctx->revs->blob_objects) return; @@ -101,11 +102,13 @@ static void process_gitlink(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name); + const char *name, + struct referred_objects *referred_objs); static void process_tree_contents(struct traversal_context *ctx, struct tree *tree, - struct strbuf *base) + struct strbuf *base, + struct referred_objects *referred_objs) { struct tree_desc desc; struct name_entry entry; @@ -133,7 +136,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path); + process_tree(ctx, t, base, entry.path, referred_objs); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -146,7 +149,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path); + process_blob(ctx, b, base, entry.path, referred_objs); } } } @@ -154,7 +157,8 @@ static void process_tree_contents(struct traversal_context *ctx, static void process_tree(struct traversal_context *ctx, struct tree *tree, struct strbuf *base, - const char *name) + const char *name, + struct referred_objects *referred_objs) { struct object *obj = &tree->object; struct rev_info *revs = ctx->revs; @@ -163,9 +167,6 @@ static void process_tree(struct traversal_context *ctx, enum list_objects_filter_result r; int failed_parse; - show_info.show_data = ctx->show_data; - show_info.show_cache = NULL; - if (!revs->tree_objects) return; if (!obj) @@ -196,6 +197,9 @@ static void process_tree(struct traversal_context *ctx, LOFS_BEGIN_TREE, obj, base->buf, &base->buf[baselen], ctx->filter); + show_info.show_cache = referred_objs; + show_info.show_data = ctx->show_data; + if (r & LOFR_MARK_SEEN) obj->flags |= SEEN; if (r & LOFR_DO_SHOW) @@ -206,7 +210,7 @@ static void process_tree(struct traversal_context *ctx, if (r & LOFR_SKIP_TREE) trace_printf("Skipping contents of tree %s...\n", base->buf); else if (!failed_parse) - process_tree_contents(ctx, tree, base); + process_tree_contents(ctx, tree, base, referred_objs); r = list_objects_filter__filter_object(ctx->revs->repo, LOFS_END_TREE, obj, @@ -321,9 +325,9 @@ void mark_edges_uninteresting(struct rev_info *revs, } } -static void add_pending_tree(struct rev_info *revs, struct tree *tree) +static void add_pending_tree(struct rev_info *revs, struct tree *tree, struct commit *referred_commit) { - add_pending_object(revs, &tree->object, ""); + add_pending_object_with_referred_commit(revs, &tree->object, "", referred_commit); } static void traverse_trees_and_blobs(struct traversal_context *ctx, @@ -340,6 +344,7 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; + struct referred_objects *referred_objs = pending->referred_objects; const char *name = pending->name; const char *path = pending->path; if (obj->flags & (UNINTERESTING | SEEN)) @@ -352,11 +357,11 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, if (!path) path = ""; if (obj->type == OBJ_TREE) { - process_tree(ctx, (struct tree *)obj, base, path); + process_tree(ctx, (struct tree *)obj, base, path, referred_objs); continue; } if (obj->type == OBJ_BLOB) { - process_blob(ctx, (struct blob *)obj, base, path); + process_blob(ctx, (struct blob *)obj, base, path, referred_objs); continue; } die("unknown pending object %s (%s)", @@ -386,7 +391,7 @@ static void do_traverse(struct traversal_context *ctx) else if (get_commit_tree(commit)) { struct tree *tree = get_commit_tree(commit); tree->object.flags |= NOT_USER_GIVEN; - add_pending_tree(ctx->revs, tree); + add_pending_tree(ctx->revs, tree, commit); } else if (commit->object.parsed) { die(_("unable to load root tree for commit %s"), oid_to_hex(&commit->object.oid)); diff --git a/object.c b/object.c index 14188453c5..f86b52c4d6 100644 --- a/object.c +++ b/object.c @@ -322,14 +322,18 @@ void object_list_free(struct object_list **list) */ static char object_array_slopbuf[1]; -void add_object_array_with_path(struct object *obj, const char *name, - struct object_array *array, - unsigned mode, const char *path) +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path, + struct commit *referred_commit) { unsigned nr = array->nr; unsigned alloc = array->alloc; struct object_array_entry *objects = array->objects; struct object_array_entry *entry; + struct referred_objects *referred_objs; + referred_objs = xmalloc(sizeof(struct referred_objects)); + referred_objs->commit = referred_commit; if (nr >= alloc) { alloc = (alloc + 32) * 2; @@ -339,6 +343,7 @@ void add_object_array_with_path(struct object *obj, const char *name, } entry = &objects[nr]; entry->item = obj; + entry->referred_objects = referred_objs; if (!name) entry->name = NULL; else if (!*name) @@ -354,6 +359,13 @@ void add_object_array_with_path(struct object *obj, const char *name, array->nr = ++nr; } +void add_object_array_with_path(struct object *obj, const char *name, + struct object_array *array, + unsigned mode, const char *path) +{ + add_object_array_with_path_and_referred_commit(obj, name, array, mode, path, NULL); +} + void add_object_array(struct object *obj, const char *name, struct object_array *array) { add_object_array_with_path(obj, name, array, S_IFINVALID, NULL); @@ -368,6 +380,7 @@ static void object_array_release_entry(struct object_array_entry *ent) if (ent->name != object_array_slopbuf) free(ent->name); free(ent->path); + free(ent->referred_objects); } struct object *object_array_pop(struct object_array *array) diff --git a/object.h b/object.h index 87a6da47c8..4db0ecc3f2 100644 --- a/object.h +++ b/object.h @@ -52,9 +52,20 @@ struct object_array { char *name; char *path; unsigned mode; + /* + * referred_objects or NULL. If non-NULL, it will + * temporary storage the referred objects when + * traversing the specified object. Space for time, + * reduce related computing costs (such as packfile-uri + * exclusion), clean up when the traversal is over. + */ + struct referred_objects *referred_objects; } *objects; }; +struct referred_objects{ + struct commit *commit; +}; #define OBJECT_ARRAY_INIT { 0, 0, NULL } /* @@ -157,7 +168,8 @@ void object_list_free(struct object_list **list); /* Object array handling .. */ void add_object_array(struct object *obj, const char *name, struct object_array *array); void add_object_array_with_path(struct object *obj, const char *name, struct object_array *array, unsigned mode, const char *path); - +void add_object_array_with_path_and_referred_commit(struct object *obj, const char *name, struct object_array *array, + unsigned mode, const char *path, struct commit *referred_commit); /* * Returns NULL if the array is empty. Otherwise, returns the last object * after removing its entry from the array. Other resources associated diff --git a/revision.c b/revision.c index 4853c85d0b..89a8b311ea 100644 --- a/revision.c +++ b/revision.c @@ -304,10 +304,11 @@ void mark_parents_uninteresting(struct commit *commit) commit_stack_clear(&pending); } -static void add_pending_object_with_path(struct rev_info *revs, - struct object *obj, - const char *name, unsigned mode, - const char *path) +static void add_pending_object_with_path_and_referred_commit(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path, + struct commit *referred_commit) { struct interpret_branch_name_options options = { 0 }; if (!obj) @@ -326,20 +327,35 @@ static void add_pending_object_with_path(struct rev_info *revs, strbuf_release(&buf); return; /* do not add the commit itself */ } - add_object_array_with_path(obj, name, &revs->pending, mode, path); + add_object_array_with_path_and_referred_commit(obj, name, &revs->pending, mode, path, referred_commit); } +static void add_pending_object_with_path(struct rev_info *revs, + struct object *obj, + const char *name, unsigned mode, + const char *path) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, path, NULL); +} static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, - const char *name, unsigned mode) + const char *name, unsigned mode, + struct commit *referred_commit) +{ + add_pending_object_with_path_and_referred_commit(revs, obj, name, mode, NULL, referred_commit); +} + +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct commit *referred_commit) { - add_pending_object_with_path(revs, obj, name, mode, NULL); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, referred_commit); } void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { - add_pending_object_with_mode(revs, obj, name, S_IFINVALID); + add_pending_object_with_mode(revs, obj, name, S_IFINVALID, NULL); } void add_head_to_pending(struct rev_info *revs) @@ -2817,7 +2833,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc)) diagnose_missing_default(revs->def); object = get_reference(revs, revs->def, &oid, 0); - add_pending_object_with_mode(revs, object, revs->def, oc.mode); + add_pending_object_with_mode(revs, object, revs->def, oc.mode, NULL); } /* Did the user ask for any diff output? Run the diff! */ diff --git a/revision.h b/revision.h index a24f72dcd1..b2e0c0b9b7 100644 --- a/revision.h +++ b/revision.h @@ -423,6 +423,9 @@ void show_object_with_name(FILE *, struct object *, const char *); */ void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); +void add_pending_object_with_referred_commit(struct rev_info *revs, + struct object *obj, const char *name, + struct commit *referred_commit); void add_pending_oid(struct rev_info *revs, const char *name, const struct object_id *oid, -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 07/12] t5702: test cases for excluding commits 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (5 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 06/12] packfile-uri: support for excluding commits Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 08/12] packfile-uri: support for excluding trees Teng Long ` (4 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long Signed-off-by: Teng Long <tenglong@alibaba-inc.com> --- t/t5702-protocol-v2.sh | 300 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index ccd3678311..6e323253f7 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -967,6 +967,306 @@ test_expect_success 'blob-exclusion (using uploadpack.excludeobject): packfile U blobpackfileuri_fetch new ' +test_expect_success 'commit-exclusion(excluding_type=ET_SELF): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="0" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/my-tree/sub-tree && + echo sub-blob >"$P"/my-tree/sub-tree/sub-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD my-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + subblobh=$(git -C "$P" hash-object my-tree/sub-tree/sub-blob) && + configure_exclusion commit "$P" "$commith" new "$excluding_type" >h && + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child +' + +test_expect_success 'commit-exclusion(excluding_type=ET_INCLUDE): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="1" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/my-tree/sub-tree && + echo sub-blob >"$P"/my-tree/sub-tree/sub-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD my-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + subblobh=$(git -C "$P" hash-object my-tree/sub-tree/sub-blob) && + configure_exclusion commit "$P" "$commith" new "$excluding_type" >h && + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 7 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi && + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + # Ensure that there are exactly 2 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + +test_expect_success 'commit-exclusion(excluding_type=ET_REACHABLE): hitten a full packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="2" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + configure_exclusion commit "$P" "$commith" new "$excluding_type" >h && + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 5 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + elif test_line_count = 0 out.objectlist + then + >emptypackfound + fi + done && + test -f emptypackfound && + test -f mytreehfound && + test -f myblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + # Ensure that there are exactly 2 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + +test_expect_success 'commit-exclusion(excluding_type=ET_REACHABLE): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="2" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + git -C "$P" add other-tree && + test_commit -C "$P" B && + ah=$(git -C "$P" hash-object A.t) && + bh=$(git -C "$P" hash-object B.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + rm -rf "$P"/my-tree "$P"/other-tree "$P"/A.t "$P"/B.t && + mkdir "$P"/another-tree && + echo another-blob >"$P"/another-tree/another-blob && + git -C "$P" add . && + test_commit -C "$P" C && + commitAh=$(git -C "$P" rev-parse A) && + commitBh=$(git -C "$P" rev-parse B) && + commitCh=$(git -C "$P" rev-parse C) && + roottreeAh=$(git -C "$P" rev-parse A:) && + roottreeBh=$(git -C "$P" rev-parse B:) && + roottreeCh=$(git -C "$P" rev-parse C:) && + mytreeh=$(git -C "$P" ls-tree A my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree B other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + anothertreeh=$(git -C "$P" ls-tree C another-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ch=$(git -C "$P" hash-object C.t) && + anotherblobh=$(git -C "$P" hash-object another-tree/another-blob) && + configure_exclusion commit "$P" "$commitBh" new "$excluding_type" >h && + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 5 out.objectlist + then + if grep $commitCh out + then + >commitChfound + fi && + if grep $roottreeCh out + then + >roottreeChfound + fi && + if grep $anothertreeh out + then + >anothertreehfound + fi && + if grep $anotherblobh out + then + >anotherblobhfound + fi && + if grep $ch out + then + >chfound + fi + elif test_line_count = 10 out.objectlist + then + if grep $commitAh out + then + >commitAhfound + fi && + if grep $commitBh out + then + >commitBhfound + fi && + if grep $roottreeAh out + then + >roottreeAhfound + fi && + if grep $roottreeBh out + then + >roottreeBhfound + fi && + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $othertreeh out + then + >othertreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi && + if grep $otherblobh out + then + >otherblobhfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $bh out + then + >bhfound + fi + fi + done && + test -f commitChfound && + test -f roottreeChfound && + test -f anothertreehfound && + test -f anotherblobhfound && + test -f chfound && + test -f commitAhfound && + test -f commitBhfound && + test -f roottreeAhfound && + test -f roottreeBhfound && + test -f mytreehfound && + test -f othertreehfound && + test -f myblobhfound && + test -f otherblobhfound && + test -f ahfound && + test -f bhfound && + # Ensure that there are exactly 2 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_when_finished "rm -rf \"$P\" http_child log" && -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 08/12] packfile-uri: support for excluding trees 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (6 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 07/12] t5702: test cases " Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 09/12] t5702: test cases " Teng Long ` (3 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> This commit introduce the exclusion of tree objects. The exclusion range is designed by an enum named `exclude_level` in "pack-objects.c" that enumerate three values, "ET_SELF", "ET_INCLUDE" and "ET_REACHABLE". Exclusion scope on different level: 1. When a tree is specified to be excluded with level "ET_SELF", only the tree object itself will be excluded. 2. When a tree specified to be excluded with level "ET_INCLUDE", exclude the tree itself, as well as all the trees and blobs it contains. 3. When it is specified with level "ET_REACHABLE", the excluding scope is as same as level "ET_INCLUDE", because tree do not have any ancestors. Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 18 ++++++++++++++++++ list-objects.c | 8 ++++++-- object.c | 1 + object.h | 1 + 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index e7b27ef443..6713e734fb 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1250,6 +1250,21 @@ static int match_packfile_uri_exclusions(struct configured_exclusion *ex) return 0; } +static int want_exclude_object(struct object_list *objects) +{ + struct object_list *p; + struct configured_exclusion *ex; + + if (!objects) + return 0; + for (p = objects; p; p = p->next) { + ex = oidmap_get(&configured_exclusions, &p->item->oid); + if (match_packfile_uri_exclusions(ex) && ex->level > ET_SELF) + return 1; + } + return 0; +} + static int want_found_object(const struct object_id *oid, int exclude, struct packed_git *p) { @@ -1400,11 +1415,14 @@ static int want_object_in_pack(const struct object_id *oid, if (uri_protocols.nr) { if (referred_objs) { struct commit *commit = referred_objs->commit; + struct object_list *trees = referred_objs->trees; if (commit) { commit_ex = oidmap_get(&configured_exclusions, &commit->object.oid); if (match_packfile_uri_exclusions(commit_ex) && commit_ex->level > ET_SELF) return 0; } + if (want_exclude_object(trees)) + return 0; } ex = oidmap_get(&configured_exclusions, oid); diff --git a/list-objects.c b/list-objects.c index b32213ecf1..40292e2cc8 100644 --- a/list-objects.c +++ b/list-objects.c @@ -114,8 +114,11 @@ static void process_tree_contents(struct traversal_context *ctx, struct name_entry entry; enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ? all_entries_interesting : entry_not_interesting; + struct referred_objects *referred_buf; init_tree_desc(&desc, tree->buffer, tree->size); + referred_buf = xmemdupz(referred_objs, sizeof(struct referred_objects)); + object_list_insert(&tree->object, &referred_buf->trees); while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { @@ -136,7 +139,7 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } t->object.flags |= NOT_USER_GIVEN; - process_tree(ctx, t, base, entry.path, referred_objs); + process_tree(ctx, t, base, entry.path, referred_buf); } else if (S_ISGITLINK(entry.mode)) process_gitlink(ctx, entry.oid.hash, @@ -149,9 +152,10 @@ static void process_tree_contents(struct traversal_context *ctx, entry.path, oid_to_hex(&tree->object.oid)); } b->object.flags |= NOT_USER_GIVEN; - process_blob(ctx, b, base, entry.path, referred_objs); + process_blob(ctx, b, base, entry.path, referred_buf); } } + free(referred_buf); } static void process_tree(struct traversal_context *ctx, diff --git a/object.c b/object.c index f86b52c4d6..895068cbc2 100644 --- a/object.c +++ b/object.c @@ -334,6 +334,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch struct referred_objects *referred_objs; referred_objs = xmalloc(sizeof(struct referred_objects)); referred_objs->commit = referred_commit; + referred_objs->trees = NULL; if (nr >= alloc) { alloc = (alloc + 32) * 2; diff --git a/object.h b/object.h index 4db0ecc3f2..618d674249 100644 --- a/object.h +++ b/object.h @@ -65,6 +65,7 @@ struct object_array { struct referred_objects{ struct commit *commit; + struct object_list *trees; }; #define OBJECT_ARRAY_INIT { 0, 0, NULL } -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 09/12] t5702: test cases for excluding trees 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (7 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 08/12] packfile-uri: support for excluding trees Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 10/12] packfile-uri: support for excluding tags Teng Long ` (2 subsequent siblings) 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long Signed-off-by: Teng Long <tenglong@alibaba-inc.com> --- t/t5702-protocol-v2.sh | 213 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 6e323253f7..762a9c2505 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -1267,6 +1267,219 @@ test_expect_success 'commit-exclusion(excluding_type=ET_REACHABLE): part of pack test_line_count = 4 filelist ' +test_expect_success 'tree-exclusion(excluding_type=ET_SELF): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="0" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + # Dir struct + # . + # |-- A.t + # |-- my-tree + # | `-- my-blob + # `-- other-tree + # |-- other-blob + # `-- sub-tree + # `-- sub-blob + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + mkdir "$P"/other-tree/sub-tree && + echo sub-blob >"$P"/other-tree/sub-tree/sub-blob && + git -C "$P" add other-tree && + test_commit -C "$P" A && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree HEAD other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD other-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + subblobh=$(git -C "$P" hash-object other-tree/sub-tree/sub-blob) && + + configure_exclusion tree "$P" "$mytreeh" new 0 >h && + configure_exclusion tree "$P" "$othertreeh" new 0 >h2 && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && +# Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 1 out.objectlist + then + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $othertreeh out + then + >othertreehfound + fi + elif test_line_count = 7 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $myblobh out + then + >myblobhfound + fi && + if grep $otherblobh out + then + >otherblobhfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f othertreehfound && + test -f otherblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 6 filelist +' + +test_expect_success 'tree-exclusion(excluding_type=ET_INCLUDE), part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log *found" && + excluding_type="1" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + # Dir struct + # . + # |-- A.t + # |-- my-tree + # | `-- my-blob + # `-- other-tree + # |-- other-blob + # `-- sub-tree + # `-- sub-blob + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + mkdir "$P"/other-tree/sub-tree && + echo sub-blob >"$P"/other-tree/sub-tree/sub-blob && + git -C "$P" add other-tree && + test_commit -C "$P" A && + + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree HEAD other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + subtreeh=$(git -C "$P" ls-tree HEAD other-tree/sub-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + subblobh=$(git -C "$P" hash-object other-tree/sub-tree/sub-blob) && + + configure_exclusion tree "$P" "$mytreeh" new $excluding_type >h && + configure_exclusion tree "$P" "$othertreeh" new $excluding_type >h2 && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 3 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi + elif test_line_count = 2 out.objectlist + then + if grep $mytreeh out + then + >mytreehfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + elif test_line_count = 4 out.objectlist + then + if grep $othertreeh out + then + >othertreehfound + fi && + if grep $otherblobh out + then + >otherblobhfound + fi && + if grep $subtreeh out + then + >subtreehfound + fi && + if grep $subblobh out + then + >subblobhfound + fi + fi + done && + test -f mytreehfound && + test -f myblobhfound && + test -f othertreehfound && + test -f otherblobhfound && + test -f subtreehfound && + test -f subblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 6 filelist +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_when_finished "rm -rf \"$P\" http_child log" && -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 10/12] packfile-uri: support for excluding tags 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (8 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 09/12] t5702: test cases " Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 11/12] t5702: test cases " Teng Long 2021-10-19 11:38 ` [PATCH v6 12/12] packfile-uri.txt: support multiple object types Teng Long 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long From: Teng Long <dyroneteng@gmail.com> This commit brings the tags exclusion feature of packfile-uri. The excluding level of tag is supported with "ET_SELF", "ET_INCLUDE" and "ET_REACHABLE". Exclusion scope on different level: 1. When a tag is specified to be excluded with level "ET_SELF", only the tag object itself will be excluded. 2. When it's specified to be excluded with level "ET_INCLUDE", exclude the referenced commit, and all trees and blobs contained in its top-level. If it's a annotated tag, the tag object will be excluded too. 3. When it is specified with level "ET_REACHABLE", exclude the ancestors of the referenced commit, as well as the objects need to be excluded under the level "ET_INCLUDED". Signed-off-by: Teng Long <dyroneteng@gmail.com> --- builtin/pack-objects.c | 6 +++++- list-objects.c | 20 ++++++++++++++++---- object.c | 1 + object.h | 1 + revision.c | 13 ++++++++++++- revision.h | 9 +++++++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6713e734fb..073c3815a1 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1416,6 +1416,9 @@ static int want_object_in_pack(const struct object_id *oid, if (referred_objs) { struct commit *commit = referred_objs->commit; struct object_list *trees = referred_objs->trees; + struct object_list *tags = referred_objs->tags; + if (want_exclude_object(tags)) + return 0; if (commit) { commit_ex = oidmap_get(&configured_exclusions, &commit->object.oid); if (match_packfile_uri_exclusions(commit_ex) && commit_ex->level > ET_SELF) @@ -3344,7 +3347,8 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, struct show_info *info) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); + struct referred_objects *referred_objs = info->show_cache; + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, referred_objs); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) diff --git a/list-objects.c b/list-objects.c index 40292e2cc8..2e241e8707 100644 --- a/list-objects.c +++ b/list-objects.c @@ -348,9 +348,10 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; - struct referred_objects *referred_objs = pending->referred_objects; const char *name = pending->name; const char *path = pending->path; + struct referred_objects *referred_objs = pending->referred_objects; + struct commit_wraps_entry *cw_entry = NULL; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { @@ -358,6 +359,10 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, ctx->show_object(obj, name, &show_info); continue; } + if (referred_objs->commit) + cw_entry = oidmap_get(ctx->revs->commit_wraps, &referred_objs->commit->object.oid); + if (cw_entry) + referred_objs->tags = cw_entry->wraps; if (!path) path = ""; if (obj->type == OBJ_TREE) { @@ -378,12 +383,14 @@ static void do_traverse(struct traversal_context *ctx) { struct commit *commit; struct strbuf csp; /* callee's scratch pad */ - struct show_info show_info; + struct commit_wraps_entry *entry; + struct oidmap *commit_wraps = ctx->revs->commit_wraps; + struct referred_objects referred_objs = { NULL, NULL, NULL }; + struct show_info show_info = { ctx->show_data , NULL }; strbuf_init(&csp, PATH_MAX); - show_info.show_data = ctx->show_data; - show_info.show_cache = NULL; + show_info.show_cache = &referred_objs; while ((commit = get_revision(ctx->revs)) != NULL) { /* @@ -401,6 +408,11 @@ static void do_traverse(struct traversal_context *ctx) oid_to_hex(&commit->object.oid)); } + if (commit_wraps) { + entry = oidmap_get(commit_wraps, &commit->object.oid); + referred_objs.tags = entry ? entry->wraps : NULL; + } + ctx->show_commit(commit, &show_info); if (ctx->revs->tree_blobs_in_commit_order) diff --git a/object.c b/object.c index 895068cbc2..167cc87ec9 100644 --- a/object.c +++ b/object.c @@ -335,6 +335,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch referred_objs = xmalloc(sizeof(struct referred_objects)); referred_objs->commit = referred_commit; referred_objs->trees = NULL; + referred_objs->tags = NULL; if (nr >= alloc) { alloc = (alloc + 32) * 2; diff --git a/object.h b/object.h index 618d674249..42a2178531 100644 --- a/object.h +++ b/object.h @@ -66,6 +66,7 @@ struct object_array { struct referred_objects{ struct commit *commit; struct object_list *trees; + struct object_list *tags; }; #define OBJECT_ARRAY_INIT { 0, 0, NULL } diff --git a/revision.c b/revision.c index 89a8b311ea..d16f9bbbb9 100644 --- a/revision.c +++ b/revision.c @@ -416,14 +416,17 @@ static struct commit *handle_commit(struct rev_info *revs, const char *path = entry->path; unsigned int mode = entry->mode; unsigned long flags = object->flags; + struct object_list *wraps = NULL; /* * Tag object? Look what it points to.. */ while (object->type == OBJ_TAG) { struct tag *tag = (struct tag *) object; - if (revs->tag_objects && !(flags & UNINTERESTING)) + if (revs->tag_objects && !(flags & UNINTERESTING)) { add_pending_object(revs, object, tag->tag); + object_list_insert(object, &wraps); + } object = parse_object(revs->repo, get_tagged_oid(tag)); if (!object) { if (revs->ignore_missing_links || (flags & UNINTERESTING)) @@ -449,6 +452,14 @@ static struct commit *handle_commit(struct rev_info *revs, */ if (object->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)object; + struct oidmap *commit_wraps = malloc(sizeof(struct oidmap)); + struct commit_wraps_entry *cw_entry = xmalloc(sizeof(struct commit_wraps_entry)); + + oidmap_init(commit_wraps, 0); + cw_entry->e.oid = object->oid; + cw_entry->wraps = wraps; + oidmap_put(commit_wraps, cw_entry); + revs->commit_wraps = commit_wraps; if (repo_parse_commit(revs->repo, commit) < 0) die("unable to parse commit %s", name); diff --git a/revision.h b/revision.h index b2e0c0b9b7..a633ea2174 100644 --- a/revision.h +++ b/revision.h @@ -8,6 +8,7 @@ #include "pretty.h" #include "diff.h" #include "commit-slab-decl.h" +#include "oidmap.h" /** * The revision walking API offers functions to build a list of revisions @@ -64,6 +65,11 @@ struct bloom_key; struct bloom_filter_settings; define_shared_commit_slab(revision_sources, char *); +struct commit_wraps_entry { + struct oidmap_entry e; + struct object_list *wraps; +}; + struct rev_cmdline_info { unsigned int nr; unsigned int alloc; @@ -321,6 +327,9 @@ struct rev_info { /* misc. flags related to '--no-kept-objects' */ unsigned keep_pack_cache_flags; + + /* The commit_wraps caches the referred wrapped objects(such as tags) of a commit */ + struct oidmap *commit_wraps; }; int ref_excluded(struct string_list *, const char *path); -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 11/12] t5702: test cases for excluding tags 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (9 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 10/12] packfile-uri: support for excluding tags Teng Long @ 2021-10-19 11:38 ` Teng Long 2021-10-19 11:38 ` [PATCH v6 12/12] packfile-uri.txt: support multiple object types Teng Long 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long Signed-off-by: Teng Long <tenglong@alibaba-inc.com> --- t/t5702-protocol-v2.sh | 197 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 762a9c2505..f91ae62fd8 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -1480,6 +1480,203 @@ test_expect_success 'tree-exclusion(excluding_type=ET_INCLUDE), part of packfile test_line_count = 6 filelist ' +test_expect_success 'tag-exclusion(excluding_type=ET_SELF): part of packfile response provided as URI' ' + test_when_finished "rm -rf \"$P\" http_child log" && + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + git -C "$P" tag -a -m "annotated_tag" tagA && + + tagh=$(git -C "$P" rev-parse tagA) && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-blob) && + + configure_exclusion tag "$P" "$tagh" new 0 >h2 && + git init http_child && + GIT_TRACE=1 GIT_TRACE_PACKET=`pwd`/log GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child \ + -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch --tags "$HTTPD_URL/smart/http_parent" && + + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 1 out.objectlist + then + if grep $tagh out + then + >taghfound + fi + + elif test_line_count = 4 out.objectlist + then + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + fi + done && + test -f myblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + test -f taghfound && + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + +test_expect_success 'tag-exclusion(excluding_type=ET_INCLUDE): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + echo my-blob >"$P/my-blob" && + git -C "$P" add my-blob && + test_commit -C "$P" A && + git -C "$P" tag -a -m "annotated_tag" tagA && + + tagh=$(git -C "$P" rev-parse tagA) && + commith=$(git -C "$P" rev-parse A) && + roottreeh=$(git -C "$P" rev-parse A:) && + ah=$(git -C "$P" hash-object A.t) && + myblobh=$(git -C "$P" hash-object my-blob) && + + configure_exclusion tag "$P" "$tagh" new 1 >h2 && + + git init http_child && + GIT_TRACE=1 GIT_TRACE_PACKET=`pwd`/log GIT_TEST_SIDEBAND_ALL=1 \ + git -C http_child \ + -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + fetch --tags "$HTTPD_URL/smart/http_parent" && + + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 5 out.objectlist + then + if grep $tagh out + then + >taghfound + fi && + if grep $commith out + then + >commithfound + fi && + if grep $roottreeh out + then + >roottreehfound + fi && + if grep $ah out + then + >ahfound + fi && + if grep $myblobh out + then + >myblobhfound + fi + fi + done && + test -f myblobhfound && + test -f commithfound && + test -f roottreehfound && + test -f ahfound && + test -f taghfound && + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + +test_expect_success 'tag-exclusion(excluding_type=ET_REACHABLE): part of packfile response provided as URI' ' + P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_when_finished "rm -rf \"$P\" http_child log" && + git init "$P" && + git -C "$P" config "uploadpack.allowsidebandall" "true" && + + + mkdir "$P"/my-tree && + echo my-blob >"$P"/my-tree/my-blob && + git -C "$P" add my-tree && + test_commit -C "$P" A && + + mkdir "$P"/other-tree && + echo other-blob >"$P"/other-tree/other-blob && + git -C "$P" add other-tree && + test_commit -C "$P" B && + + git -C "$P" tag -a -m "tag X" tagX && + + tagh=$(git -C "$P" rev-parse tagX) && + commitAh=$(git -C "$P" rev-parse A) && + commitBh=$(git -C "$P" rev-parse B) && + roottreeAh=$(git -C "$P" rev-parse A:) && + roottreeBh=$(git -C "$P" rev-parse B:) && + mytreeh=$(git -C "$P" ls-tree HEAD my-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + othertreeh=$(git -C "$P" ls-tree HEAD other-tree | sed -ne "s/.*\($OID_REGEX\).*/\1/p") && + ah=$(git -C "$P" hash-object A.t) && + bh=$(git -C "$P" hash-object B.t) && + myblobh=$(git -C "$P" hash-object my-tree/my-blob) && + otherblobh=$(git -C "$P" hash-object other-tree/other-blob) && + + configure_exclusion tag "$P" "$tagh" new 2 >h && + + GIT_TRACE=1 GIT_TRACE_PACKET="$(pwd)/log" GIT_TEST_SIDEBAND_ALL=1 \ + git -c protocol.version=2 \ + -c fetch.uriprotocols=http,https \ + clone "$HTTPD_URL/smart/http_parent" http_child && + + # Ensure that my-tree and other-tree and theirs complementary set are in separate packfiles. + for idx in http_child/.git/objects/pack/*.idx + do + git verify-pack --object-format=$(test_oid algo) --verbose $idx >out && + { + grep "^[0-9a-f]\{16,\} " out || : + } >out.objectlist && + if test_line_count = 11 out.objectlist + then + >fullpackfound + elif test_line_count = 0 out.objectlist + then + >emptypackfound + fi + done && + test -f fullpackfound && + test -f emptypackfound && + # Ensure that there are exactly 3 packfiles with associated .idx + ls http_child/.git/objects/pack/*.pack \ + http_child/.git/objects/pack/*.idx >filelist && + test_line_count = 4 filelist +' + test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' P="$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && test_when_finished "rm -rf \"$P\" http_child log" && -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
* [PATCH v6 12/12] packfile-uri.txt: support multiple object types 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long ` (10 preceding siblings ...) 2021-10-19 11:38 ` [PATCH v6 11/12] t5702: test cases " Teng Long @ 2021-10-19 11:38 ` Teng Long 11 siblings, 0 replies; 72+ messages in thread From: Teng Long @ 2021-10-19 11:38 UTC (permalink / raw) To: git Cc: gitster, avarab, jonathantanmy, bagasdotme, adlternative, stolee, Teng Long Signed-off-by: Teng Long <tenglong@alibaba-inc.com> --- Documentation/technical/packfile-uri.txt | 74 ++++++++++++++++++++---- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/Documentation/technical/packfile-uri.txt b/Documentation/technical/packfile-uri.txt index f7eabc6c76..0e6d7c8dda 100644 --- a/Documentation/technical/packfile-uri.txt +++ b/Documentation/technical/packfile-uri.txt @@ -34,14 +34,69 @@ having it advertise `packfile-uris`, tolerating the client sending include some sort of non-trivial implementation in the Minimum Viable Product, at least so that we can test the client. -This is the implementation: a feature, marked experimental, that allows the -server to be configured by one or more `uploadpack.blobPackfileUri=<sha1> -<uri>` entries. Whenever the list of objects to be sent is assembled, all such -blobs are excluded, replaced with URIs. As noted in "Future work" below, the -server can evolve in the future to support excluding other objects (or other -implementations of servers could be made that support excluding other objects) -without needing a protocol change, so clients should not expect that packfiles -downloaded in this way only contain single blobs. +This is the implementation: a feature, marked experimental, that allows +the server to be configured by one or more entries with the format: + + uploadpack.excludeobject=<object-hash> <level> <pack-hash> <uri> + +Value `<object-hash>` is the key of entry, and the object type can be +blob, tree, commit, or tag. Value of entry has three parts, +`<pack-hash>` is used to identify the packfile which contains the given +`<object-hash>` object, and `<uri>` is the URI to download the packfile by +client. For example, When a blob is configured with `uploadpack.excludeobject` +that means whenever the blob to be send is assembled, the object will +be excluded. + +In addition to excluding a single object like blob, sometimes it's +hoped to exclude not only the object itself, but also all the related +objects with it, like all the objects a tree contains or the ancestors +that a commit can reach. In these cases, the `<level>` is designed to +distinguish the scope of exclusion, it supports three levels: + +- Level 0: Excluding a single object itself, without any objects that + have a relationship with it. + +- Level 1: Excluding object itself, and objects it contains. + +- Level 2: Excluding object itself, the objects it contains, and the + ancestors it can reach. + +If `<level>` is configured as 0, only the object itself will be +excluded, no matter what the object type is. It is a common scenario +for large size blobs, but it does much not sense for other object types +(e.g. download a singe commit without downloading the blobs and tree +in it). + +If `<level>` is configured as 1, not only the single object but also all +the objects in it will be excluded. This applies to scenarios where +it's wanted to exclude a specified non-blob object that includes some +lage size objects. + +- If <object-hash> is a blob, the result is the same as level 0, because blob +contains nothing just itself. + +- If <object-hash> is a tree, the tree itself, and all blobs and trees + in it will be excluded. + +- If <object-hash> is a commit, the commit itself, the referenced + root-tree, and all blobs and trees in the root-tree will be excluded. + +- If <object-hash> is a tag, the tag itself, the dereferenced commit + and all trees and blobs contained in its root-tree will be excluded. + +If `<level>` is configured as 2, not only the objects in the scope of +level 1 , but also the reachable ancestors will be excluded if +`<object-hash>` is commit or tag. + +Configuration compatibility +--------------------------- + +The old configuration of packfile-uri: + + uploadpack.blobPackfileUri=<object-hash> <pack-hash> <uri> + +For the old configuration is compatible with the new one, but it only +supports the exclusion of blob objects. Client design ------------- @@ -65,9 +120,6 @@ The protocol design allows some evolution of the server and client without any need for protocol changes, so only a small-scoped design is included here to form the MVP. For example, the following can be done: - * On the server, more sophisticated means of excluding objects (e.g. by - specifying a commit to represent that commit and all objects that it - references). * On the client, resumption of clone. If a clone is interrupted, information could be recorded in the repository's config and a "clone-resume" command can resume the clone in progress. (Resumption of subsequent fetches is more -- 2.31.1.453.g945ddc3a74.dirty ^ permalink raw reply related [flat|nested] 72+ messages in thread
end of thread, other threads:[~2021-10-19 11:40 UTC | newest] Thread overview: 72+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-05-07 2:11 [PATCH] Packfile-uris support excluding commit objects Teng Long 2021-05-10 11:14 ` Ævar Arnfjörð Bjarmason 2021-05-18 8:49 ` [PATCH v2 0/3] packfile-uris: commit objects exclusion Teng Long 2021-05-18 8:49 ` [PATCH v2 1/3] packfile-uris: support for excluding commit object Teng Long 2021-05-19 4:28 ` Junio C Hamano 2021-05-20 4:46 ` Junio C Hamano 2021-05-18 8:49 ` [PATCH v2 2/3] packfile-uris.txt: " Teng Long 2021-05-18 8:49 ` [PATCH v2 3/3] t5702: excluding commits with packfile-uris Teng Long 2021-07-26 9:46 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Teng Long 2021-07-26 9:46 ` [PATCH v3 1/3] packfile-uris: support for excluding commit objects Teng Long 2021-07-26 18:15 ` Junio C Hamano 2021-07-26 19:45 ` Felipe Contreras 2021-08-11 1:44 ` Teng Long 2021-07-26 9:46 ` [PATCH v3 2/3] t5702: " Teng Long 2021-07-26 15:03 ` Ævar Arnfjörð Bjarmason 2021-08-11 1:46 ` [PATCH v3 1/3] packfile-uris: " Teng Long 2021-07-26 9:46 ` [PATCH v3 3/3] packfile-uri.txt: " Teng Long 2021-07-26 20:52 ` Junio C Hamano 2021-08-11 1:47 ` Teng Long 2021-07-26 12:34 ` [PATCH v3 0/3] packfile-uris: commit objects exclusio Ævar Arnfjörð Bjarmason 2021-08-11 1:48 ` Teng Long 2021-08-11 7:45 ` [PATCH v4 0/7] packfile-uris: commits and trees exclusion Teng Long 2021-08-11 7:45 ` [PATCH v4 1/7] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long 2021-08-11 7:45 ` [PATCH v4 2/7] Add new parameter "carry_data" for "show_object" function Teng Long 2021-08-11 7:45 ` [PATCH v4 3/7] packfile-uri: support for excluding commit objects Teng Long 2021-08-11 7:45 ` [PATCH v4 4/7] packfile-uri: support for excluding tree objects Teng Long 2021-08-11 7:45 ` [PATCH v4 5/7] packfile-uri.txt: support for excluding commits and trees Teng Long 2021-08-11 9:59 ` Bagas Sanjaya 2021-08-11 7:45 ` [PATCH v4 6/7] t5702: replace with "test_when_finished" for cleanup Teng Long 2021-08-11 7:45 ` [PATCH v4 7/7] t5702: support for excluding commit objects Teng Long 2021-08-25 2:21 ` [PATCH v5 00/14] packfile-uris: commits, trees and tags exclusion Teng Long 2021-08-25 2:21 ` [PATCH v5 01/14] pack-objects.c: introduce new method `match_packfile_uri_exclusions` Teng Long 2021-08-25 2:21 ` [PATCH v5 02/14] Add new parameter "carry_data" for "show_object" function Teng Long 2021-08-26 20:45 ` Junio C Hamano 2021-09-02 11:08 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 03/14] packfile-uri: support for excluding commit objects Teng Long 2021-08-25 23:49 ` Ævar Arnfjörð Bjarmason 2021-09-02 12:26 ` Teng Long 2021-08-26 20:56 ` Junio C Hamano 2021-09-02 12:51 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 04/14] packfile-uri: support for excluding tree objects Teng Long 2021-08-25 2:21 ` [PATCH v5 05/14] packfile-uri.txt: support for excluding commits and trees Teng Long 2021-08-25 23:52 ` Ævar Arnfjörð Bjarmason 2021-09-02 11:23 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 06/14] t5702: replace with "test_when_finished" for cleanup Teng Long 2021-08-25 23:55 ` Ævar Arnfjörð Bjarmason 2021-09-02 11:37 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 07/14] t5702: support for excluding commit objects Teng Long 2021-08-25 2:21 ` [PATCH v5 08/14] Add new parameter "carry_data" for "show_commit function Teng Long 2021-08-25 2:21 ` [PATCH v5 09/14] commit.h: add wrapped tags in commit struct Teng Long 2021-08-25 23:58 ` Ævar Arnfjörð Bjarmason 2021-09-02 12:17 ` Teng Long 2021-09-02 12:39 ` ZheNing Hu 2021-09-02 13:01 ` Teng Long 2021-08-25 2:21 ` [PATCH v5 10/14] object.h: add referred tags in `referred_objects` struct Teng Long 2021-08-25 2:21 ` [PATCH v5 11/14] packfile-uri: support for excluding tag objects Teng Long 2021-08-25 2:21 ` [PATCH v5 12/14] packfile-uri.txt: " Teng Long 2021-08-25 2:21 ` [PATCH v5 13/14] t5702: add tag exclusion test case Teng Long 2021-08-25 2:21 ` [PATCH v5 14/14] pack-objects.c: introduce `want_exclude_object` function Teng Long 2021-10-19 11:38 ` [PATCH v6 00/12] packfile-uri: support excluding multiple object types Teng Long 2021-10-19 11:38 ` [PATCH v6 01/12] objects.c: introduce `exclude_level` enum Teng Long 2021-10-19 11:38 ` [PATCH v6 02/12] Introduce function `match_packfile_uri_exclusions` Teng Long 2021-10-19 11:38 ` [PATCH v6 03/12] Replace `show_data` with structure `show_info` Teng Long 2021-10-19 11:38 ` [PATCH v6 04/12] Introduce `uploadpack.excludeobject` configuration Teng Long 2021-10-19 11:38 ` [PATCH v6 05/12] t5702: test cases for `uploadpack.excludeobject` Teng Long 2021-10-19 11:38 ` [PATCH v6 06/12] packfile-uri: support for excluding commits Teng Long 2021-10-19 11:38 ` [PATCH v6 07/12] t5702: test cases " Teng Long 2021-10-19 11:38 ` [PATCH v6 08/12] packfile-uri: support for excluding trees Teng Long 2021-10-19 11:38 ` [PATCH v6 09/12] t5702: test cases " Teng Long 2021-10-19 11:38 ` [PATCH v6 10/12] packfile-uri: support for excluding tags Teng Long 2021-10-19 11:38 ` [PATCH v6 11/12] t5702: test cases " Teng Long 2021-10-19 11:38 ` [PATCH v6 12/12] packfile-uri.txt: support multiple object types Teng Long
Code repositories for project(s) associated with this public inbox https://80x24.org/mirrors/git.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).