git/refspec.h
Jonathan Nieder 6c301adb0a fetch: do not pass ref-prefixes for fetch by exact SHA1
When v2.18.0-rc0~10^2~1 (refspec: consolidate ref-prefix generation
logic, 2018-05-16) factored out the ref-prefix generation code for
reuse, it left out the 'if (!item->exact_sha1)' test in the original
ref-prefix generation code. As a result, fetches by SHA-1 generate
ref-prefixes as though the SHA-1 being fetched were an abbreviated ref
name:

 $ GIT_TRACE_PACKET=1 bin-wrappers/git -c protocol.version=2 \
	fetch origin 12039e008f
[...]
 packet:        fetch> ref-prefix 12039e008f
 packet:        fetch> ref-prefix refs/12039e008f9a4e3394f3f94f8ea897785cb09448
 packet:        fetch> ref-prefix refs/tags/12039e008f9a4e3394f3f94f8ea897785cb09448
 packet:        fetch> ref-prefix refs/heads/12039e008f9a4e3394f3f94f8ea897785cb09448
 packet:        fetch> ref-prefix refs/remotes/12039e008f9a4e3394f3f94f8ea897785cb09448
 packet:        fetch> ref-prefix refs/remotes/12039e008f9a4e3394f3f94f8ea897785cb09448/HEAD
 packet:        fetch> 0000

If there is another ref name on the command line or the object being
fetched is already available locally, then that's mostly harmless.
But otherwise, we error out with

 fatal: no matching remote head

since the server did not send any refs we are interested in.  Filter
out the exact_sha1 refspecs to avoid this.

This patch adds a test to check this behavior that notices another
behavior difference between protocol v0 and v2 in the process.  Add a
NEEDSWORK comment to clear it up.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-01 15:15:22 +09:00

53 lines
1.2 KiB
C

#ifndef REFSPEC_H
#define REFSPEC_H
#define TAG_REFSPEC "refs/tags/*:refs/tags/*"
extern const struct refspec_item *tag_refspec;
struct refspec_item {
unsigned force : 1;
unsigned pattern : 1;
unsigned matching : 1;
unsigned exact_sha1 : 1;
char *src;
char *dst;
};
#define REFSPEC_FETCH 1
#define REFSPEC_PUSH 0
#define REFSPEC_INIT_FETCH { .fetch = REFSPEC_FETCH }
#define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH }
struct refspec {
struct refspec_item *items;
int alloc;
int nr;
const char **raw;
int raw_alloc;
int raw_nr;
int fetch;
};
void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch);
void refspec_item_clear(struct refspec_item *item);
void refspec_init(struct refspec *rs, int fetch);
void refspec_append(struct refspec *rs, const char *refspec);
void refspec_appendn(struct refspec *rs, const char **refspecs, int nr);
void refspec_clear(struct refspec *rs);
int valid_fetch_refspec(const char *refspec);
struct argv_array;
/*
* Determine what <prefix> values to pass to the peer in ref-prefix lines
* (see Documentation/technical/protocol-v2.txt).
*/
void refspec_ref_prefixes(const struct refspec *rs,
struct argv_array *ref_prefixes);
#endif /* REFSPEC_H */