Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/technical/pack-protocol.txt4
-rw-r--r--builtin/clone.c2
-rw-r--r--list-objects.c6
-rw-r--r--object.h2
-rw-r--r--revision.c1
-rw-r--r--revision.h3
-rwxr-xr-xt/t5317-pack-objects-filter-objects.sh16
-rwxr-xr-xt/t5616-partial-clone.sh64
8 files changed, 91 insertions, 7 deletions
diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt
index 7fee6b780a..508a344cf1 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -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
objects from the packfile using one of several filtering techniques.
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
transferred, clients MUST send a flush-pkt, to tell the server side
diff --git a/builtin/clone.c b/builtin/clone.c
index 2f84717e11..5c439f1394 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1202,7 +1202,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
update_remote_refs(refs, mapped_refs, remote_head_points_at,
branch_top.buf, reflog_msg.buf, transport,
- !is_local && !filter_options.choice);
+ !is_local);
update_head(our_head_points_at, remote_head, reflog_msg.buf);
diff --git a/list-objects.c b/list-objects.c
index 3e5e1992eb..b1f2138c29 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -48,7 +48,7 @@ static void process_blob(struct rev_info *revs,
pathlen = path->len;
strbuf_addstr(path, name);
- if (filter_fn)
+ if (!(obj->flags & USER_GIVEN) && filter_fn)
r = filter_fn(LOFS_BLOB, obj,
path->buf, &path->buf[pathlen],
filter_data);
@@ -133,7 +133,7 @@ static void process_tree(struct rev_info *revs,
}
strbuf_addstr(base, name);
- if (filter_fn)
+ if (!(obj->flags & USER_GIVEN) && filter_fn)
r = filter_fn(LOFS_BEGIN_TREE, obj,
base->buf, &base->buf[baselen],
filter_data);
@@ -172,7 +172,7 @@ static void process_tree(struct rev_info *revs,
cb_data, filter_fn, filter_data);
}
- if (filter_fn) {
+ if (!(obj->flags & USER_GIVEN) && filter_fn) {
r = filter_fn(LOFS_END_TREE, obj,
base->buf, &base->buf[baselen],
filter_data);
diff --git a/object.h b/object.h
index 1b96073601..3afd123d73 100644
--- a/object.h
+++ b/object.h
@@ -53,7 +53,7 @@ struct object_array {
/*
* object flag allocation:
- * revision.h: 0---------10 26
+ * revision.h: 0---------10 2526
* fetch-pack.c: 0----5
* walker.c: 0-2
* upload-pack.c: 4 11----------------19
diff --git a/revision.c b/revision.c
index 72abe235e4..a2570397b6 100644
--- a/revision.c
+++ b/revision.c
@@ -175,6 +175,7 @@ static void add_pending_object_with_path(struct rev_info *revs,
strbuf_release(&buf);
return; /* do not add the commit itself */
}
+ obj->flags |= USER_GIVEN;
add_object_array_with_path(obj, name, &revs->pending, mode, path);
}
diff --git a/revision.h b/revision.h
index bf2239f876..c599c34da9 100644
--- a/revision.h
+++ b/revision.h
@@ -20,8 +20,9 @@
#define SYMMETRIC_LEFT (1u<<8)
#define PATCHSAME (1u<<9)
#define BOTTOM (1u<<10)
+#define USER_GIVEN (1u<<25) /* given directly by the user */
#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_FULL_REFS 2
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 1b0acc383b..6710c8bc8c 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -160,6 +160,22 @@ test_expect_success 'verify blob:limit=1k' '
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' '
git -C r2 ls-files -s large.1000 large.10000 \
| awk -f print_2.awk \
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index cee5565367..44d8e80171 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -154,4 +154,68 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack -
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_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+# Converts bytes into a form suitable for inclusion in a sed command. For
+# example, "printf 'ab\r\n' | hex_unpack" results in '\x61\x62\x0d\x0a'.
+sed_escape () {
+ perl -e '$/ = undef; $input = <>; print unpack("H2" x length($input), $input)' |
+ sed 's/\(..\)/\\x\1/g'
+}
+
+test_expect_success 'upon cloning, check that all refs point to objects' '
+ SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
+ rm -rf "$SERVER" repo &&
+ test_create_repo "$SERVER" &&
+ test_commit -C "$SERVER" foo &&
+ test_config -C "$SERVER" uploadpack.allowfilter 1 &&
+ test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 &&
+
+ # Create a tag pointing to a blob.
+ BLOB=$(echo blob-contents | git -C "$SERVER" hash-object --stdin -w) &&
+ git -C "$SERVER" tag myblob "$BLOB" &&
+
+ # Craft a packfile not including that blob.
+ git -C "$SERVER" rev-parse HEAD |
+ git -C "$SERVER" pack-objects --stdout >incomplete.pack &&
+
+ # Replace the existing packfile with the crafted one. The protocol
+ # requires that the packfile be sent in sideband 1, hence the extra
+ # \x01 byte at the beginning.
+ printf "1,/packfile/!c %04x\\\\x01%s0000" \
+ "$(($(wc -c <incomplete.pack) + 5))" \
+ "$(sed_escape <incomplete.pack)" \
+ >"$HTTPD_ROOT_PATH/one-time-sed" &&
+
+ # Use protocol v2 because the sed command looks for the "packfile"
+ # section header.
+ test_config -C "$SERVER" protocol.version 2 &&
+ test_must_fail git -c protocol.version=2 clone \
+ --filter=blob:none $HTTPD_URL/one_time_sed/server repo 2>err &&
+
+ grep "did not send all necessary objects" err &&
+
+ # Ensure that the one-time-sed script was used.
+ ! test -e "$HTTPD_ROOT_PATH/one-time-sed"
+'
+
+stop_httpd
+
test_done