remote: support downloading all tags Also honor remote.$name.tagopt = --tags.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 1bca7a7..c015289 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -307,7 +307,8 @@ GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbac
enum {
GIT_REMOTE_DOWNLOAD_TAGS_UNSET,
GIT_REMOTE_DOWNLOAD_TAGS_NONE,
- GIT_REMOTE_DOWNLOAD_TAGS_AUTO
+ GIT_REMOTE_DOWNLOAD_TAGS_AUTO,
+ GIT_REMOTE_DOWNLOAD_TAGS_ALL
};
/**
diff --git a/src/fetch.c b/src/fetch.c
index 98e1f0b..f9cc8aa 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -21,7 +21,7 @@
struct filter_payload {
git_remote *remote;
- const git_refspec *spec;
+ const git_refspec *spec, *tagspec;
git_odb *odb;
int found_head;
};
@@ -29,18 +29,21 @@ struct filter_payload {
static int filter_ref__cb(git_remote_head *head, void *payload)
{
struct filter_payload *p = payload;
+ int match = 0;
- if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0) {
+ if (!git_reference_is_valid_name(head->name))
+ return 0;
+
+ if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0)
p->found_head = 1;
- } else {
- /* If it doesn't match the refpec, we don't want it */
- if (!git_refspec_src_matches(p->spec, head->name))
- return 0;
+ else if (git_refspec_src_matches(p->spec, head->name))
+ match = 1;
+ else if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL &&
+ git_refspec_src_matches(p->tagspec, head->name))
+ match = 1;
- /* Don't even try to ask for the annotation target */
- if (!git__suffixcmp(head->name, "^{}"))
- return 0;
- }
+ if (!match)
+ return 0;
/* If we have the object, mark it so we don't ask for it */
if (git_odb_exists(p->odb, &head->oid))
@@ -54,8 +57,11 @@ static int filter_ref__cb(git_remote_head *head, void *payload)
static int filter_wants(git_remote *remote)
{
struct filter_payload p;
+ git_refspec tagspec;
git_vector_clear(&remote->refs);
+ if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
+ return -1;
/*
* The fetch refspec can be NULL, and what this means is that the
@@ -64,6 +70,7 @@ static int filter_wants(git_remote *remote)
* HEAD, which will be stored in FETCH_HEAD after the fetch.
*/
p.spec = git_remote_fetchspec(remote);
+ p.tagspec = &tagspec;
p.found_head = 0;
p.remote = remote;
diff --git a/src/refspec.h b/src/refspec.h
index 8307815..a5df458 100644
--- a/src/refspec.h
+++ b/src/refspec.h
@@ -19,6 +19,8 @@ struct git_refspec {
matching :1;
};
+#define GIT_REFSPEC_TAGS "refs/tags/*:refs/tags/*"
+
int git_refspec_parse(struct git_refspec *refspec, const char *str);
int git_refspec__parse(
struct git_refspec *refspec,
diff --git a/src/remote.c b/src/remote.c
index f446cfe..fd78164 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -47,6 +47,8 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
git_buf_free(&buf);
if (!error && !strcmp(val, "--no-tags"))
remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
+ else if (!error && !strcmp(val, "--tags"))
+ remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
if (error == GIT_ENOTFOUND)
error = 0;
@@ -455,7 +457,6 @@ int git_remote_update_tips(git_remote *remote)
git_remote_head *head;
git_reference *ref;
struct git_refspec *spec;
- char *tagstr = "refs/tags/*:refs/tags/*";
git_refspec tagspec;
assert(remote);
@@ -469,7 +470,7 @@ int git_remote_update_tips(git_remote *remote)
if (git_repository_odb(&odb, remote->repo) < 0)
return -1;
- if (git_refspec__parse(&tagspec, tagstr, true) < 0)
+ if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
return -1;
/* HEAD is only allowed to be the first in the list */
@@ -500,7 +501,9 @@ int git_remote_update_tips(git_remote *remote)
if (git_refspec_transform_r(&refname, spec, head->name) < 0)
goto on_error;
} else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
- autotag = 1;
+
+ if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
+ autotag = 1;
if (!git_refspec_src_matches(&tagspec, head->name))
continue;
diff --git a/src/remote.h b/src/remote.h
index 51587be..b8bb2c5 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -24,7 +24,7 @@ struct git_remote {
git_repository *repo;
git_remote_callbacks callbacks;
unsigned int need_pack:1,
- download_tags:2, /* There are three possible values */
+ download_tags:2, /* There are four possible values */
check_cert:1;
};