зеркало из https://github.com/microsoft/git.git
fetch-pack: always allow fetching of literal SHA1s
fetch-pack, when fetching a literal SHA-1 from a server that is not configured with uploadpack.allowtipsha1inwant (or similar), always returns an error message of the form "Server does not allow request for unadvertised object %s". However, it is sometimes the case that such object is advertised. This situation would occur, for example, if a user or a script was provided a SHA-1 instead of a branch or tag name for fetching, and wanted to invoke "git fetch" or "git fetch-pack" using that SHA-1. Teach fetch-pack to also check the SHA-1s of the refs in the received ref advertisement if a literal SHA-1 was given by the user. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
b06d364310
Коммит
fdb69d33c4
40
fetch-pack.c
40
fetch-pack.c
|
@ -15,6 +15,7 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "prio-queue.h"
|
#include "prio-queue.h"
|
||||||
#include "sha1-array.h"
|
#include "sha1-array.h"
|
||||||
|
#include "oidset.h"
|
||||||
|
|
||||||
static int transfer_unpack_limit = -1;
|
static int transfer_unpack_limit = -1;
|
||||||
static int fetch_unpack_limit = -1;
|
static int fetch_unpack_limit = -1;
|
||||||
|
@ -592,13 +593,38 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_refs_to_oidset(struct oidset *oids, struct ref *refs)
|
||||||
|
{
|
||||||
|
for (; refs; refs = refs->next)
|
||||||
|
oidset_insert(oids, &refs->old_oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tip_oids_contain(struct oidset *tip_oids,
|
||||||
|
struct ref *unmatched, struct ref *newlist,
|
||||||
|
const struct object_id *id)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Note that this only looks at the ref lists the first time it's
|
||||||
|
* called. This works out in filter_refs() because even though it may
|
||||||
|
* add to "newlist" between calls, the additions will always be for
|
||||||
|
* oids that are already in the set.
|
||||||
|
*/
|
||||||
|
if (!tip_oids->map.tablesize) {
|
||||||
|
add_refs_to_oidset(tip_oids, unmatched);
|
||||||
|
add_refs_to_oidset(tip_oids, newlist);
|
||||||
|
}
|
||||||
|
return oidset_contains(tip_oids, id);
|
||||||
|
}
|
||||||
|
|
||||||
static void filter_refs(struct fetch_pack_args *args,
|
static void filter_refs(struct fetch_pack_args *args,
|
||||||
struct ref **refs,
|
struct ref **refs,
|
||||||
struct ref **sought, int nr_sought)
|
struct ref **sought, int nr_sought)
|
||||||
{
|
{
|
||||||
struct ref *newlist = NULL;
|
struct ref *newlist = NULL;
|
||||||
struct ref **newtail = &newlist;
|
struct ref **newtail = &newlist;
|
||||||
|
struct ref *unmatched = NULL;
|
||||||
struct ref *ref, *next;
|
struct ref *ref, *next;
|
||||||
|
struct oidset tip_oids = OIDSET_INIT;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -631,7 +657,8 @@ static void filter_refs(struct fetch_pack_args *args,
|
||||||
ref->next = NULL;
|
ref->next = NULL;
|
||||||
newtail = &ref->next;
|
newtail = &ref->next;
|
||||||
} else {
|
} else {
|
||||||
free(ref);
|
ref->next = unmatched;
|
||||||
|
unmatched = ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +675,9 @@ static void filter_refs(struct fetch_pack_args *args,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((allow_unadvertised_object_request &
|
if ((allow_unadvertised_object_request &
|
||||||
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
|
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1)) ||
|
||||||
|
tip_oids_contain(&tip_oids, unmatched, newlist,
|
||||||
|
&ref->old_oid)) {
|
||||||
ref->match_status = REF_MATCHED;
|
ref->match_status = REF_MATCHED;
|
||||||
*newtail = copy_ref(ref);
|
*newtail = copy_ref(ref);
|
||||||
newtail = &(*newtail)->next;
|
newtail = &(*newtail)->next;
|
||||||
|
@ -656,6 +685,13 @@ static void filter_refs(struct fetch_pack_args *args,
|
||||||
ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
|
ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oidset_clear(&tip_oids);
|
||||||
|
for (ref = unmatched; ref; ref = next) {
|
||||||
|
next = ref->next;
|
||||||
|
free(ref);
|
||||||
|
}
|
||||||
|
|
||||||
*refs = newlist;
|
*refs = newlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -547,6 +547,41 @@ test_expect_success 'fetch-pack can fetch a raw sha1' '
|
||||||
git fetch-pack hidden $(git -C hidden rev-parse refs/hidden/one)
|
git fetch-pack hidden $(git -C hidden rev-parse refs/hidden/one)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch-pack can fetch a raw sha1 that is advertised as a ref' '
|
||||||
|
rm -rf server client &&
|
||||||
|
git init server &&
|
||||||
|
test_commit -C server 1 &&
|
||||||
|
|
||||||
|
git init client &&
|
||||||
|
git -C client fetch-pack ../server \
|
||||||
|
$(git -C server rev-parse refs/heads/master)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch-pack can fetch a raw sha1 overlapping a named ref' '
|
||||||
|
rm -rf server client &&
|
||||||
|
git init server &&
|
||||||
|
test_commit -C server 1 &&
|
||||||
|
test_commit -C server 2 &&
|
||||||
|
|
||||||
|
git init client &&
|
||||||
|
git -C client fetch-pack ../server \
|
||||||
|
$(git -C server rev-parse refs/tags/1) refs/tags/1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch-pack cannot fetch a raw sha1 that is not advertised as a ref' '
|
||||||
|
rm -rf server &&
|
||||||
|
|
||||||
|
git init server &&
|
||||||
|
test_commit -C server 5 &&
|
||||||
|
git -C server tag -d 5 &&
|
||||||
|
test_commit -C server 6 &&
|
||||||
|
|
||||||
|
git init client &&
|
||||||
|
test_must_fail git -C client fetch-pack ../server \
|
||||||
|
$(git -C server rev-parse refs/heads/master^) 2>err &&
|
||||||
|
test_i18ngrep "Server does not allow request for unadvertised object" err
|
||||||
|
'
|
||||||
|
|
||||||
check_prot_path () {
|
check_prot_path () {
|
||||||
cat >expected <<-EOF &&
|
cat >expected <<-EOF &&
|
||||||
Diag: url=$1
|
Diag: url=$1
|
||||||
|
|
Загрузка…
Ссылка в новой задаче