提交 a0c9016a 编写于 作者: J Jonathan Tan 提交者: Junio C Hamano

upload-pack: send refs' objects despite "filter"

A filter line in a request to upload-pack filters out objects regardless
of whether they are directly referenced by a "want" line or not. This
means that cloning with "--filter=blob:none" (or another filter that
excludes blobs) from a repository with at least one ref pointing to a
blob (for example, the Git repository itself) results in output like the
following:

    error: missing object referenced by 'refs/tags/junio-gpg-pub'

and if that particular blob is not referenced by a fetched tree, the
resulting clone fails fsck because there is no object from the remote to
vouch that the missing object is a promisor object.

Update both the protocol and the upload-pack implementation to include
all explicitly specified "want" objects in the packfile regardless of
the filter specification.
Signed-off-by: NJonathan Tan <jonathantanmy@google.com>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 cf1e7c07
...@@ -284,7 +284,9 @@ information is sent back to the client in the next step. ...@@ -284,7 +284,9 @@ information is sent back to the client in the next step.
The client can optionally request that pack-objects omit various The client can optionally request that pack-objects omit various
objects from the packfile using one of several filtering techniques. objects from the packfile using one of several filtering techniques.
These are intended for use with partial clone and partial fetch These are intended for use with partial clone and partial fetch
operations. See `rev-list` for possible "filter-spec" values. operations. An object that does not meet a filter-spec value is
omitted unless explicitly requested in a 'want' line. See `rev-list`
for possible filter-spec values.
Once all the 'want's and 'shallow's (and optional 'deepen') are Once all the 'want's and 'shallow's (and optional 'deepen') are
transferred, clients MUST send a flush-pkt, to tell the server side transferred, clients MUST send a flush-pkt, to tell the server side
......
...@@ -47,7 +47,7 @@ static void process_blob(struct rev_info *revs, ...@@ -47,7 +47,7 @@ static void process_blob(struct rev_info *revs,
pathlen = path->len; pathlen = path->len;
strbuf_addstr(path, name); strbuf_addstr(path, name);
if (filter_fn) if (!(obj->flags & USER_GIVEN) && filter_fn)
r = filter_fn(LOFS_BLOB, obj, r = filter_fn(LOFS_BLOB, obj,
path->buf, &path->buf[pathlen], path->buf, &path->buf[pathlen],
filter_data); filter_data);
...@@ -132,7 +132,7 @@ static void process_tree(struct rev_info *revs, ...@@ -132,7 +132,7 @@ static void process_tree(struct rev_info *revs,
} }
strbuf_addstr(base, name); strbuf_addstr(base, name);
if (filter_fn) if (!(obj->flags & USER_GIVEN) && filter_fn)
r = filter_fn(LOFS_BEGIN_TREE, obj, r = filter_fn(LOFS_BEGIN_TREE, obj,
base->buf, &base->buf[baselen], base->buf, &base->buf[baselen],
filter_data); filter_data);
...@@ -171,7 +171,7 @@ static void process_tree(struct rev_info *revs, ...@@ -171,7 +171,7 @@ static void process_tree(struct rev_info *revs,
cb_data, filter_fn, filter_data); cb_data, filter_fn, filter_data);
} }
if (filter_fn) { if (!(obj->flags & USER_GIVEN) && filter_fn) {
r = filter_fn(LOFS_END_TREE, obj, r = filter_fn(LOFS_END_TREE, obj,
base->buf, &base->buf[baselen], base->buf, &base->buf[baselen],
filter_data); filter_data);
......
...@@ -27,7 +27,7 @@ struct object_array { ...@@ -27,7 +27,7 @@ struct object_array {
/* /*
* object flag allocation: * object flag allocation:
* revision.h: 0---------10 26 * revision.h: 0---------10 2526
* fetch-pack.c: 0----5 * fetch-pack.c: 0----5
* walker.c: 0-2 * walker.c: 0-2
* upload-pack.c: 4 11----------------19 * upload-pack.c: 4 11----------------19
......
...@@ -172,6 +172,7 @@ static void add_pending_object_with_path(struct rev_info *revs, ...@@ -172,6 +172,7 @@ static void add_pending_object_with_path(struct rev_info *revs,
strbuf_release(&buf); strbuf_release(&buf);
return; /* do not add the commit itself */ return; /* do not add the commit itself */
} }
obj->flags |= USER_GIVEN;
add_object_array_with_path(obj, name, &revs->pending, mode, path); add_object_array_with_path(obj, name, &revs->pending, mode, path);
} }
......
...@@ -19,8 +19,9 @@ ...@@ -19,8 +19,9 @@
#define SYMMETRIC_LEFT (1u<<8) #define SYMMETRIC_LEFT (1u<<8)
#define PATCHSAME (1u<<9) #define PATCHSAME (1u<<9)
#define BOTTOM (1u<<10) #define BOTTOM (1u<<10)
#define USER_GIVEN (1u<<25) /* given directly by the user */
#define TRACK_LINEAR (1u<<26) #define TRACK_LINEAR (1u<<26)
#define ALL_REV_FLAGS (((1u<<11)-1) | TRACK_LINEAR) #define ALL_REV_FLAGS (((1u<<11)-1) | USER_GIVEN | TRACK_LINEAR)
#define DECORATE_SHORT_REFS 1 #define DECORATE_SHORT_REFS 1
#define DECORATE_FULL_REFS 2 #define DECORATE_FULL_REFS 2
......
...@@ -160,6 +160,22 @@ test_expect_success 'verify blob:limit=1k' ' ...@@ -160,6 +160,22 @@ test_expect_success 'verify blob:limit=1k' '
test_cmp observed expected test_cmp observed expected
' '
test_expect_success 'verify explicitly specifying oversized blob in input' '
git -C r2 ls-files -s large.1000 large.10000 \
| awk -f print_2.awk \
| sort >expected &&
git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&
HEAD
$(git -C r2 rev-parse HEAD:large.10000)
EOF
git -C r2 index-pack ../filter.pack &&
git -C r2 verify-pack -v ../filter.pack \
| grep blob \
| awk -f print_1.awk \
| sort >observed &&
test_cmp observed expected
'
test_expect_success 'verify blob:limit=1m' ' test_expect_success 'verify blob:limit=1m' '
git -C r2 ls-files -s large.1000 large.10000 \ git -C r2 ls-files -s large.1000 large.10000 \
| awk -f print_2.awk \ | awk -f print_2.awk \
......
...@@ -154,4 +154,20 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack - ...@@ -154,4 +154,20 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack -
grep "git index-pack.*--fsck-objects" trace grep "git index-pack.*--fsck-objects" trace
' '
test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' '
rm -rf src dst &&
git init src &&
test_commit -C src x &&
test_config -C src uploadpack.allowfilter 1 &&
test_config -C src uploadpack.allowanysha1inwant 1 &&
# Create a tag pointing to a blob.
BLOB=$(echo blob-contents | git -C src hash-object --stdin -w) &&
git -C src tag myblob "$BLOB" &&
git clone --filter="blob:none" "file://$(pwd)/src" dst 2>err &&
! grep "does not point to a valid object" err &&
git -C dst fsck
'
test_done test_done
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册