blob: 0764fca0db9978336ae5ae13f79853d44a1e0944 [file] [log] [blame]
Elijah Newrene93fc5d2023-04-11 00:41:50 -07001#include "git-compat-util.h"
Elijah Newren0b027f62023-03-21 06:25:58 +00002#include "abspath.h"
Elijah Newren36bf1952023-02-24 00:09:24 +00003#include "alloc.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07004#include "config.h"
Elijah Newren32a8f512023-03-21 06:26:03 +00005#include "environment.h"
Elijah Newrenf394e092023-03-21 06:25:54 +00006#include "gettext.h"
Elijah Newren41771fa2023-02-24 00:09:27 +00007#include "hex.h"
Daniel Barkalow5751f492007-05-12 11:45:53 -04008#include "remote.h"
Derrick Stolee6dcbdc02022-06-06 14:36:16 +00009#include "urlmatch.h"
Daniel Barkalow5751f492007-05-12 11:45:53 -040010#include "refs.h"
Brandon Williamsec0cb492018-05-16 15:57:48 -070011#include "refspec.h"
Elijah Newrendabab1d2023-04-11 00:41:49 -070012#include "object-name.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070013#include "object-store.h"
Junio C Hamano6d21bf92008-07-02 00:51:18 -070014#include "commit.h"
15#include "diff.h"
16#include "revision.h"
Alexander Potashev8ca12c02009-01-10 15:07:50 +030017#include "dir.h"
Jay Soffianec8452d2009-02-25 03:32:12 -050018#include "tag.h"
Elijah Newrene38da482023-03-21 06:26:05 +000019#include "setup.h"
Julian Phillips73cf0822009-10-25 21:28:11 +000020#include "string-list.h"
Jeff Kingdbbcd442020-07-28 16:23:39 -040021#include "strvec.h"
Derrick Stolee64043552018-07-20 16:33:04 +000022#include "commit-reach.h"
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +000023#include "advice.h"
Derrick Stolee1d04e712022-05-16 20:11:03 +000024#include "connect.h"
SZEDER Gábor49fd5512023-03-19 17:27:11 +010025#include "parse-options.h"
Daniel Barkalow5751f492007-05-12 11:45:53 -040026
Felipe Contreras6ddba5e2012-02-23 00:43:41 +020027enum map_direction { FROM_SRC, FROM_DST };
28
Junio C Hamano844112c2008-02-24 22:25:04 -080029struct counted_string {
30 size_t len;
31 const char *s;
32};
Daniel Barkalow55029ae2008-02-20 13:43:53 -050033
Daniel Barkalow0a4da292009-11-18 02:42:23 +010034static int valid_remote(const struct remote *remote)
35{
Daniel Barkalowc578f512009-11-18 02:42:25 +010036 return (!!remote->url) || (!!remote->foreign_vcs);
Daniel Barkalow0a4da292009-11-18 02:42:23 +010037}
38
Josh Triplettd071d942009-09-07 01:56:00 -070039static const char *alias_url(const char *url, struct rewrites *r)
Daniel Barkalow55029ae2008-02-20 13:43:53 -050040{
41 int i, j;
Junio C Hamano844112c2008-02-24 22:25:04 -080042 struct counted_string *longest;
43 int longest_i;
44
45 longest = NULL;
46 longest_i = -1;
Josh Triplettd071d942009-09-07 01:56:00 -070047 for (i = 0; i < r->rewrite_nr; i++) {
48 if (!r->rewrite[i])
Daniel Barkalow55029ae2008-02-20 13:43:53 -050049 continue;
Josh Triplettd071d942009-09-07 01:56:00 -070050 for (j = 0; j < r->rewrite[i]->instead_of_nr; j++) {
Christian Couder59556542013-11-30 21:55:40 +010051 if (starts_with(url, r->rewrite[i]->instead_of[j].s) &&
Junio C Hamano844112c2008-02-24 22:25:04 -080052 (!longest ||
Josh Triplettd071d942009-09-07 01:56:00 -070053 longest->len < r->rewrite[i]->instead_of[j].len)) {
54 longest = &(r->rewrite[i]->instead_of[j]);
Junio C Hamano844112c2008-02-24 22:25:04 -080055 longest_i = i;
Daniel Barkalow55029ae2008-02-20 13:43:53 -050056 }
57 }
58 }
Junio C Hamano844112c2008-02-24 22:25:04 -080059 if (!longest)
60 return url;
61
Jeff King75faa452015-09-24 17:07:03 -040062 return xstrfmt("%s%s", r->rewrite[longest_i]->base, url + longest->len);
Daniel Barkalow55029ae2008-02-20 13:43:53 -050063}
64
Shawn O. Pearce28b91f82007-09-19 00:49:27 -040065static void add_url(struct remote *remote, const char *url)
Daniel Barkalow5751f492007-05-12 11:45:53 -040066{
Daniel Barkalow2d313472008-02-18 23:41:41 -050067 ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
68 remote->url[remote->url_nr++] = url;
Daniel Barkalow5751f492007-05-12 11:45:53 -040069}
70
Michael J Gruber20346232009-06-09 18:01:34 +020071static void add_pushurl(struct remote *remote, const char *pushurl)
72{
73 ALLOC_GROW(remote->pushurl, remote->pushurl_nr + 1, remote->pushurl_alloc);
74 remote->pushurl[remote->pushurl_nr++] = pushurl;
75}
76
Glen Choo085b98f2021-11-17 16:53:23 -080077static void add_pushurl_alias(struct remote_state *remote_state,
78 struct remote *remote, const char *url)
Josh Triplett1c2eafb2009-09-07 01:56:33 -070079{
Glen Choo085b98f2021-11-17 16:53:23 -080080 const char *pushurl = alias_url(url, &remote_state->rewrites_push);
Josh Triplett1c2eafb2009-09-07 01:56:33 -070081 if (pushurl != url)
82 add_pushurl(remote, pushurl);
83}
84
Glen Choo085b98f2021-11-17 16:53:23 -080085static void add_url_alias(struct remote_state *remote_state,
86 struct remote *remote, const char *url)
Josh Triplett1c2eafb2009-09-07 01:56:33 -070087{
Glen Choo085b98f2021-11-17 16:53:23 -080088 add_url(remote, alias_url(url, &remote_state->rewrites));
89 add_pushurl_alias(remote_state, remote, url);
Josh Triplett1c2eafb2009-09-07 01:56:33 -070090}
91
Patrick Reynoldsd0da0032014-07-29 14:43:39 +000092struct remotes_hash_key {
93 const char *str;
94 int len;
95};
96
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +020097static int remotes_hash_cmp(const void *cmp_data UNUSED,
Eric Wong939af162019-10-06 23:30:37 +000098 const struct hashmap_entry *eptr,
99 const struct hashmap_entry *entry_or_key,
Stefan Beller45dcb352017-06-30 17:28:35 -0700100 const void *keydata)
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000101{
Eric Wong939af162019-10-06 23:30:37 +0000102 const struct remote *a, *b;
Stefan Beller45dcb352017-06-30 17:28:35 -0700103 const struct remotes_hash_key *key = keydata;
104
Eric Wong939af162019-10-06 23:30:37 +0000105 a = container_of(eptr, const struct remote, ent);
106 b = container_of(entry_or_key, const struct remote, ent);
107
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000108 if (key)
109 return strncmp(a->name, key->str, key->len) || a->name[key->len];
110 else
111 return strcmp(a->name, b->name);
112}
113
Glen Choo085b98f2021-11-17 16:53:23 -0800114static struct remote *make_remote(struct remote_state *remote_state,
115 const char *name, int len)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400116{
Carlo Marcelo Arenas Belón6540b712021-09-02 04:52:53 -0400117 struct remote *ret;
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000118 struct remotes_hash_key lookup;
Eric Wongf23a4652019-10-06 23:30:36 +0000119 struct hashmap_entry lookup_entry, *e;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400120
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000121 if (!len)
122 len = strlen(name);
123
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000124 lookup.str = name;
125 lookup.len = len;
126 hashmap_entry_init(&lookup_entry, memhash(name, len));
127
Glen Choo085b98f2021-11-17 16:53:23 -0800128 e = hashmap_get(&remote_state->remotes_hash, &lookup_entry, &lookup);
Eric Wongf23a4652019-10-06 23:30:36 +0000129 if (e)
130 return container_of(e, struct remote, ent);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400131
René Scharfeca56dad2021-03-13 17:17:22 +0100132 CALLOC_ARRAY(ret, 1);
Michael Schubert737c5a92013-07-13 11:36:24 +0200133 ret->prune = -1; /* unspecified */
Ævar Arnfjörð Bjarmason97716d22018-02-09 20:32:15 +0000134 ret->prune_tags = -1; /* unspecified */
Brandon Williams6bdb3042018-05-16 15:58:00 -0700135 ret->name = xstrndup(name, len);
136 refspec_init(&ret->push, REFSPEC_PUSH);
Brandon Williamse5349ab2018-05-16 15:58:01 -0700137 refspec_init(&ret->fetch, REFSPEC_FETCH);
Brandon Williams6bdb3042018-05-16 15:58:00 -0700138
Glen Choo085b98f2021-11-17 16:53:23 -0800139 ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
140 remote_state->remotes_alloc);
141 remote_state->remotes[remote_state->remotes_nr++] = ret;
Patrick Reynoldsd0da0032014-07-29 14:43:39 +0000142
Eric Wongd22245a2019-10-06 23:30:27 +0000143 hashmap_entry_init(&ret->ent, lookup_entry.hash);
Glen Choo085b98f2021-11-17 16:53:23 -0800144 if (hashmap_put_entry(&remote_state->remotes_hash, ret, ent))
Carlo Marcelo Arenas Belón6540b712021-09-02 04:52:53 -0400145 BUG("hashmap_put overwrote entry after hashmap_get returned NULL");
Daniel Barkalow2d313472008-02-18 23:41:41 -0500146 return ret;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400147}
148
Glen Choofd3cb052021-11-17 16:53:22 -0800149static void remote_clear(struct remote *remote)
150{
151 int i;
152
153 free((char *)remote->name);
154 free((char *)remote->foreign_vcs);
155
Ævar Arnfjörð Bjarmason338959d2022-06-07 17:50:03 +0200156 for (i = 0; i < remote->url_nr; i++)
Glen Choofd3cb052021-11-17 16:53:22 -0800157 free((char *)remote->url[i]);
Ævar Arnfjörð Bjarmason323822c2022-06-07 17:50:04 +0200158 FREE_AND_NULL(remote->url);
Glen Choofd3cb052021-11-17 16:53:22 -0800159
Ævar Arnfjörð Bjarmason338959d2022-06-07 17:50:03 +0200160 for (i = 0; i < remote->pushurl_nr; i++)
Glen Choofd3cb052021-11-17 16:53:22 -0800161 free((char *)remote->pushurl[i]);
Glen Choofd3cb052021-11-17 16:53:22 -0800162 FREE_AND_NULL(remote->pushurl);
163 free((char *)remote->receivepack);
164 free((char *)remote->uploadpack);
165 FREE_AND_NULL(remote->http_proxy);
166 FREE_AND_NULL(remote->http_proxy_authmethod);
167}
168
Daniel Barkalowcf818342007-09-10 23:02:56 -0400169static void add_merge(struct branch *branch, const char *name)
170{
Daniel Barkalow2d313472008-02-18 23:41:41 -0500171 ALLOC_GROW(branch->merge_name, branch->merge_nr + 1,
172 branch->merge_alloc);
173 branch->merge_name[branch->merge_nr++] = name;
Daniel Barkalowcf818342007-09-10 23:02:56 -0400174}
175
Glen Choo4a2dcb12021-11-17 16:53:25 -0800176struct branches_hash_key {
177 const char *str;
178 int len;
179};
180
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +0200181static int branches_hash_cmp(const void *cmp_data UNUSED,
Glen Choo4a2dcb12021-11-17 16:53:25 -0800182 const struct hashmap_entry *eptr,
183 const struct hashmap_entry *entry_or_key,
184 const void *keydata)
185{
186 const struct branch *a, *b;
187 const struct branches_hash_key *key = keydata;
188
189 a = container_of(eptr, const struct branch, ent);
190 b = container_of(entry_or_key, const struct branch, ent);
191
192 if (key)
193 return strncmp(a->name, key->str, key->len) ||
194 a->name[key->len];
195 else
196 return strcmp(a->name, b->name);
197}
198
199static struct branch *find_branch(struct remote_state *remote_state,
200 const char *name, size_t len)
201{
202 struct branches_hash_key lookup;
203 struct hashmap_entry lookup_entry, *e;
204
Glen Choo4a2dcb12021-11-17 16:53:25 -0800205 lookup.str = name;
206 lookup.len = len;
207 hashmap_entry_init(&lookup_entry, memhash(name, len));
208
209 e = hashmap_get(&remote_state->branches_hash, &lookup_entry, &lookup);
210 if (e)
211 return container_of(e, struct branch, ent);
212
213 return NULL;
214}
215
216static void die_on_missing_branch(struct repository *repo,
217 struct branch *branch)
218{
219 /* branch == NULL is always valid because it represents detached HEAD. */
220 if (branch &&
Glen Choo91e2e8f2022-05-31 23:12:33 +0000221 branch != find_branch(repo->remote_state, branch->name,
222 strlen(branch->name)))
Glen Choo4a2dcb12021-11-17 16:53:25 -0800223 die("branch %s was not found in the repository", branch->name);
224}
225
Glen Choo085b98f2021-11-17 16:53:23 -0800226static struct branch *make_branch(struct remote_state *remote_state,
227 const char *name, size_t len)
Daniel Barkalowcf818342007-09-10 23:02:56 -0400228{
Daniel Barkalow2d313472008-02-18 23:41:41 -0500229 struct branch *ret;
Daniel Barkalowcf818342007-09-10 23:02:56 -0400230
Glen Choo4a2dcb12021-11-17 16:53:25 -0800231 ret = find_branch(remote_state, name, len);
232 if (ret)
233 return ret;
Daniel Barkalowcf818342007-09-10 23:02:56 -0400234
René Scharfeca56dad2021-03-13 17:17:22 +0100235 CALLOC_ARRAY(ret, 1);
Jeff King021ba322020-04-10 15:43:41 -0400236 ret->name = xstrndup(name, len);
Jeff Kingfa3f60b2014-06-18 16:02:13 -0400237 ret->refname = xstrfmt("refs/heads/%s", ret->name);
Daniel Barkalowcf818342007-09-10 23:02:56 -0400238
Glen Choo4a2dcb12021-11-17 16:53:25 -0800239 hashmap_entry_init(&ret->ent, memhash(name, len));
240 if (hashmap_put_entry(&remote_state->branches_hash, ret, ent))
241 BUG("hashmap_put overwrote entry after hashmap_get returned NULL");
Daniel Barkalow2d313472008-02-18 23:41:41 -0500242 return ret;
Daniel Barkalowcf818342007-09-10 23:02:56 -0400243}
244
Jeff King021ba322020-04-10 15:43:41 -0400245static struct rewrite *make_rewrite(struct rewrites *r,
246 const char *base, size_t len)
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500247{
248 struct rewrite *ret;
249 int i;
250
Josh Triplettd071d942009-09-07 01:56:00 -0700251 for (i = 0; i < r->rewrite_nr; i++) {
Jeff King021ba322020-04-10 15:43:41 -0400252 if (len == r->rewrite[i]->baselen &&
253 !strncmp(base, r->rewrite[i]->base, len))
Josh Triplettd071d942009-09-07 01:56:00 -0700254 return r->rewrite[i];
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500255 }
256
Josh Triplettd071d942009-09-07 01:56:00 -0700257 ALLOC_GROW(r->rewrite, r->rewrite_nr + 1, r->rewrite_alloc);
René Scharfeca56dad2021-03-13 17:17:22 +0100258 CALLOC_ARRAY(ret, 1);
Josh Triplettd071d942009-09-07 01:56:00 -0700259 r->rewrite[r->rewrite_nr++] = ret;
Jeff King021ba322020-04-10 15:43:41 -0400260 ret->base = xstrndup(base, len);
261 ret->baselen = len;
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500262 return ret;
263}
264
265static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
266{
267 ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
Junio C Hamano844112c2008-02-24 22:25:04 -0800268 rewrite->instead_of[rewrite->instead_of_nr].s = instead_of;
269 rewrite->instead_of[rewrite->instead_of_nr].len = strlen(instead_of);
270 rewrite->instead_of_nr++;
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500271}
272
Jeff King0e265a92015-09-24 17:07:20 -0400273static const char *skip_spaces(const char *s)
274{
275 while (isspace(*s))
276 s++;
277 return s;
278}
279
Glen Choo085b98f2021-11-17 16:53:23 -0800280static void read_remotes_file(struct remote_state *remote_state,
281 struct remote *remote)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400282{
Jeff King0e265a92015-09-24 17:07:20 -0400283 struct strbuf buf = STRBUF_INIT;
Nguyễn Thái Ngọc Duye9d983f2017-05-03 17:16:50 +0700284 FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r");
Daniel Barkalow5751f492007-05-12 11:45:53 -0400285
286 if (!f)
287 return;
Johannes Schindeline459b072017-01-19 22:20:02 +0100288 remote->configured_in_repo = 1;
Miklos Vajna89cf4c72008-11-10 21:43:00 +0100289 remote->origin = REMOTE_REMOTES;
Junio C Hamano18814d02015-10-28 13:27:33 -0700290 while (strbuf_getline(&buf, f) != EOF) {
Jeff King0e265a92015-09-24 17:07:20 -0400291 const char *v;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400292
Jeff King0e265a92015-09-24 17:07:20 -0400293 strbuf_rtrim(&buf);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400294
Jeff King0e265a92015-09-24 17:07:20 -0400295 if (skip_prefix(buf.buf, "URL:", &v))
Glen Choo085b98f2021-11-17 16:53:23 -0800296 add_url_alias(remote_state, remote,
297 xstrdup(skip_spaces(v)));
Jeff King0e265a92015-09-24 17:07:20 -0400298 else if (skip_prefix(buf.buf, "Push:", &v))
Brandon Williams6bdb3042018-05-16 15:58:00 -0700299 refspec_append(&remote->push, skip_spaces(v));
Jeff King0e265a92015-09-24 17:07:20 -0400300 else if (skip_prefix(buf.buf, "Pull:", &v))
Brandon Williamse5349ab2018-05-16 15:58:01 -0700301 refspec_append(&remote->fetch, skip_spaces(v));
Daniel Barkalow5751f492007-05-12 11:45:53 -0400302 }
Jeff King0e265a92015-09-24 17:07:20 -0400303 strbuf_release(&buf);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400304 fclose(f);
305}
306
Glen Choo085b98f2021-11-17 16:53:23 -0800307static void read_branches_file(struct remote_state *remote_state,
308 struct remote *remote)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400309{
Daniel Barkalowcf818342007-09-10 23:02:56 -0400310 char *frag;
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400311 struct strbuf buf = STRBUF_INIT;
Nguyễn Thái Ngọc Duye9d983f2017-05-03 17:16:50 +0700312 FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
Daniel Barkalow5751f492007-05-12 11:45:53 -0400313
314 if (!f)
315 return;
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400316
Junio C Hamano8f309ae2016-01-13 15:31:17 -0800317 strbuf_getline_lf(&buf, f);
Johannes Sixt0fb19902015-10-23 08:02:51 +0200318 fclose(f);
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400319 strbuf_trim(&buf);
320 if (!buf.len) {
321 strbuf_release(&buf);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400322 return;
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400323 }
324
Johannes Schindeline459b072017-01-19 22:20:02 +0100325 remote->configured_in_repo = 1;
Miklos Vajna89cf4c72008-11-10 21:43:00 +0100326 remote->origin = REMOTE_BRANCHES;
Daniel Barkalow472fa4c2008-03-25 19:35:28 -0400327
328 /*
Ramkumar Ramachandra55cfde22013-06-22 13:28:12 +0530329 * The branches file would have URL and optionally
Johannes Schindelina4712142020-06-24 14:46:35 +0000330 * #branch specified. The default (or specified) branch is
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400331 * fetched and stored in the local branch matching the
332 * remote name.
Daniel Barkalow472fa4c2008-03-25 19:35:28 -0400333 */
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400334 frag = strchr(buf.buf, '#');
335 if (frag)
Daniel Barkalowcf818342007-09-10 23:02:56 -0400336 *(frag++) = '\0';
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400337 else
Johannes Schindelincc0f13c2020-12-11 11:36:56 +0000338 frag = (char *)git_default_branch_name(0);
Ramkumar Ramachandra55cfde22013-06-22 13:28:12 +0530339
Glen Choo085b98f2021-11-17 16:53:23 -0800340 add_url_alias(remote_state, remote, strbuf_detach(&buf, NULL));
René Scharfe1af8b8c2020-09-05 16:49:30 +0200341 refspec_appendf(&remote->fetch, "refs/heads/%s:refs/heads/%s",
342 frag, remote->name);
Jeff Kingf28e3ab2015-09-24 17:07:18 -0400343
Martin Koegler18afe102008-11-10 22:47:11 +0100344 /*
345 * Cogito compatible push: push current HEAD to remote #branch
346 * (master if missing)
347 */
René Scharfe1af8b8c2020-09-05 16:49:30 +0200348 refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag);
Daniel Barkalowd71ab172007-09-10 23:03:08 -0400349 remote->fetch_tags = 1; /* always auto-follow */
Daniel Barkalow5751f492007-05-12 11:45:53 -0400350}
351
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100352static int handle_config(const char *key, const char *value, void *cb)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400353{
354 const char *name;
Jeff Kingf5914f42020-04-10 15:44:28 -0400355 size_t namelen;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400356 const char *subkey;
357 struct remote *remote;
Daniel Barkalowcf818342007-09-10 23:02:56 -0400358 struct branch *branch;
Glen Choo085b98f2021-11-17 16:53:23 -0800359 struct remote_state *remote_state = cb;
360
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100361 if (parse_config_key(key, "branch", &name, &namelen, &subkey) >= 0) {
Glen Choof1dfbd92022-05-31 23:12:34 +0000362 /* There is no subsection. */
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100363 if (!name)
Daniel Barkalowcf818342007-09-10 23:02:56 -0400364 return 0;
Glen Choof1dfbd92022-05-31 23:12:34 +0000365 /* There is a subsection, but it is empty. */
366 if (!namelen)
367 return -1;
Glen Choo085b98f2021-11-17 16:53:23 -0800368 branch = make_branch(remote_state, name, namelen);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100369 if (!strcmp(subkey, "remote")) {
Jeff Kinge41bf352015-05-01 18:44:41 -0400370 return git_config_string(&branch->remote_name, key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100371 } else if (!strcmp(subkey, "pushremote")) {
Jeff Kingda66b272015-05-21 00:45:20 -0400372 return git_config_string(&branch->pushremote_name, key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100373 } else if (!strcmp(subkey, "merge")) {
Junio C Hamanod2370cc2008-02-11 11:00:10 -0800374 if (!value)
375 return config_error_nonbool(key);
Daniel Barkalowcf818342007-09-10 23:02:56 -0400376 add_merge(branch, xstrdup(value));
Junio C Hamanod2370cc2008-02-11 11:00:10 -0800377 }
Daniel Barkalowcf818342007-09-10 23:02:56 -0400378 return 0;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400379 }
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100380 if (parse_config_key(key, "url", &name, &namelen, &subkey) >= 0) {
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500381 struct rewrite *rewrite;
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100382 if (!name)
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500383 return 0;
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100384 if (!strcmp(subkey, "insteadof")) {
Josh Triplett1c2eafb2009-09-07 01:56:33 -0700385 if (!value)
386 return config_error_nonbool(key);
Glen Choo085b98f2021-11-17 16:53:23 -0800387 rewrite = make_rewrite(&remote_state->rewrites, name,
388 namelen);
Josh Triplett1c2eafb2009-09-07 01:56:33 -0700389 add_instead_of(rewrite, xstrdup(value));
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100390 } else if (!strcmp(subkey, "pushinsteadof")) {
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500391 if (!value)
392 return config_error_nonbool(key);
Glen Choo085b98f2021-11-17 16:53:23 -0800393 rewrite = make_rewrite(&remote_state->rewrites_push,
394 name, namelen);
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500395 add_instead_of(rewrite, xstrdup(value));
396 }
397 }
Ramkumar Ramachandra224c2172013-04-02 13:10:33 +0530398
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100399 if (parse_config_key(key, "remote", &name, &namelen, &subkey) < 0)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400400 return 0;
Ramkumar Ramachandra224c2172013-04-02 13:10:33 +0530401
402 /* Handle remote.* variables */
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100403 if (!name && !strcmp(subkey, "pushdefault"))
Glen Choo085b98f2021-11-17 16:53:23 -0800404 return git_config_string(&remote_state->pushremote_name, key,
405 value);
Ramkumar Ramachandra224c2172013-04-02 13:10:33 +0530406
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100407 if (!name)
408 return 0;
Ramkumar Ramachandra224c2172013-04-02 13:10:33 +0530409 /* Handle remote.<name>.* variables */
Brandon Caseyc82efaf2008-10-14 15:30:21 -0500410 if (*name == '/') {
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +0100411 warning(_("config remote shorthand cannot begin with '/': %s"),
Brandon Caseyc82efaf2008-10-14 15:30:21 -0500412 name);
413 return 0;
414 }
Glen Choo085b98f2021-11-17 16:53:23 -0800415 remote = make_remote(remote_state, name, namelen);
Miklos Vajna89cf4c72008-11-10 21:43:00 +0100416 remote->origin = REMOTE_CONFIG;
Matthew Rogers6dc905d2020-02-10 00:30:54 +0000417 if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
Jeff King08e9df22020-12-03 03:00:18 -0500418 current_config_scope() == CONFIG_SCOPE_WORKTREE)
Johannes Schindeline459b072017-01-19 22:20:02 +0100419 remote->configured_in_repo = 1;
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100420 if (!strcmp(subkey, "mirror"))
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200421 remote->mirror = git_config_bool(key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100422 else if (!strcmp(subkey, "skipdefaultupdate"))
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200423 remote->skip_default_update = git_config_bool(key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100424 else if (!strcmp(subkey, "skipfetchall"))
Björn Gustavsson7cc91a22009-11-09 21:11:06 +0100425 remote->skip_default_update = git_config_bool(key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100426 else if (!strcmp(subkey, "prune"))
Michael Schubert737c5a92013-07-13 11:36:24 +0200427 remote->prune = git_config_bool(key, value);
Ævar Arnfjörð Bjarmason97716d22018-02-09 20:32:15 +0000428 else if (!strcmp(subkey, "prunetags"))
429 remote->prune_tags = git_config_bool(key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100430 else if (!strcmp(subkey, "url")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200431 const char *v;
432 if (git_config_string(&v, key, value))
433 return -1;
434 add_url(remote, v);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100435 } else if (!strcmp(subkey, "pushurl")) {
Michael J Gruber20346232009-06-09 18:01:34 +0200436 const char *v;
437 if (git_config_string(&v, key, value))
438 return -1;
439 add_pushurl(remote, v);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100440 } else if (!strcmp(subkey, "push")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200441 const char *v;
442 if (git_config_string(&v, key, value))
443 return -1;
Brandon Williams6bdb3042018-05-16 15:58:00 -0700444 refspec_append(&remote->push, v);
445 free((char *)v);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100446 } else if (!strcmp(subkey, "fetch")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200447 const char *v;
448 if (git_config_string(&v, key, value))
449 return -1;
Brandon Williamse5349ab2018-05-16 15:58:01 -0700450 refspec_append(&remote->fetch, v);
451 free((char *)v);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100452 } else if (!strcmp(subkey, "receivepack")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200453 const char *v;
454 if (git_config_string(&v, key, value))
455 return -1;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400456 if (!remote->receivepack)
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200457 remote->receivepack = v;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400458 else
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +0100459 error(_("more than one receivepack given, using the first"));
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100460 } else if (!strcmp(subkey, "uploadpack")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200461 const char *v;
462 if (git_config_string(&v, key, value))
463 return -1;
Daniel Barkalow0012ba22007-09-10 23:02:51 -0400464 if (!remote->uploadpack)
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200465 remote->uploadpack = v;
Daniel Barkalow0012ba22007-09-10 23:02:51 -0400466 else
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +0100467 error(_("more than one uploadpack given, using the first"));
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100468 } else if (!strcmp(subkey, "tagopt")) {
Daniel Barkalowd71ab172007-09-10 23:03:08 -0400469 if (!strcmp(value, "--no-tags"))
470 remote->fetch_tags = -1;
Samuel Tardieu944163a2010-04-20 01:31:25 +0200471 else if (!strcmp(value, "--tags"))
472 remote->fetch_tags = 2;
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100473 } else if (!strcmp(subkey, "proxy")) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200474 return git_config_string((const char **)&remote->http_proxy,
475 key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100476 } else if (!strcmp(subkey, "proxyauthmethod")) {
Knut Frankeef976392016-01-26 13:02:47 +0000477 return git_config_string((const char **)&remote->http_proxy_authmethod,
478 key, value);
Thomas Gummererbc60f8a2016-02-16 10:47:49 +0100479 } else if (!strcmp(subkey, "vcs")) {
Daniel Barkalowc578f512009-11-18 02:42:25 +0100480 return git_config_string(&remote->foreign_vcs, key, value);
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200481 }
Daniel Barkalow5751f492007-05-12 11:45:53 -0400482 return 0;
483}
484
Glen Choo085b98f2021-11-17 16:53:23 -0800485static void alias_all_urls(struct remote_state *remote_state)
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500486{
487 int i, j;
Glen Choo085b98f2021-11-17 16:53:23 -0800488 for (i = 0; i < remote_state->remotes_nr; i++) {
Josh Triplett1c2eafb2009-09-07 01:56:33 -0700489 int add_pushurl_aliases;
Glen Choo085b98f2021-11-17 16:53:23 -0800490 if (!remote_state->remotes[i])
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500491 continue;
Glen Choo085b98f2021-11-17 16:53:23 -0800492 for (j = 0; j < remote_state->remotes[i]->pushurl_nr; j++) {
493 remote_state->remotes[i]->pushurl[j] =
494 alias_url(remote_state->remotes[i]->pushurl[j],
495 &remote_state->rewrites);
Michael J Gruber20346232009-06-09 18:01:34 +0200496 }
Glen Choo085b98f2021-11-17 16:53:23 -0800497 add_pushurl_aliases = remote_state->remotes[i]->pushurl_nr == 0;
498 for (j = 0; j < remote_state->remotes[i]->url_nr; j++) {
Josh Triplett1c2eafb2009-09-07 01:56:33 -0700499 if (add_pushurl_aliases)
Glen Choofd3cb052021-11-17 16:53:22 -0800500 add_pushurl_alias(
Glen Choo085b98f2021-11-17 16:53:23 -0800501 remote_state, remote_state->remotes[i],
502 remote_state->remotes[i]->url[j]);
503 remote_state->remotes[i]->url[j] =
504 alias_url(remote_state->remotes[i]->url[j],
505 &remote_state->rewrites);
Josh Triplett1c2eafb2009-09-07 01:56:33 -0700506 }
Daniel Barkalow55029ae2008-02-20 13:43:53 -0500507 }
508}
509
Glen Choo085b98f2021-11-17 16:53:23 -0800510static void read_config(struct repository *repo)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400511{
Daniel Barkalow5751f492007-05-12 11:45:53 -0400512 int flag;
Jeff Kinge41bf352015-05-01 18:44:41 -0400513
Glen Choo085b98f2021-11-17 16:53:23 -0800514 if (repo->remote_state->initialized)
Daniel Barkalow5751f492007-05-12 11:45:53 -0400515 return;
Glen Choo085b98f2021-11-17 16:53:23 -0800516 repo->remote_state->initialized = 1;
Jeff Kinge41bf352015-05-01 18:44:41 -0400517
Glen Choo085b98f2021-11-17 16:53:23 -0800518 repo->remote_state->current_branch = NULL;
Jeff Kingf2f12d12016-03-05 17:11:57 -0500519 if (startup_info->have_repository) {
Glen Choo085b98f2021-11-17 16:53:23 -0800520 const char *head_ref = refs_resolve_ref_unsafe(
Ævar Arnfjörð Bjarmasonce14de02022-01-26 15:37:01 +0100521 get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
Jeff Kingf2f12d12016-03-05 17:11:57 -0500522 if (head_ref && (flag & REF_ISSYMREF) &&
523 skip_prefix(head_ref, "refs/heads/", &head_ref)) {
Glen Choo085b98f2021-11-17 16:53:23 -0800524 repo->remote_state->current_branch = make_branch(
525 repo->remote_state, head_ref, strlen(head_ref));
Jeff Kingf2f12d12016-03-05 17:11:57 -0500526 }
Daniel Barkalow5751f492007-05-12 11:45:53 -0400527 }
Glen Choo085b98f2021-11-17 16:53:23 -0800528 repo_config(repo, handle_config, repo->remote_state);
529 alias_all_urls(repo->remote_state);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400530}
531
Daniel Barkalowdf93e332008-02-15 14:14:18 -0500532static int valid_remote_nick(const char *name)
533{
Alexander Potashev8ca12c02009-01-10 15:07:50 +0300534 if (!name[0] || is_dot_or_dotdot(name))
Daniel Barkalowdf93e332008-02-15 14:14:18 -0500535 return 0;
Johannes Sixtd9244ec2017-05-25 14:00:13 +0200536
537 /* remote nicknames cannot contain slashes */
538 while (*name)
539 if (is_dir_sep(*name++))
540 return 0;
541 return 1;
Daniel Barkalowdf93e332008-02-15 14:14:18 -0500542}
543
Glen Choo56eed342021-11-17 16:53:24 -0800544static const char *remotes_remote_for_branch(struct remote_state *remote_state,
545 struct branch *branch,
546 int *explicit)
Jeff Kingf0521542015-05-21 00:45:16 -0400547{
548 if (branch && branch->remote_name) {
549 if (explicit)
550 *explicit = 1;
551 return branch->remote_name;
552 }
553 if (explicit)
554 *explicit = 0;
Tao Klerks8a649be2022-04-29 09:56:45 +0000555 if (remote_state->remotes_nr == 1)
556 return remote_state->remotes[0]->name;
Jeff Kingf0521542015-05-21 00:45:16 -0400557 return "origin";
558}
559
Glen Choo56eed342021-11-17 16:53:24 -0800560const char *remote_for_branch(struct branch *branch, int *explicit)
561{
562 read_config(the_repository);
Glen Choo4a2dcb12021-11-17 16:53:25 -0800563 die_on_missing_branch(the_repository, branch);
564
Glen Choo56eed342021-11-17 16:53:24 -0800565 return remotes_remote_for_branch(the_repository->remote_state, branch,
566 explicit);
567}
568
569static const char *
570remotes_pushremote_for_branch(struct remote_state *remote_state,
571 struct branch *branch, int *explicit)
Jeff Kingda66b272015-05-21 00:45:20 -0400572{
573 if (branch && branch->pushremote_name) {
574 if (explicit)
575 *explicit = 1;
576 return branch->pushremote_name;
577 }
Glen Choo56eed342021-11-17 16:53:24 -0800578 if (remote_state->pushremote_name) {
Jeff Kingda66b272015-05-21 00:45:20 -0400579 if (explicit)
580 *explicit = 1;
Glen Choo56eed342021-11-17 16:53:24 -0800581 return remote_state->pushremote_name;
Jeff Kingda66b272015-05-21 00:45:20 -0400582 }
Glen Choo56eed342021-11-17 16:53:24 -0800583 return remotes_remote_for_branch(remote_state, branch, explicit);
Jeff Kingda66b272015-05-21 00:45:20 -0400584}
585
Glen Choo56eed342021-11-17 16:53:24 -0800586const char *pushremote_for_branch(struct branch *branch, int *explicit)
587{
588 read_config(the_repository);
Glen Choo4a2dcb12021-11-17 16:53:25 -0800589 die_on_missing_branch(the_repository, branch);
590
Glen Choo56eed342021-11-17 16:53:24 -0800591 return remotes_pushremote_for_branch(the_repository->remote_state,
592 branch, explicit);
593}
594
595static struct remote *remotes_remote_get(struct remote_state *remote_state,
596 const char *name);
597
Jeff Kingaf8ccd82020-03-03 17:12:22 +0100598const char *remote_ref_for_branch(struct branch *branch, int for_push)
J Wyman9700fae2017-11-07 17:31:08 +0100599{
Glen Choo56eed342021-11-17 16:53:24 -0800600 read_config(the_repository);
Glen Choo4a2dcb12021-11-17 16:53:25 -0800601 die_on_missing_branch(the_repository, branch);
602
J Wyman9700fae2017-11-07 17:31:08 +0100603 if (branch) {
604 if (!for_push) {
605 if (branch->merge_nr) {
J Wyman9700fae2017-11-07 17:31:08 +0100606 return branch->merge_name[0];
607 }
608 } else {
Glen Choo56eed342021-11-17 16:53:24 -0800609 const char *dst,
610 *remote_name = remotes_pushremote_for_branch(
611 the_repository->remote_state, branch,
612 NULL);
613 struct remote *remote = remotes_remote_get(
614 the_repository->remote_state, remote_name);
J Wyman9700fae2017-11-07 17:31:08 +0100615
Brandon Williams6bdb3042018-05-16 15:58:00 -0700616 if (remote && remote->push.nr &&
Brandon Williamsd0004142018-05-16 15:58:11 -0700617 (dst = apply_refspecs(&remote->push,
J Wyman9700fae2017-11-07 17:31:08 +0100618 branch->refname))) {
J Wyman9700fae2017-11-07 17:31:08 +0100619 return dst;
620 }
621 }
622 }
Jeff Kingaf8ccd82020-03-03 17:12:22 +0100623 return NULL;
J Wyman9700fae2017-11-07 17:31:08 +0100624}
625
Derrick Stolee6dcbdc02022-06-06 14:36:16 +0000626static void validate_remote_url(struct remote *remote)
627{
628 int i;
629 const char *value;
630 struct strbuf redacted = STRBUF_INIT;
631 int warn_not_die;
632
Ævar Arnfjörð Bjarmason7281c192022-06-15 12:44:12 +0200633 if (git_config_get_string_tmp("transfer.credentialsinurl", &value))
Derrick Stolee6dcbdc02022-06-06 14:36:16 +0000634 return;
635
636 if (!strcmp("warn", value))
637 warn_not_die = 1;
638 else if (!strcmp("die", value))
639 warn_not_die = 0;
640 else if (!strcmp("allow", value))
641 return;
642 else
Jiang Xinb4eda052022-06-17 18:03:09 +0800643 die(_("unrecognized value transfer.credentialsInUrl: '%s'"), value);
Derrick Stolee6dcbdc02022-06-06 14:36:16 +0000644
645 for (i = 0; i < remote->url_nr; i++) {
646 struct url_info url_info = { 0 };
647
648 if (!url_normalize(remote->url[i], &url_info) ||
649 !url_info.passwd_off)
650 goto loop_cleanup;
651
652 strbuf_reset(&redacted);
653 strbuf_add(&redacted, url_info.url, url_info.passwd_off);
654 strbuf_addstr(&redacted, "<redacted>");
655 strbuf_addstr(&redacted,
656 url_info.url + url_info.passwd_off + url_info.passwd_len);
657
658 if (warn_not_die)
659 warning(_("URL '%s' uses plaintext credentials"), redacted.buf);
660 else
661 die(_("URL '%s' uses plaintext credentials"), redacted.buf);
662
663loop_cleanup:
664 free(url_info.url);
665 }
666
667 strbuf_release(&redacted);
668}
669
Glen Choo56eed342021-11-17 16:53:24 -0800670static struct remote *
671remotes_remote_get_1(struct remote_state *remote_state, const char *name,
672 const char *(*get_default)(struct remote_state *,
673 struct branch *, int *))
Daniel Barkalow5751f492007-05-12 11:45:53 -0400674{
675 struct remote *ret;
Daniel Barkalowfa685bd2009-03-11 01:47:20 -0400676 int name_given = 0;
Daniel Barkalow5751f492007-05-12 11:45:53 -0400677
Daniel Barkalowfa685bd2009-03-11 01:47:20 -0400678 if (name)
679 name_given = 1;
Jeff Kingda66b272015-05-21 00:45:20 -0400680 else
Glen Choo56eed342021-11-17 16:53:24 -0800681 name = get_default(remote_state, remote_state->current_branch,
Glen Choofd3cb052021-11-17 16:53:22 -0800682 &name_given);
Junio C Hamano9326d492009-03-16 00:35:09 -0700683
Glen Choo56eed342021-11-17 16:53:24 -0800684 ret = make_remote(remote_state, name, 0);
Jeff King4539c212017-02-14 15:33:28 -0500685 if (valid_remote_nick(name) && have_git_dir()) {
Daniel Barkalow0a4da292009-11-18 02:42:23 +0100686 if (!valid_remote(ret))
Glen Choo56eed342021-11-17 16:53:24 -0800687 read_remotes_file(remote_state, ret);
Daniel Barkalow0a4da292009-11-18 02:42:23 +0100688 if (!valid_remote(ret))
Glen Choo56eed342021-11-17 16:53:24 -0800689 read_branches_file(remote_state, ret);
Daniel Barkalow5751f492007-05-12 11:45:53 -0400690 }
Daniel Barkalow0a4da292009-11-18 02:42:23 +0100691 if (name_given && !valid_remote(ret))
Glen Choo56eed342021-11-17 16:53:24 -0800692 add_url_alias(remote_state, ret, name);
Daniel Barkalow0a4da292009-11-18 02:42:23 +0100693 if (!valid_remote(ret))
Daniel Barkalow5751f492007-05-12 11:45:53 -0400694 return NULL;
Derrick Stolee6dcbdc02022-06-06 14:36:16 +0000695
696 validate_remote_url(ret);
697
Daniel Barkalow5751f492007-05-12 11:45:53 -0400698 return ret;
699}
Daniel Barkalow6b628162007-05-12 11:45:59 -0400700
Glen Choo56eed342021-11-17 16:53:24 -0800701static inline struct remote *
702remotes_remote_get(struct remote_state *remote_state, const char *name)
703{
704 return remotes_remote_get_1(remote_state, name,
705 remotes_remote_for_branch);
706}
707
Ramkumar Ramachandraf24f7152013-04-02 13:10:32 +0530708struct remote *remote_get(const char *name)
709{
Glen Choo56eed342021-11-17 16:53:24 -0800710 read_config(the_repository);
711 return remotes_remote_get(the_repository->remote_state, name);
712}
713
714static inline struct remote *
715remotes_pushremote_get(struct remote_state *remote_state, const char *name)
716{
717 return remotes_remote_get_1(remote_state, name,
718 remotes_pushremote_for_branch);
Ramkumar Ramachandraf24f7152013-04-02 13:10:32 +0530719}
720
721struct remote *pushremote_get(const char *name)
722{
Glen Choo56eed342021-11-17 16:53:24 -0800723 read_config(the_repository);
724 return remotes_pushremote_get(the_repository->remote_state, name);
Ramkumar Ramachandraf24f7152013-04-02 13:10:32 +0530725}
726
Johannes Schindeline459b072017-01-19 22:20:02 +0100727int remote_is_configured(struct remote *remote, int in_repo)
Finn Arne Gangstad9a23ba32009-04-06 15:41:01 +0200728{
Johannes Schindeline459b072017-01-19 22:20:02 +0100729 if (!remote)
730 return 0;
731 if (in_repo)
732 return remote->configured_in_repo;
733 return !!remote->origin;
Finn Arne Gangstad9a23ba32009-04-06 15:41:01 +0200734}
735
Johannes Schindelinb42f6922007-07-10 18:48:40 +0100736int for_each_remote(each_remote_fn fn, void *priv)
737{
738 int i, result = 0;
Glen Choo085b98f2021-11-17 16:53:23 -0800739 read_config(the_repository);
Glen Choofd3cb052021-11-17 16:53:22 -0800740 for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
741 i++) {
742 struct remote *remote =
743 the_repository->remote_state->remotes[i];
744 if (!remote)
Johannes Schindelinb42f6922007-07-10 18:48:40 +0100745 continue;
Glen Choofd3cb052021-11-17 16:53:22 -0800746 result = fn(remote, priv);
Johannes Schindelinb42f6922007-07-10 18:48:40 +0100747 }
748 return result;
749}
750
Michael Haggertydf02ebd2013-10-30 06:33:10 +0100751static void handle_duplicate(struct ref *ref1, struct ref *ref2)
752{
Michael Haggertyf096e6e2013-10-30 06:33:12 +0100753 if (strcmp(ref1->name, ref2->name)) {
754 if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
755 ref2->fetch_head_status != FETCH_HEAD_IGNORE) {
756 die(_("Cannot fetch both %s and %s to %s"),
757 ref1->name, ref2->name, ref2->peer_ref->name);
758 } else if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
759 ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
760 warning(_("%s usually tracks %s, not %s"),
761 ref2->peer_ref->name, ref2->name, ref1->name);
762 } else if (ref1->fetch_head_status == FETCH_HEAD_IGNORE &&
763 ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
764 die(_("%s tracks both %s and %s"),
765 ref2->peer_ref->name, ref1->name, ref2->name);
766 } else {
767 /*
768 * This last possibility doesn't occur because
769 * FETCH_HEAD_IGNORE entries always appear at
770 * the end of the list.
771 */
Nguyễn Thái Ngọc Duy92ca8682018-11-10 06:16:08 +0100772 BUG("Internal error");
Michael Haggertyf096e6e2013-10-30 06:33:12 +0100773 }
774 }
Michael Haggertydf02ebd2013-10-30 06:33:10 +0100775 free(ref2->peer_ref);
776 free(ref2);
777}
778
Michael Haggertyb9afe662013-10-30 06:33:09 +0100779struct ref *ref_remove_duplicates(struct ref *ref_map)
Daniel Barkalow2467a4f2007-10-08 00:25:07 -0400780{
Thiago Farina183113a2010-07-04 16:46:19 -0300781 struct string_list refs = STRING_LIST_INIT_NODUP;
Michael Haggertyb9afe662013-10-30 06:33:09 +0100782 struct ref *retval = NULL;
783 struct ref **p = &retval;
Julian Phillips73cf0822009-10-25 21:28:11 +0000784
Michael Haggertyb9afe662013-10-30 06:33:09 +0100785 while (ref_map) {
786 struct ref *ref = ref_map;
Julian Phillips73cf0822009-10-25 21:28:11 +0000787
Michael Haggertyb9afe662013-10-30 06:33:09 +0100788 ref_map = ref_map->next;
789 ref->next = NULL;
790
791 if (!ref->peer_ref) {
792 *p = ref;
793 p = &ref->next;
Michael Haggerty09ea1f82013-10-30 06:33:07 +0100794 } else {
Michael Haggertyb9afe662013-10-30 06:33:09 +0100795 struct string_list_item *item =
796 string_list_insert(&refs, ref->peer_ref->name);
797
798 if (item->util) {
799 /* Entry already existed */
Michael Haggertydf02ebd2013-10-30 06:33:10 +0100800 handle_duplicate((struct ref *)item->util, ref);
Michael Haggertyb9afe662013-10-30 06:33:09 +0100801 } else {
802 *p = ref;
803 p = &ref->next;
804 item->util = ref;
805 }
Daniel Barkalow2467a4f2007-10-08 00:25:07 -0400806 }
807 }
Michael Haggertyb9afe662013-10-30 06:33:09 +0100808
Julian Phillips73cf0822009-10-25 21:28:11 +0000809 string_list_clear(&refs, 0);
Michael Haggertyb9afe662013-10-30 06:33:09 +0100810 return retval;
Daniel Barkalow2467a4f2007-10-08 00:25:07 -0400811}
812
Shawn O. Pearce28b91f82007-09-19 00:49:27 -0400813int remote_has_url(struct remote *remote, const char *url)
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -0400814{
815 int i;
Shawn O. Pearce28b91f82007-09-19 00:49:27 -0400816 for (i = 0; i < remote->url_nr; i++) {
817 if (!strcmp(remote->url[i], url))
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -0400818 return 1;
819 }
820 return 0;
821}
822
Daniel Barkalowe9282132009-03-07 01:11:34 -0500823static int match_name_with_pattern(const char *key, const char *name,
824 const char *value, char **result)
Daniel Barkalowa3c84232009-03-07 01:11:29 -0500825{
Daniel Barkalow08fbdb32009-03-07 01:11:36 -0500826 const char *kstar = strchr(key, '*');
827 size_t klen;
Daniel Barkalowabd2bde2009-03-07 01:11:39 -0500828 size_t ksuffixlen;
829 size_t namelen;
Daniel Barkalow08fbdb32009-03-07 01:11:36 -0500830 int ret;
831 if (!kstar)
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +0100832 die(_("key '%s' of pattern had no '*'"), key);
Daniel Barkalow08fbdb32009-03-07 01:11:36 -0500833 klen = kstar - key;
Daniel Barkalowabd2bde2009-03-07 01:11:39 -0500834 ksuffixlen = strlen(kstar + 1);
835 namelen = strlen(name);
836 ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen &&
837 !memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen);
Daniel Barkalowe9282132009-03-07 01:11:34 -0500838 if (ret && value) {
René Scharfe07bfa572014-09-21 10:23:37 +0200839 struct strbuf sb = STRBUF_INIT;
Daniel Barkalow08fbdb32009-03-07 01:11:36 -0500840 const char *vstar = strchr(value, '*');
Daniel Barkalow08fbdb32009-03-07 01:11:36 -0500841 if (!vstar)
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +0100842 die(_("value '%s' of pattern has no '*'"), value);
René Scharfe07bfa572014-09-21 10:23:37 +0200843 strbuf_add(&sb, value, vstar - value);
844 strbuf_add(&sb, name + klen, namelen - klen - ksuffixlen);
845 strbuf_addstr(&sb, vstar + 1);
846 *result = strbuf_detach(&sb, NULL);
Daniel Barkalowe9282132009-03-07 01:11:34 -0500847 }
Daniel Barkalowa3c84232009-03-07 01:11:29 -0500848 return ret;
849}
850
Jacob Kellerc0192df2020-09-30 14:25:29 -0700851static int refspec_match(const struct refspec_item *refspec,
852 const char *name)
853{
854 if (refspec->pattern)
855 return match_name_with_pattern(refspec->src, name, NULL, NULL);
856
857 return !strcmp(refspec->src, name);
858}
859
Jacob Keller2c80a822022-06-16 17:20:31 -0700860int omit_name_by_refspec(const char *name, struct refspec *rs)
Jacob Kellerc0192df2020-09-30 14:25:29 -0700861{
862 int i;
863
864 for (i = 0; i < rs->nr; i++) {
865 if (rs->items[i].negative && refspec_match(&rs->items[i], name))
866 return 1;
867 }
868 return 0;
869}
870
871struct ref *apply_negative_refspecs(struct ref *ref_map, struct refspec *rs)
872{
873 struct ref **tail;
874
875 for (tail = &ref_map; *tail; ) {
876 struct ref *ref = *tail;
877
878 if (omit_name_by_refspec(ref->name, rs)) {
879 *tail = ref->next;
880 free(ref->peer_ref);
881 free(ref);
882 } else
883 tail = &ref->next;
884 }
885
886 return ref_map;
887}
888
889static int query_matches_negative_refspec(struct refspec *rs, struct refspec_item *query)
890{
891 int i, matched_negative = 0;
892 int find_src = !query->src;
893 struct string_list reversed = STRING_LIST_INIT_NODUP;
894 const char *needle = find_src ? query->dst : query->src;
895
896 /*
897 * Check whether the queried ref matches any negative refpsec. If so,
898 * then we should ultimately treat this as not matching the query at
899 * all.
900 *
901 * Note that negative refspecs always match the source, but the query
902 * item uses the destination. To handle this, we apply pattern
903 * refspecs in reverse to figure out if the query source matches any
904 * of the negative refspecs.
Nipunn Koorapati773c6942020-12-22 03:58:17 +0000905 *
906 * The first loop finds and expands all positive refspecs
907 * matched by the queried ref.
908 *
909 * The second loop checks if any of the results of the first loop
910 * match any negative refspec.
Jacob Kellerc0192df2020-09-30 14:25:29 -0700911 */
912 for (i = 0; i < rs->nr; i++) {
913 struct refspec_item *refspec = &rs->items[i];
914 char *expn_name;
915
916 if (refspec->negative)
917 continue;
918
919 /* Note the reversal of src and dst */
920 if (refspec->pattern) {
921 const char *key = refspec->dst ? refspec->dst : refspec->src;
922 const char *value = refspec->src;
923
924 if (match_name_with_pattern(key, needle, value, &expn_name))
925 string_list_append_nodup(&reversed, expn_name);
Nipunn Koorapati18f9c982020-12-22 03:58:16 +0000926 } else if (refspec->matching) {
927 /* For the special matching refspec, any query should match */
928 string_list_append(&reversed, needle);
929 } else if (!refspec->src) {
930 BUG("refspec->src should not be null here");
931 } else if (!strcmp(needle, refspec->src)) {
932 string_list_append(&reversed, refspec->src);
Jacob Kellerc0192df2020-09-30 14:25:29 -0700933 }
934 }
935
936 for (i = 0; !matched_negative && i < reversed.nr; i++) {
937 if (omit_name_by_refspec(reversed.items[i].string, rs))
938 matched_negative = 1;
939 }
940
941 string_list_clear(&reversed, 0);
942
943 return matched_negative;
944}
945
Brandon Williamsa2ac50c2018-05-16 15:58:10 -0700946static void query_refspecs_multiple(struct refspec *rs,
947 struct refspec_item *query,
948 struct string_list *results)
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +0100949{
950 int i;
951 int find_src = !query->src;
952
953 if (find_src && !query->dst)
Nguyễn Thái Ngọc Duy92ca8682018-11-10 06:16:08 +0100954 BUG("query_refspecs_multiple: need either src or dst");
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +0100955
Jacob Kellerc0192df2020-09-30 14:25:29 -0700956 if (query_matches_negative_refspec(rs, query))
957 return;
958
Brandon Williamsa2ac50c2018-05-16 15:58:10 -0700959 for (i = 0; i < rs->nr; i++) {
960 struct refspec_item *refspec = &rs->items[i];
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +0100961 const char *key = find_src ? refspec->dst : refspec->src;
962 const char *value = find_src ? refspec->src : refspec->dst;
963 const char *needle = find_src ? query->dst : query->src;
964 char **result = find_src ? &query->src : &query->dst;
965
Jacob Kellerc0192df2020-09-30 14:25:29 -0700966 if (!refspec->dst || refspec->negative)
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +0100967 continue;
968 if (refspec->pattern) {
969 if (match_name_with_pattern(key, needle, value, result))
970 string_list_append_nodup(results, *result);
971 } else if (!strcmp(needle, key)) {
972 string_list_append(results, value);
973 }
974 }
975}
976
Brandon Williams86baf822018-05-16 15:58:12 -0700977int query_refspecs(struct refspec *rs, struct refspec_item *query)
Daniel Barkalow72ff8942009-11-18 02:42:28 +0100978{
979 int i;
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200980 int find_src = !query->src;
Michael Haggerty049bff82013-10-30 06:33:01 +0100981 const char *needle = find_src ? query->dst : query->src;
982 char **result = find_src ? &query->src : &query->dst;
Daniel Barkalow72ff8942009-11-18 02:42:28 +0100983
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200984 if (find_src && !query->dst)
Nguyễn Thái Ngọc Duy92ca8682018-11-10 06:16:08 +0100985 BUG("query_refspecs: need either src or dst");
Johannes Schindelinb42f6922007-07-10 18:48:40 +0100986
Jacob Kellerc0192df2020-09-30 14:25:29 -0700987 if (query_matches_negative_refspec(rs, query))
988 return -1;
989
Brandon Williams86baf822018-05-16 15:58:12 -0700990 for (i = 0; i < rs->nr; i++) {
991 struct refspec_item *refspec = &rs->items[i];
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200992 const char *key = find_src ? refspec->dst : refspec->src;
993 const char *value = find_src ? refspec->src : refspec->dst;
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200994
Jacob Kellerc0192df2020-09-30 14:25:29 -0700995 if (!refspec->dst || refspec->negative)
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -0400996 continue;
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200997 if (refspec->pattern) {
Daniel Barkalowe9282132009-03-07 01:11:34 -0500998 if (match_name_with_pattern(key, needle, value, result)) {
Carlos Martín Nietoc5003522011-10-15 07:04:24 +0200999 query->force = refspec->force;
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -04001000 return 0;
1001 }
Johannes Schindelinb42f6922007-07-10 18:48:40 +01001002 } else if (!strcmp(needle, key)) {
1003 *result = xstrdup(value);
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001004 query->force = refspec->force;
Johannes Schindelinb42f6922007-07-10 18:48:40 +01001005 return 0;
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -04001006 }
1007 }
Daniel Barkalow5d46c9d2007-05-12 11:46:03 -04001008 return -1;
1009}
1010
Brandon Williamsd0004142018-05-16 15:58:11 -07001011char *apply_refspecs(struct refspec *rs, const char *name)
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001012{
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001013 struct refspec_item query;
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001014
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001015 memset(&query, 0, sizeof(struct refspec_item));
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001016 query.src = (char *)name;
1017
Brandon Williams86baf822018-05-16 15:58:12 -07001018 if (query_refspecs(rs, &query))
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001019 return NULL;
1020
1021 return query.dst;
1022}
1023
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001024int remote_find_tracking(struct remote *remote, struct refspec_item *refspec)
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001025{
Brandon Williams86baf822018-05-16 15:58:12 -07001026 return query_refspecs(&remote->fetch, refspec);
Carlos Martín Nietoc5003522011-10-15 07:04:24 +02001027}
1028
René Scharfe80097682008-10-18 10:37:40 +02001029static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen,
1030 const char *name)
1031{
1032 size_t len = strlen(name);
Jeff King50a6c8e2016-02-22 17:44:35 -05001033 struct ref *ref = xcalloc(1, st_add4(sizeof(*ref), prefixlen, len, 1));
René Scharfe80097682008-10-18 10:37:40 +02001034 memcpy(ref->name, prefix, prefixlen);
1035 memcpy(ref->name + prefixlen, name, len);
1036 return ref;
1037}
1038
René Scharfe59c69c02008-10-18 10:44:18 +02001039struct ref *alloc_ref(const char *name)
Daniel Barkalowdfd255d2007-07-10 00:47:23 -04001040{
René Scharfe59c69c02008-10-18 10:44:18 +02001041 return alloc_ref_with_prefix("", 0, name);
Krzysztof Kowalczyk737922a2008-05-10 16:26:58 -07001042}
1043
Jeff King59a57752011-06-07 19:03:03 -04001044struct ref *copy_ref(const struct ref *ref)
Daniel Barkalowd71ab172007-09-10 23:03:08 -04001045{
Jay Soffian7b3db092009-02-27 14:10:04 -05001046 struct ref *cpy;
1047 size_t len;
1048 if (!ref)
1049 return NULL;
Jeff King50a6c8e2016-02-22 17:44:35 -05001050 len = st_add3(sizeof(struct ref), strlen(ref->name), 1);
1051 cpy = xmalloc(len);
1052 memcpy(cpy, ref, len);
Jay Soffian7b3db092009-02-27 14:10:04 -05001053 cpy->next = NULL;
Jeff King8c53f072015-01-12 20:59:09 -05001054 cpy->symref = xstrdup_or_null(ref->symref);
1055 cpy->remote_status = xstrdup_or_null(ref->remote_status);
Jay Soffian7b3db092009-02-27 14:10:04 -05001056 cpy->peer_ref = copy_ref(ref->peer_ref);
1057 return cpy;
Daniel Barkalowd71ab172007-09-10 23:03:08 -04001058}
1059
Daniel Barkalow45773702007-10-29 21:05:40 -04001060struct ref *copy_ref_list(const struct ref *ref)
1061{
1062 struct ref *ret = NULL;
1063 struct ref **tail = &ret;
1064 while (ref) {
1065 *tail = copy_ref(ref);
1066 ref = ref->next;
1067 tail = &((*tail)->next);
1068 }
1069 return ret;
1070}
1071
Jeff King10271862019-04-13 01:54:31 -04001072void free_one_ref(struct ref *ref)
Daniel Barkalowbe885d92008-04-26 15:53:12 -04001073{
1074 if (!ref)
1075 return;
Jeff King10271862019-04-13 01:54:31 -04001076 free_one_ref(ref->peer_ref);
Daniel Barkalowbe885d92008-04-26 15:53:12 -04001077 free(ref->remote_status);
1078 free(ref->symref);
1079 free(ref);
1080}
1081
Daniel Barkalowdfd255d2007-07-10 00:47:23 -04001082void free_refs(struct ref *ref)
1083{
1084 struct ref *next;
1085 while (ref) {
1086 next = ref->next;
Jeff King10271862019-04-13 01:54:31 -04001087 free_one_ref(ref);
Daniel Barkalowdfd255d2007-07-10 00:47:23 -04001088 ref = next;
1089 }
1090}
1091
Junio C Hamanoca024652013-12-03 15:41:15 -08001092int count_refspec_match(const char *pattern,
1093 struct ref *refs,
1094 struct ref **matched_ref)
Daniel Barkalow6b628162007-05-12 11:45:59 -04001095{
1096 int patlen = strlen(pattern);
1097 struct ref *matched_weak = NULL;
1098 struct ref *matched = NULL;
1099 int weak_match = 0;
1100 int match = 0;
1101
1102 for (weak_match = match = 0; refs; refs = refs->next) {
1103 char *name = refs->name;
1104 int namelen = strlen(name);
Daniel Barkalow6b628162007-05-12 11:45:59 -04001105
Michael Haggerty54457fe2014-01-14 04:16:07 +01001106 if (!refname_match(pattern, name))
Daniel Barkalow6b628162007-05-12 11:45:59 -04001107 continue;
1108
1109 /* A match is "weak" if it is with refs outside
1110 * heads or tags, and did not specify the pattern
1111 * in full (e.g. "refs/remotes/origin/master") or at
1112 * least from the toplevel (e.g. "remotes/origin/master");
1113 * otherwise "git push $URL master" would result in
1114 * ambiguity between remotes/origin/master and heads/master
1115 * at the remote site.
1116 */
1117 if (namelen != patlen &&
1118 patlen != namelen - 5 &&
Christian Couder59556542013-11-30 21:55:40 +01001119 !starts_with(name, "refs/heads/") &&
1120 !starts_with(name, "refs/tags/")) {
Daniel Barkalow6b628162007-05-12 11:45:59 -04001121 /* We want to catch the case where only weak
1122 * matches are found and there are multiple
1123 * matches, and where more than one strong
1124 * matches are found, as ambiguous. One
1125 * strong match with zero or more weak matches
1126 * are acceptable as a unique match.
1127 */
1128 matched_weak = refs;
1129 weak_match++;
1130 }
1131 else {
1132 matched = refs;
1133 match++;
1134 }
1135 }
1136 if (!matched) {
Jeff King471fd3f2014-03-05 14:03:43 -05001137 if (matched_ref)
1138 *matched_ref = matched_weak;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001139 return weak_match;
1140 }
1141 else {
Jeff King471fd3f2014-03-05 14:03:43 -05001142 if (matched_ref)
1143 *matched_ref = matched;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001144 return match;
1145 }
1146}
1147
Daniel Barkalow1d735262007-07-10 00:47:26 -04001148static void tail_link_ref(struct ref *ref, struct ref ***tail)
Daniel Barkalow6b628162007-05-12 11:45:59 -04001149{
1150 **tail = ref;
Daniel Barkalow1d735262007-07-10 00:47:26 -04001151 while (ref->next)
1152 ref = ref->next;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001153 *tail = &ref->next;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001154}
1155
Felipe Contreras67655242012-02-23 00:43:40 +02001156static struct ref *alloc_delete_ref(void)
1157{
1158 struct ref *ref = alloc_ref("(delete)");
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001159 oidclr(&ref->new_oid);
Felipe Contreras67655242012-02-23 00:43:40 +02001160 return ref;
1161}
1162
Jeff King471fd3f2014-03-05 14:03:43 -05001163static int try_explicit_object_name(const char *name,
1164 struct ref **match)
Daniel Barkalow6b628162007-05-12 11:45:59 -04001165{
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001166 struct object_id oid;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001167
Jeff King471fd3f2014-03-05 14:03:43 -05001168 if (!*name) {
1169 if (match)
1170 *match = alloc_delete_ref();
1171 return 0;
1172 }
1173
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +02001174 if (repo_get_oid(the_repository, name, &oid))
Jeff King471fd3f2014-03-05 14:03:43 -05001175 return -1;
1176
1177 if (match) {
1178 *match = alloc_ref(name);
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001179 oidcpy(&(*match)->new_oid, &oid);
Jeff King471fd3f2014-03-05 14:03:43 -05001180 }
1181 return 0;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001182}
1183
Daniel Barkalow1d735262007-07-10 00:47:26 -04001184static struct ref *make_linked_ref(const char *name, struct ref ***tail)
Junio C Hamano163f0ee2007-06-09 00:07:34 -07001185{
René Scharfe59c69c02008-10-18 10:44:18 +02001186 struct ref *ret = alloc_ref(name);
Daniel Barkalow1d735262007-07-10 00:47:26 -04001187 tail_link_ref(ret, tail);
1188 return ret;
Junio C Hamano163f0ee2007-06-09 00:07:34 -07001189}
1190
Jeff Kingf8aae122008-04-23 05:16:06 -04001191static char *guess_ref(const char *name, struct ref *peer)
1192{
1193 struct strbuf buf = STRBUF_INIT;
Jeff Kingf8aae122008-04-23 05:16:06 -04001194
Ronnie Sahlberg7695d112014-07-15 12:59:36 -07001195 const char *r = resolve_ref_unsafe(peer->name, RESOLVE_REF_READING,
René Scharfe744c0402017-09-23 11:45:04 +02001196 NULL, NULL);
Jeff Kingf8aae122008-04-23 05:16:06 -04001197 if (!r)
1198 return NULL;
1199
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001200 if (starts_with(r, "refs/heads/")) {
Jeff Kingf8aae122008-04-23 05:16:06 -04001201 strbuf_addstr(&buf, "refs/heads/");
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001202 } else if (starts_with(r, "refs/tags/")) {
Jeff Kingf8aae122008-04-23 05:16:06 -04001203 strbuf_addstr(&buf, "refs/tags/");
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001204 } else {
Jeff Kingf8aae122008-04-23 05:16:06 -04001205 return NULL;
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001206 }
Jeff Kingf8aae122008-04-23 05:16:06 -04001207
1208 strbuf_addstr(&buf, name);
1209 return strbuf_detach(&buf, NULL);
1210}
1211
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001212static int match_explicit_lhs(struct ref *src,
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001213 struct refspec_item *rs,
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001214 struct ref **match,
1215 int *allocated_match)
1216{
1217 switch (count_refspec_match(rs->src, src, match)) {
1218 case 1:
Jeff King471fd3f2014-03-05 14:03:43 -05001219 if (allocated_match)
1220 *allocated_match = 0;
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001221 return 0;
1222 case 0:
1223 /* The source could be in the get_sha1() format
1224 * not a reference name. :refs/other is a
1225 * way to delete 'other' ref at the remote end.
1226 */
Jeff King471fd3f2014-03-05 14:03:43 -05001227 if (try_explicit_object_name(rs->src, match) < 0)
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001228 return error(_("src refspec %s does not match any"), rs->src);
Jeff King471fd3f2014-03-05 14:03:43 -05001229 if (allocated_match)
1230 *allocated_match = 1;
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001231 return 0;
1232 default:
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001233 return error(_("src refspec %s matches more than one"), rs->src);
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001234 }
1235}
1236
Ævar Arnfjörð Bjarmason04d17282018-11-13 19:52:42 +00001237static void show_push_unqualified_ref_name_error(const char *dst_value,
1238 const char *matched_src_name)
1239{
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +00001240 struct object_id oid;
1241 enum object_type type;
1242
Ævar Arnfjörð Bjarmason04d17282018-11-13 19:52:42 +00001243 /*
1244 * TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
1245 * <remote> <src>:<dst>" push, and "being pushed ('%s')" is
1246 * the <src>.
1247 */
1248 error(_("The destination you provided is not a full refname (i.e.,\n"
1249 "starting with \"refs/\"). We tried to guess what you meant by:\n"
1250 "\n"
1251 "- Looking for a ref that matches '%s' on the remote side.\n"
1252 "- Checking if the <src> being pushed ('%s')\n"
1253 " is a ref in \"refs/{heads,tags}/\". If so we add a corresponding\n"
1254 " refs/{heads,tags}/ prefix on the remote side.\n"
1255 "\n"
1256 "Neither worked, so we gave up. You must fully qualify the ref."),
1257 dst_value, matched_src_name);
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +00001258
Ben Boeckeled9bff02021-08-23 12:44:00 +02001259 if (!advice_enabled(ADVICE_PUSH_UNQUALIFIED_REF_NAME))
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +00001260 return;
1261
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +02001262 if (repo_get_oid(the_repository, matched_src_name, &oid))
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +00001263 BUG("'%s' is not a valid object, "
1264 "match_explicit_lhs() should catch this!",
1265 matched_src_name);
1266 type = oid_object_info(the_repository, &oid, NULL);
1267 if (type == OBJ_COMMIT) {
1268 advise(_("The <src> part of the refspec is a commit object.\n"
1269 "Did you mean to create a new branch by pushing to\n"
1270 "'%s:refs/heads/%s'?"),
1271 matched_src_name, dst_value);
1272 } else if (type == OBJ_TAG) {
1273 advise(_("The <src> part of the refspec is a tag object.\n"
1274 "Did you mean to create a new tag by pushing to\n"
1275 "'%s:refs/tags/%s'?"),
1276 matched_src_name, dst_value);
1277 } else if (type == OBJ_TREE) {
1278 advise(_("The <src> part of the refspec is a tree object.\n"
1279 "Did you mean to tag a new tree by pushing to\n"
1280 "'%s:refs/tags/%s'?"),
1281 matched_src_name, dst_value);
1282 } else if (type == OBJ_BLOB) {
1283 advise(_("The <src> part of the refspec is a blob object.\n"
1284 "Did you mean to tag a new blob by pushing to\n"
1285 "'%s:refs/tags/%s'?"),
1286 matched_src_name, dst_value);
1287 } else {
1288 BUG("'%s' should be commit/tag/tree/blob, is '%d'",
1289 matched_src_name, type);
1290 }
Ævar Arnfjörð Bjarmason04d17282018-11-13 19:52:42 +00001291}
1292
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001293static int match_explicit(struct ref *src, struct ref *dst,
1294 struct ref ***dst_tail,
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001295 struct refspec_item *rs)
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001296{
1297 struct ref *matched_src, *matched_dst;
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001298 int allocated_src;
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001299
1300 const char *dst_value = rs->dst;
Jeff Kingf8aae122008-04-23 05:16:06 -04001301 char *dst_guess;
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001302
Jacob Kellerc0192df2020-09-30 14:25:29 -07001303 if (rs->pattern || rs->matching || rs->negative)
Jeff King9a7bbd12008-06-16 12:15:02 -04001304 return 0;
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001305
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001306 matched_src = matched_dst = NULL;
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001307 if (match_explicit_lhs(src, rs, &matched_src, &allocated_src) < 0)
1308 return -1;
Junio C Hamano3c8b7df2007-06-09 00:14:04 -07001309
Shawn O. Pearce4491e622007-09-25 00:13:25 -04001310 if (!dst_value) {
Daniel Barkalow9f0ea7e2008-02-20 12:54:05 -05001311 int flag;
1312
Ronnie Sahlberg7695d112014-07-15 12:59:36 -07001313 dst_value = resolve_ref_unsafe(matched_src->name,
1314 RESOLVE_REF_READING,
René Scharfe744c0402017-09-23 11:45:04 +02001315 NULL, &flag);
Daniel Barkalow9f0ea7e2008-02-20 12:54:05 -05001316 if (!dst_value ||
1317 ((flag & REF_ISSYMREF) &&
Christian Couder59556542013-11-30 21:55:40 +01001318 !starts_with(dst_value, "refs/heads/")))
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001319 die(_("%s cannot be resolved to branch"),
Daniel Barkalow9f0ea7e2008-02-20 12:54:05 -05001320 matched_src->name);
Shawn O. Pearce4491e622007-09-25 00:13:25 -04001321 }
Junio C Hamano3c8b7df2007-06-09 00:14:04 -07001322
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001323 switch (count_refspec_match(dst_value, dst, &matched_dst)) {
1324 case 1:
1325 break;
1326 case 0:
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001327 if (starts_with(dst_value, "refs/")) {
Daniel Barkalow1d735262007-07-10 00:47:26 -04001328 matched_dst = make_linked_ref(dst_value, dst_tail);
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001329 } else if (is_null_oid(&matched_src->new_oid)) {
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001330 error(_("unable to delete '%s': remote ref does not exist"),
Jeff King5742c822012-07-03 14:04:39 -04001331 dst_value);
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001332 } else if ((dst_guess = guess_ref(dst_value, matched_src))) {
Jeff Kingf8aae122008-04-23 05:16:06 -04001333 matched_dst = make_linked_ref(dst_guess, dst_tail);
Johannes Schindelin3dc7ea92017-05-04 15:59:01 +02001334 free(dst_guess);
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001335 } else {
Ævar Arnfjörð Bjarmason04d17282018-11-13 19:52:42 +00001336 show_push_unqualified_ref_name_error(dst_value,
1337 matched_src->name);
Ævar Arnfjörð Bjarmasoncab53982018-11-13 19:52:39 +00001338 }
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001339 break;
1340 default:
Junio C Hamano3c8b7df2007-06-09 00:14:04 -07001341 matched_dst = NULL;
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001342 error(_("dst refspec %s matches more than one"),
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001343 dst_value);
1344 break;
1345 }
Jeff King9a7bbd12008-06-16 12:15:02 -04001346 if (!matched_dst)
1347 return -1;
1348 if (matched_dst->peer_ref)
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01001349 return error(_("dst ref %s receives from more than one src"),
1350 matched_dst->name);
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001351 else {
Jeff Kingf7ade3d2014-03-05 14:03:21 -05001352 matched_dst->peer_ref = allocated_src ?
1353 matched_src :
1354 copy_ref(matched_src);
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001355 matched_dst->force = rs->force;
1356 }
Jeff King9a7bbd12008-06-16 12:15:02 -04001357 return 0;
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001358}
1359
Daniel Barkalow6b628162007-05-12 11:45:59 -04001360static int match_explicit_refs(struct ref *src, struct ref *dst,
Brandon Williams9fa2e5e2018-05-16 15:58:14 -07001361 struct ref ***dst_tail, struct refspec *rs)
Daniel Barkalow6b628162007-05-12 11:45:59 -04001362{
1363 int i, errs;
Brandon Williams9fa2e5e2018-05-16 15:58:14 -07001364 for (i = errs = 0; i < rs->nr; i++)
1365 errs += match_explicit(src, dst, dst_tail, &rs->items[i]);
Jeff King9a7bbd12008-06-16 12:15:02 -04001366 return errs;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001367}
1368
Brandon Williamsf3acb832018-05-16 15:58:13 -07001369static char *get_ref_match(const struct refspec *rs, const struct ref *ref,
1370 int send_mirror, int direction,
1371 const struct refspec_item **ret_pat)
Daniel Barkalow8558fd92007-05-25 01:20:56 -04001372{
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001373 const struct refspec_item *pat;
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001374 char *name;
Daniel Barkalow8558fd92007-05-25 01:20:56 -04001375 int i;
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001376 int matching_refs = -1;
Brandon Williamsf3acb832018-05-16 15:58:13 -07001377 for (i = 0; i < rs->nr; i++) {
1378 const struct refspec_item *item = &rs->items[i];
Jacob Kellerc0192df2020-09-30 14:25:29 -07001379
1380 if (item->negative)
1381 continue;
1382
Brandon Williamsf3acb832018-05-16 15:58:13 -07001383 if (item->matching &&
1384 (matching_refs == -1 || item->force)) {
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001385 matching_refs = i;
1386 continue;
1387 }
1388
Brandon Williamsf3acb832018-05-16 15:58:13 -07001389 if (item->pattern) {
1390 const char *dst_side = item->dst ? item->dst : item->src;
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001391 int match;
1392 if (direction == FROM_SRC)
Brandon Williamsf3acb832018-05-16 15:58:13 -07001393 match = match_name_with_pattern(item->src, ref->name, dst_side, &name);
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001394 else
Brandon Williamsf3acb832018-05-16 15:58:13 -07001395 match = match_name_with_pattern(dst_side, ref->name, item->src, &name);
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001396 if (match) {
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001397 matching_refs = i;
1398 break;
1399 }
1400 }
Daniel Barkalow8558fd92007-05-25 01:20:56 -04001401 }
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001402 if (matching_refs == -1)
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001403 return NULL;
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001404
Brandon Williamsf3acb832018-05-16 15:58:13 -07001405 pat = &rs->items[matching_refs];
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001406 if (pat->matching) {
1407 /*
1408 * "matching refs"; traditionally we pushed everything
1409 * including refs outside refs/heads/ hierarchy, but
1410 * that does not make much sense these days.
1411 */
Christian Couder59556542013-11-30 21:55:40 +01001412 if (!send_mirror && !starts_with(ref->name, "refs/heads/"))
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001413 return NULL;
1414 name = xstrdup(ref->name);
1415 }
1416 if (ret_pat)
1417 *ret_pat = pat;
1418 return name;
Daniel Barkalow8558fd92007-05-25 01:20:56 -04001419}
1420
Clemens Buchacher6d2bf962009-05-31 16:26:48 +02001421static struct ref **tail_ref(struct ref **head)
1422{
1423 struct ref **tail = head;
1424 while (*tail)
1425 tail = &((*tail)->next);
1426 return tail;
1427}
1428
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001429struct tips {
1430 struct commit **tip;
1431 int nr, alloc;
1432};
1433
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001434static void add_to_tips(struct tips *tips, const struct object_id *oid)
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001435{
1436 struct commit *commit;
1437
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001438 if (is_null_oid(oid))
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001439 return;
Stefan Beller21e1ee82018-06-28 18:21:57 -07001440 commit = lookup_commit_reference_gently(the_repository, oid, 1);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001441 if (!commit || (commit->object.flags & TMP_MARK))
1442 return;
1443 commit->object.flags |= TMP_MARK;
1444 ALLOC_GROW(tips->tip, tips->nr + 1, tips->alloc);
1445 tips->tip[tips->nr++] = commit;
1446}
1447
1448static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***dst_tail)
1449{
1450 struct string_list dst_tag = STRING_LIST_INIT_NODUP;
1451 struct string_list src_tag = STRING_LIST_INIT_NODUP;
1452 struct string_list_item *item;
1453 struct ref *ref;
1454 struct tips sent_tips;
1455
1456 /*
1457 * Collect everything we know they would have at the end of
1458 * this push, and collect all tags they have.
1459 */
1460 memset(&sent_tips, 0, sizeof(sent_tips));
1461 for (ref = *dst; ref; ref = ref->next) {
1462 if (ref->peer_ref &&
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001463 !is_null_oid(&ref->peer_ref->new_oid))
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001464 add_to_tips(&sent_tips, &ref->peer_ref->new_oid);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001465 else
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001466 add_to_tips(&sent_tips, &ref->old_oid);
Christian Couder59556542013-11-30 21:55:40 +01001467 if (starts_with(ref->name, "refs/tags/"))
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001468 string_list_append(&dst_tag, ref->name);
1469 }
1470 clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);
1471
Michael Haggerty3383e192014-11-25 09:02:35 +01001472 string_list_sort(&dst_tag);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001473
1474 /* Collect tags they do not have. */
1475 for (ref = src; ref; ref = ref->next) {
Christian Couder59556542013-11-30 21:55:40 +01001476 if (!starts_with(ref->name, "refs/tags/"))
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001477 continue; /* not a tag */
1478 if (string_list_has_string(&dst_tag, ref->name))
1479 continue; /* they already have it */
Stefan Beller0df8e962018-04-25 11:20:59 -07001480 if (oid_object_info(the_repository, &ref->new_oid, NULL) != OBJ_TAG)
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001481 continue; /* be conservative */
1482 item = string_list_append(&src_tag, ref->name);
1483 item->util = ref;
1484 }
1485 string_list_clear(&dst_tag, 0);
1486
1487 /*
1488 * At this point, src_tag lists tags that are missing from
1489 * dst, and sent_tips lists the tips we are pushing or those
1490 * that we know they already have. An element in the src_tag
1491 * that is an ancestor of any of the sent_tips needs to be
1492 * sent to the other side.
1493 */
1494 if (sent_tips.nr) {
Derrick Stolee85daa012018-11-02 06:14:49 -07001495 const int reachable_flag = 1;
1496 struct commit_list *found_commits;
1497 struct commit **src_commits;
1498 int nr_src_commits = 0, alloc_src_commits = 16;
1499 ALLOC_ARRAY(src_commits, alloc_src_commits);
1500
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001501 for_each_string_list_item(item, &src_tag) {
1502 struct ref *ref = item->util;
Derrick Stolee85daa012018-11-02 06:14:49 -07001503 struct commit *commit;
1504
1505 if (is_null_oid(&ref->new_oid))
1506 continue;
1507 commit = lookup_commit_reference_gently(the_repository,
1508 &ref->new_oid,
1509 1);
1510 if (!commit)
1511 /* not pushing a commit, which is not an error */
1512 continue;
1513
1514 ALLOC_GROW(src_commits, nr_src_commits + 1, alloc_src_commits);
1515 src_commits[nr_src_commits++] = commit;
1516 }
1517
1518 found_commits = get_reachable_subset(sent_tips.tip, sent_tips.nr,
1519 src_commits, nr_src_commits,
1520 reachable_flag);
1521
1522 for_each_string_list_item(item, &src_tag) {
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001523 struct ref *dst_ref;
Derrick Stolee85daa012018-11-02 06:14:49 -07001524 struct ref *ref = item->util;
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001525 struct commit *commit;
1526
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001527 if (is_null_oid(&ref->new_oid))
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001528 continue;
Stefan Beller21e1ee82018-06-28 18:21:57 -07001529 commit = lookup_commit_reference_gently(the_repository,
1530 &ref->new_oid,
brian m. carlsonbc832662017-05-06 22:10:10 +00001531 1);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001532 if (!commit)
1533 /* not pushing a commit, which is not an error */
1534 continue;
1535
1536 /*
1537 * Is this tag, which they do not have, reachable from
1538 * any of the commits we are sending?
1539 */
Derrick Stolee85daa012018-11-02 06:14:49 -07001540 if (!(commit->object.flags & reachable_flag))
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001541 continue;
1542
1543 /* Add it in */
1544 dst_ref = make_linked_ref(ref->name, dst_tail);
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001545 oidcpy(&dst_ref->new_oid, &ref->new_oid);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001546 dst_ref->peer_ref = copy_ref(ref);
1547 }
Derrick Stolee85daa012018-11-02 06:14:49 -07001548
1549 clear_commit_marks_many(nr_src_commits, src_commits, reachable_flag);
1550 free(src_commits);
1551 free_commit_list(found_commits);
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001552 }
Derrick Stolee85daa012018-11-02 06:14:49 -07001553
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001554 string_list_clear(&src_tag, 0);
1555 free(sent_tips.tip);
1556}
1557
Junio C Hamano47a59182013-07-08 13:56:53 -07001558struct ref *find_ref_by_name(const struct ref *list, const char *name)
1559{
1560 for ( ; list; list = list->next)
1561 if (!strcmp(list->name, name))
1562 return (struct ref *)list;
1563 return NULL;
1564}
1565
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001566static void prepare_ref_index(struct string_list *ref_index, struct ref *ref)
1567{
1568 for ( ; ref; ref = ref->next)
1569 string_list_append_nodup(ref_index, ref->name)->util = ref;
1570
Michael Haggerty3383e192014-11-25 09:02:35 +01001571 string_list_sort(ref_index);
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001572}
1573
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001574/*
Jeff Kingba928c12014-03-05 14:04:54 -05001575 * Given only the set of local refs, sanity-check the set of push
1576 * refspecs. We can't catch all errors that match_push_refs would,
1577 * but we can catch some errors early before even talking to the
1578 * remote side.
1579 */
Brandon Williamsafb1aed2018-05-16 15:58:22 -07001580int check_push_refs(struct ref *src, struct refspec *rs)
Jeff Kingba928c12014-03-05 14:04:54 -05001581{
Jeff Kingba928c12014-03-05 14:04:54 -05001582 int ret = 0;
1583 int i;
1584
Brandon Williamsafb1aed2018-05-16 15:58:22 -07001585 for (i = 0; i < rs->nr; i++) {
1586 struct refspec_item *item = &rs->items[i];
Jeff Kingba928c12014-03-05 14:04:54 -05001587
Jacob Kellerc0192df2020-09-30 14:25:29 -07001588 if (item->pattern || item->matching || item->negative)
Jeff Kingba928c12014-03-05 14:04:54 -05001589 continue;
1590
Brandon Williamsafb1aed2018-05-16 15:58:22 -07001591 ret |= match_explicit_lhs(src, item, NULL, NULL);
Jeff Kingba928c12014-03-05 14:04:54 -05001592 }
1593
Jeff Kingba928c12014-03-05 14:04:54 -05001594 return ret;
1595}
1596
1597/*
Junio C Hamano29753cd2011-09-09 11:54:58 -07001598 * Given the set of refs the local repository has, the set of refs the
1599 * remote repository has, and the refspec used for push, determine
1600 * what remote refs we will update and with what value by setting
1601 * peer_ref (which object is being pushed) and force (if the push is
1602 * forced) in elements of "dst". The function may add new elements to
1603 * dst (e.g. pushing to a new branch, done in match_explicit_refs).
Junio C Hamano54a8ad92007-06-08 23:22:58 -07001604 */
Junio C Hamano29753cd2011-09-09 11:54:58 -07001605int match_push_refs(struct ref *src, struct ref **dst,
Brandon Williams5c7ec842018-05-16 15:58:21 -07001606 struct refspec *rs, int flags)
Daniel Barkalow6b628162007-05-12 11:45:59 -04001607{
Andy Whitcroft28b9d6e2007-11-09 23:32:10 +00001608 int send_all = flags & MATCH_REFS_ALL;
1609 int send_mirror = flags & MATCH_REFS_MIRROR;
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001610 int send_prune = flags & MATCH_REFS_PRUNE;
Jay Soffian5f48cb92009-02-25 03:32:17 -05001611 int errs;
Felipe Contrerasb1d8b1f2012-02-23 00:43:38 +02001612 struct ref *ref, **dst_tail = tail_ref(dst);
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001613 struct string_list dst_ref_index = STRING_LIST_INIT_NODUP;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001614
Brandon Williams5c7ec842018-05-16 15:58:21 -07001615 /* If no refspec is provided, use the default ":" */
1616 if (!rs->nr)
1617 refspec_append(rs, ":");
1618
1619 errs = match_explicit_refs(src, *dst, &dst_tail, rs);
Daniel Barkalow6b628162007-05-12 11:45:59 -04001620
1621 /* pick the remainder */
Felipe Contrerasb1d8b1f2012-02-23 00:43:38 +02001622 for (ref = src; ref; ref = ref->next) {
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001623 struct string_list_item *dst_item;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001624 struct ref *dst_peer;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001625 const struct refspec_item *pat = NULL;
Alex Riesen6e66bf32007-06-08 01:43:05 +02001626 char *dst_name;
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001627
Brandon Williams5c7ec842018-05-16 15:58:21 -07001628 dst_name = get_ref_match(rs, ref, send_mirror, FROM_SRC, &pat);
Felipe Contrerasdb70a042012-02-23 00:43:39 +02001629 if (!dst_name)
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001630 continue;
1631
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001632 if (!dst_ref_index.nr)
1633 prepare_ref_index(&dst_ref_index, *dst);
1634
1635 dst_item = string_list_lookup(&dst_ref_index, dst_name);
1636 dst_peer = dst_item ? dst_item->util : NULL;
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001637 if (dst_peer) {
1638 if (dst_peer->peer_ref)
1639 /* We're already sending something to this ref. */
1640 goto free_name;
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001641 } else {
1642 if (pat->matching && !(send_all || send_mirror))
1643 /*
1644 * Remote doesn't have it, and we have no
1645 * explicit pattern, and we don't have
Justin Lebar01689902014-03-31 15:11:46 -07001646 * --all or --mirror.
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001647 */
1648 goto free_name;
1649
Daniel Barkalow6b628162007-05-12 11:45:59 -04001650 /* Create a new one and link it */
Clemens Buchacher6d2bf962009-05-31 16:26:48 +02001651 dst_peer = make_linked_ref(dst_name, &dst_tail);
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001652 oidcpy(&dst_peer->new_oid, &ref->new_oid);
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001653 string_list_insert(&dst_ref_index,
1654 dst_peer->name)->util = dst_peer;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001655 }
Felipe Contrerasb1d8b1f2012-02-23 00:43:38 +02001656 dst_peer->peer_ref = copy_ref(ref);
Paolo Bonzinia83619d2008-04-28 11:32:12 -04001657 dst_peer->force = pat->force;
Alex Riesen6e66bf32007-06-08 01:43:05 +02001658 free_name:
1659 free(dst_name);
Daniel Barkalow6b628162007-05-12 11:45:59 -04001660 }
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001661
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001662 string_list_clear(&dst_ref_index, 0);
1663
Junio C Hamanoc2aba152013-03-04 12:09:50 -08001664 if (flags & MATCH_REFS_FOLLOW_TAGS)
1665 add_missing_tags(src, dst, &dst_tail);
1666
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001667 if (send_prune) {
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001668 struct string_list src_ref_index = STRING_LIST_INIT_NODUP;
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001669 /* check for missing refs on the remote */
1670 for (ref = *dst; ref; ref = ref->next) {
1671 char *src_name;
1672
1673 if (ref->peer_ref)
1674 /* We're already sending something to this ref. */
1675 continue;
1676
Brandon Williams5c7ec842018-05-16 15:58:21 -07001677 src_name = get_ref_match(rs, ref, send_mirror, FROM_DST, NULL);
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001678 if (src_name) {
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001679 if (!src_ref_index.nr)
1680 prepare_ref_index(&src_ref_index, src);
1681 if (!string_list_has_string(&src_ref_index,
1682 src_name))
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001683 ref->peer_ref = alloc_delete_ref();
1684 free(src_name);
1685 }
1686 }
Brandon Caseyf1bd15a2013-07-08 01:58:39 -07001687 string_list_clear(&src_ref_index, 0);
Felipe Contreras6ddba5e2012-02-23 00:43:41 +02001688 }
Brandon Williams8ca69372018-05-16 15:57:57 -07001689
Jacob Kellerc0192df2020-09-30 14:25:29 -07001690 *dst = apply_negative_refspecs(*dst, rs);
1691
Jay Soffian5f48cb92009-02-25 03:32:17 -05001692 if (errs)
1693 return -1;
Daniel Barkalow6b628162007-05-12 11:45:59 -04001694 return 0;
1695}
Daniel Barkalowcf818342007-09-10 23:02:56 -04001696
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001697void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001698 int force_update)
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001699{
1700 struct ref *ref;
1701
1702 for (ref = remote_refs; ref; ref = ref->next) {
Chris Rorvick8c5f6f72012-11-29 19:41:36 -06001703 int force_ref_update = ref->force || force_update;
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001704 int reject_reason = 0;
Chris Rorvick8c5f6f72012-11-29 19:41:36 -06001705
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001706 if (ref->peer_ref)
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001707 oidcpy(&ref->new_oid, &ref->peer_ref->new_oid);
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001708 else if (!send_mirror)
1709 continue;
1710
brian m. carlsonf4e54d02015-11-10 02:22:20 +00001711 ref->deletion = is_null_oid(&ref->new_oid);
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001712 if (!ref->deletion &&
Jeff King4a7e27e2018-08-28 17:22:40 -04001713 oideq(&ref->old_oid, &ref->new_oid)) {
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001714 ref->status = REF_STATUS_UPTODATE;
1715 continue;
1716 }
1717
Chris Rorvicka272b282012-11-29 19:41:40 -06001718 /*
Andrew Wheelerb2e93f82016-01-29 17:18:42 -06001719 * If the remote ref has moved and is now different
1720 * from what we expect, reject any push.
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001721 *
1722 * It also is an error if the user told us to check
1723 * with the remote-tracking branch to find the value
1724 * to expect, but we did not have such a tracking
1725 * branch.
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05301726 *
1727 * If the tip of the remote-tracking ref is unreachable
1728 * from any reflog entry of its local ref indicating a
1729 * possible update since checkout; reject the push.
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001730 */
1731 if (ref->expect_old_sha1) {
Jeff King9001dc22018-08-28 17:22:48 -04001732 if (!oideq(&ref->old_oid, &ref->old_oid_expect))
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001733 reject_reason = REF_STATUS_REJECT_STALE;
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05301734 else if (ref->check_reachable && ref->unreachable)
1735 reject_reason =
1736 REF_STATUS_REJECT_REMOTE_UPDATED;
Andrew Wheelerb2e93f82016-01-29 17:18:42 -06001737 else
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05301738 /*
1739 * If the ref isn't stale, and is reachable
Andrei Rybakabcb66c2021-06-11 13:18:50 +02001740 * from one of the reflog entries of
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05301741 * the local branch, force the update.
1742 */
Andrew Wheelerb2e93f82016-01-29 17:18:42 -06001743 force_ref_update = 1;
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001744 }
1745
1746 /*
Andrew Wheelerb2e93f82016-01-29 17:18:42 -06001747 * If the update isn't already rejected then check
1748 * the usual "must fast-forward" rules.
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001749 *
Junio C Hamano256b9d72013-01-16 13:02:27 -08001750 * Decide whether an individual refspec A:B can be
1751 * pushed. The push will succeed if any of the
1752 * following are true:
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001753 *
Chris Rorvicka272b282012-11-29 19:41:40 -06001754 * (1) the remote reference B does not exist
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001755 *
Chris Rorvicka272b282012-11-29 19:41:40 -06001756 * (2) the remote reference B is being removed (i.e.,
1757 * pushing :B where no source is specified)
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001758 *
Junio C Hamano256b9d72013-01-16 13:02:27 -08001759 * (3) the destination is not under refs/tags/, and
1760 * if the old and new value is a commit, the new
1761 * is a descendant of the old.
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001762 *
Chris Rorvicka272b282012-11-29 19:41:40 -06001763 * (4) it is forced using the +A:B notation, or by
1764 * passing the --force argument
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001765 */
1766
Andrew Wheelerb2e93f82016-01-29 17:18:42 -06001767 if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
Christian Couder59556542013-11-30 21:55:40 +01001768 if (starts_with(ref->name, "refs/tags/"))
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001769 reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
Ævar Arnfjörð Bjarmasonbc726bd2023-03-28 15:58:50 +02001770 else if (!repo_has_object_file(the_repository, &ref->old_oid))
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001771 reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
Stefan Beller21e1ee82018-06-28 18:21:57 -07001772 else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) ||
1773 !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1))
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001774 reject_reason = REF_STATUS_REJECT_NEEDS_FORCE;
brian m. carlson6f3d57b2015-11-10 02:22:25 +00001775 else if (!ref_newer(&ref->new_oid, &ref->old_oid))
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001776 reject_reason = REF_STATUS_REJECT_NONFASTFORWARD;
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001777 }
Junio C Hamano631b5ef2013-07-08 14:42:40 -07001778
1779 /*
1780 * "--force" will defeat any rejection implemented
1781 * by the rules above.
1782 */
1783 if (!force_ref_update)
1784 ref->status = reject_reason;
1785 else if (reject_reason)
1786 ref->forced_update = 1;
Tay Ray Chuan20e8b462010-01-08 10:12:42 +08001787 }
1788}
1789
Glen Choo56eed342021-11-17 16:53:24 -08001790static void set_merge(struct remote_state *remote_state, struct branch *ret)
Junio C Hamano05e73682014-10-14 14:42:04 -07001791{
Jeff King9e3751d2015-05-21 00:45:13 -04001792 struct remote *remote;
Junio C Hamano05e73682014-10-14 14:42:04 -07001793 char *ref;
brian m. carlsonfcd30b12015-11-10 02:22:30 +00001794 struct object_id oid;
Junio C Hamano05e73682014-10-14 14:42:04 -07001795 int i;
1796
Jeff Kingee2499f2015-05-21 00:45:09 -04001797 if (!ret)
1798 return; /* no branch */
1799 if (ret->merge)
1800 return; /* already run */
1801 if (!ret->remote_name || !ret->merge_nr) {
1802 /*
1803 * no merge config; let's make sure we don't confuse callers
1804 * with a non-zero merge_nr but a NULL merge
1805 */
1806 ret->merge_nr = 0;
1807 return;
1808 }
1809
Glen Choo56eed342021-11-17 16:53:24 -08001810 remote = remotes_remote_get(remote_state, ret->remote_name);
Jeff King9e3751d2015-05-21 00:45:13 -04001811
René Scharfeca56dad2021-03-13 17:17:22 +01001812 CALLOC_ARRAY(ret->merge, ret->merge_nr);
Junio C Hamano05e73682014-10-14 14:42:04 -07001813 for (i = 0; i < ret->merge_nr; i++) {
1814 ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
1815 ret->merge[i]->src = xstrdup(ret->merge_name[i]);
Jeff King9e3751d2015-05-21 00:45:13 -04001816 if (!remote_find_tracking(remote, ret->merge[i]) ||
Junio C Hamano05e73682014-10-14 14:42:04 -07001817 strcmp(ret->remote_name, "."))
1818 continue;
Ævar Arnfjörð Bjarmason12cb1c12023-03-28 15:58:54 +02001819 if (repo_dwim_ref(the_repository, ret->merge_name[i],
1820 strlen(ret->merge_name[i]), &oid, &ref,
1821 0) == 1)
Junio C Hamano05e73682014-10-14 14:42:04 -07001822 ret->merge[i]->dst = ref;
1823 else
1824 ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
1825 }
1826}
1827
Daniel Barkalowcf818342007-09-10 23:02:56 -04001828struct branch *branch_get(const char *name)
1829{
1830 struct branch *ret;
1831
Glen Choo085b98f2021-11-17 16:53:23 -08001832 read_config(the_repository);
Daniel Barkalowcf818342007-09-10 23:02:56 -04001833 if (!name || !*name || !strcmp(name, "HEAD"))
Glen Choofd3cb052021-11-17 16:53:22 -08001834 ret = the_repository->remote_state->current_branch;
Daniel Barkalowcf818342007-09-10 23:02:56 -04001835 else
Glen Choo085b98f2021-11-17 16:53:23 -08001836 ret = make_branch(the_repository->remote_state, name,
1837 strlen(name));
Glen Choo56eed342021-11-17 16:53:24 -08001838 set_merge(the_repository->remote_state, ret);
Daniel Barkalowcf818342007-09-10 23:02:56 -04001839 return ret;
1840}
1841
1842int branch_has_merge_config(struct branch *branch)
1843{
1844 return branch && !!branch->merge;
1845}
1846
Shawn O. Pearce85682c12007-09-18 04:54:53 -04001847int branch_merge_matches(struct branch *branch,
1848 int i,
1849 const char *refname)
Daniel Barkalowcf818342007-09-10 23:02:56 -04001850{
Shawn O. Pearce85682c12007-09-18 04:54:53 -04001851 if (!branch || i < 0 || i >= branch->merge_nr)
Daniel Barkalowcf818342007-09-10 23:02:56 -04001852 return 0;
Michael Haggerty54457fe2014-01-14 04:16:07 +01001853 return refname_match(branch->merge[i]->src, refname);
Daniel Barkalowcf818342007-09-10 23:02:56 -04001854}
Daniel Barkalowd71ab172007-09-10 23:03:08 -04001855
Jeff King060e7762016-04-25 17:15:23 -04001856__attribute__((format (printf,2,3)))
Jeff King3a429d02015-05-21 00:45:32 -04001857static const char *error_buf(struct strbuf *err, const char *fmt, ...)
Jeff Kinga9f9f8c2015-05-21 00:45:28 -04001858{
Jeff King3a429d02015-05-21 00:45:32 -04001859 if (err) {
1860 va_list ap;
1861 va_start(ap, fmt);
1862 strbuf_vaddf(err, fmt, ap);
1863 va_end(ap);
1864 }
1865 return NULL;
1866}
1867
1868const char *branch_get_upstream(struct branch *branch, struct strbuf *err)
1869{
1870 if (!branch)
1871 return error_buf(err, _("HEAD does not point to a branch"));
Jeff King1ca41a12015-05-21 20:46:43 -04001872
1873 if (!branch->merge || !branch->merge[0]) {
1874 /*
1875 * no merge config; is it because the user didn't define any,
1876 * or because it is not a real branch, and get_branch
1877 * auto-vivified it?
1878 */
Jeff King3a429d02015-05-21 00:45:32 -04001879 if (!ref_exists(branch->refname))
1880 return error_buf(err, _("no such branch: '%s'"),
1881 branch->name);
Jeff King1ca41a12015-05-21 20:46:43 -04001882 return error_buf(err,
1883 _("no upstream configured for branch '%s'"),
1884 branch->name);
1885 }
1886
1887 if (!branch->merge[0]->dst)
Jeff King3a429d02015-05-21 00:45:32 -04001888 return error_buf(err,
1889 _("upstream branch '%s' not stored as a remote-tracking branch"),
1890 branch->merge[0]->src);
Jeff King3a429d02015-05-21 00:45:32 -04001891
Jeff Kinga9f9f8c2015-05-21 00:45:28 -04001892 return branch->merge[0]->dst;
1893}
1894
Jeff Kinge291c752015-05-21 00:45:36 -04001895static const char *tracking_for_push_dest(struct remote *remote,
1896 const char *refname,
1897 struct strbuf *err)
1898{
1899 char *ret;
1900
Brandon Williamsd0004142018-05-16 15:58:11 -07001901 ret = apply_refspecs(&remote->fetch, refname);
Jeff Kinge291c752015-05-21 00:45:36 -04001902 if (!ret)
1903 return error_buf(err,
1904 _("push destination '%s' on remote '%s' has no local tracking branch"),
1905 refname, remote->name);
1906 return ret;
1907}
1908
Glen Choo56eed342021-11-17 16:53:24 -08001909static const char *branch_get_push_1(struct remote_state *remote_state,
1910 struct branch *branch, struct strbuf *err)
Jeff Kinge291c752015-05-21 00:45:36 -04001911{
1912 struct remote *remote;
1913
Glen Choo56eed342021-11-17 16:53:24 -08001914 remote = remotes_remote_get(
1915 remote_state,
1916 remotes_pushremote_for_branch(remote_state, branch, NULL));
Jeff Kinge291c752015-05-21 00:45:36 -04001917 if (!remote)
1918 return error_buf(err,
1919 _("branch '%s' has no remote for pushing"),
1920 branch->name);
1921
Brandon Williams6bdb3042018-05-16 15:58:00 -07001922 if (remote->push.nr) {
Jeff Kinge291c752015-05-21 00:45:36 -04001923 char *dst;
1924 const char *ret;
1925
Brandon Williamsd0004142018-05-16 15:58:11 -07001926 dst = apply_refspecs(&remote->push, branch->refname);
Jeff Kinge291c752015-05-21 00:45:36 -04001927 if (!dst)
1928 return error_buf(err,
1929 _("push refspecs for '%s' do not include '%s'"),
1930 remote->name, branch->name);
1931
1932 ret = tracking_for_push_dest(remote, dst, err);
1933 free(dst);
1934 return ret;
1935 }
1936
1937 if (remote->mirror)
1938 return tracking_for_push_dest(remote, branch->refname, err);
1939
1940 switch (push_default) {
1941 case PUSH_DEFAULT_NOTHING:
1942 return error_buf(err, _("push has no destination (push.default is 'nothing')"));
1943
1944 case PUSH_DEFAULT_MATCHING:
1945 case PUSH_DEFAULT_CURRENT:
1946 return tracking_for_push_dest(remote, branch->refname, err);
1947
1948 case PUSH_DEFAULT_UPSTREAM:
1949 return branch_get_upstream(branch, err);
1950
1951 case PUSH_DEFAULT_UNSPECIFIED:
1952 case PUSH_DEFAULT_SIMPLE:
1953 {
1954 const char *up, *cur;
1955
1956 up = branch_get_upstream(branch, err);
1957 if (!up)
1958 return NULL;
1959 cur = tracking_for_push_dest(remote, branch->refname, err);
1960 if (!cur)
1961 return NULL;
1962 if (strcmp(cur, up))
1963 return error_buf(err,
1964 _("cannot resolve 'simple' push to a single destination"));
1965 return cur;
1966 }
1967 }
1968
Johannes Schindelin033abf92018-05-02 11:38:39 +02001969 BUG("unhandled push situation");
Jeff Kinge291c752015-05-21 00:45:36 -04001970}
1971
1972const char *branch_get_push(struct branch *branch, struct strbuf *err)
1973{
Glen Choo56eed342021-11-17 16:53:24 -08001974 read_config(the_repository);
Glen Choo4a2dcb12021-11-17 16:53:25 -08001975 die_on_missing_branch(the_repository, branch);
1976
Kyle Meyerb10731f2017-01-06 20:12:15 -05001977 if (!branch)
1978 return error_buf(err, _("HEAD does not point to a branch"));
1979
Jeff Kinge291c752015-05-21 00:45:36 -04001980 if (!branch->push_tracking_ref)
Glen Choo56eed342021-11-17 16:53:24 -08001981 branch->push_tracking_ref = branch_get_push_1(
1982 the_repository->remote_state, branch, err);
Jeff Kinge291c752015-05-21 00:45:36 -04001983 return branch->push_tracking_ref;
1984}
1985
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01001986static int ignore_symref_update(const char *refname, struct strbuf *scratch)
Junio C Hamanof8fb9712012-12-11 13:00:52 -08001987{
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01001988 return !refs_read_symbolic_ref(get_main_ref_store(the_repository), refname, scratch);
Junio C Hamanof8fb9712012-12-11 13:00:52 -08001989}
1990
Michael Haggertyf166db22013-10-30 06:32:56 +01001991/*
1992 * Create and return a list of (struct ref) consisting of copies of
1993 * each remote_ref that matches refspec. refspec must be a pattern.
1994 * Fill in the copies' peer_ref to describe the local tracking refs to
1995 * which they map. Omit any references that would map to an existing
1996 * local symbolic ref.
1997 */
Daniel Barkalow45773702007-10-29 21:05:40 -04001998static struct ref *get_expanded_map(const struct ref *remote_refs,
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07001999 const struct refspec_item *refspec)
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002000{
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01002001 struct strbuf scratch = STRBUF_INIT;
Daniel Barkalow45773702007-10-29 21:05:40 -04002002 const struct ref *ref;
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002003 struct ref *ret = NULL;
2004 struct ref **tail = &ret;
2005
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002006 for (ref = remote_refs; ref; ref = ref->next) {
Michael Haggertye31a17f2013-10-30 06:32:57 +01002007 char *expn_name = NULL;
2008
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01002009 strbuf_reset(&scratch);
2010
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002011 if (strchr(ref->name, '^'))
2012 continue; /* a dereference item */
Daniel Barkalowe9282132009-03-07 01:11:34 -05002013 if (match_name_with_pattern(refspec->src, ref->name,
Junio C Hamanof8fb9712012-12-11 13:00:52 -08002014 refspec->dst, &expn_name) &&
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01002015 !ignore_symref_update(expn_name, &scratch)) {
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002016 struct ref *cpy = copy_ref(ref);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002017
Daniel Barkalowe9282132009-03-07 01:11:34 -05002018 cpy->peer_ref = alloc_ref(expn_name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002019 if (refspec->force)
2020 cpy->peer_ref->force = 1;
2021 *tail = cpy;
2022 tail = &cpy->next;
2023 }
Michael Haggertye31a17f2013-10-30 06:32:57 +01002024 free(expn_name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002025 }
2026
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +01002027 strbuf_release(&scratch);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002028 return ret;
2029}
2030
Daniel Barkalow45773702007-10-29 21:05:40 -04002031static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const char *name)
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002032{
Daniel Barkalow45773702007-10-29 21:05:40 -04002033 const struct ref *ref;
Junio C Hamano60650a42018-08-01 09:22:37 -07002034 const struct ref *best_match = NULL;
2035 int best_score = 0;
2036
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002037 for (ref = refs; ref; ref = ref->next) {
Junio C Hamano60650a42018-08-01 09:22:37 -07002038 int score = refname_match(name, ref->name);
2039
2040 if (best_score < score) {
2041 best_match = ref;
2042 best_score = score;
2043 }
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002044 }
Junio C Hamano60650a42018-08-01 09:22:37 -07002045 return best_match;
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002046}
2047
Daniel Barkalow45773702007-10-29 21:05:40 -04002048struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002049{
Daniel Barkalow45773702007-10-29 21:05:40 -04002050 const struct ref *ref = find_ref_by_name_abbrev(remote_refs, name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002051
2052 if (!ref)
Junio C Hamano9ad7c5a2007-10-26 23:09:48 -07002053 return NULL;
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002054
2055 return copy_ref(ref);
2056}
2057
2058static struct ref *get_local_ref(const char *name)
2059{
Clemens Buchacher3eb96992009-06-17 15:38:36 +02002060 if (!name || name[0] == '\0')
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002061 return NULL;
2062
Christian Couder59556542013-11-30 21:55:40 +01002063 if (starts_with(name, "refs/"))
René Scharfe59c69c02008-10-18 10:44:18 +02002064 return alloc_ref(name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002065
Christian Couder59556542013-11-30 21:55:40 +01002066 if (starts_with(name, "heads/") ||
2067 starts_with(name, "tags/") ||
2068 starts_with(name, "remotes/"))
René Scharfe80097682008-10-18 10:37:40 +02002069 return alloc_ref_with_prefix("refs/", 5, name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002070
René Scharfe80097682008-10-18 10:37:40 +02002071 return alloc_ref_with_prefix("refs/heads/", 11, name);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002072}
2073
Daniel Barkalow45773702007-10-29 21:05:40 -04002074int get_fetch_map(const struct ref *remote_refs,
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07002075 const struct refspec_item *refspec,
Junio C Hamano9ad7c5a2007-10-26 23:09:48 -07002076 struct ref ***tail,
2077 int missing_ok)
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002078{
Daniel Barkalowef00d152008-03-17 22:05:23 -04002079 struct ref *ref_map, **rmp;
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002080
Jacob Kellerc0192df2020-09-30 14:25:29 -07002081 if (refspec->negative)
2082 return 0;
2083
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002084 if (refspec->pattern) {
2085 ref_map = get_expanded_map(remote_refs, refspec);
2086 } else {
Junio C Hamano9ad7c5a2007-10-26 23:09:48 -07002087 const char *name = refspec->src[0] ? refspec->src : "HEAD";
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002088
Junio C Hamano6e7b66e2013-01-29 14:02:15 -08002089 if (refspec->exact_sha1) {
2090 ref_map = alloc_ref(name);
brian m. carlsonf4e54d02015-11-10 02:22:20 +00002091 get_oid_hex(name, &ref_map->old_oid);
Brandon Williams73302052018-06-27 15:30:23 -07002092 ref_map->exact_oid = 1;
Junio C Hamano6e7b66e2013-01-29 14:02:15 -08002093 } else {
2094 ref_map = get_remote_ref(remote_refs, name);
2095 }
Junio C Hamano9ad7c5a2007-10-26 23:09:48 -07002096 if (!missing_ok && !ref_map)
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01002097 die(_("couldn't find remote ref %s"), name);
Junio C Hamano9ad7c5a2007-10-26 23:09:48 -07002098 if (ref_map) {
2099 ref_map->peer_ref = get_local_ref(refspec->dst);
2100 if (ref_map->peer_ref && refspec->force)
2101 ref_map->peer_ref->force = 1;
2102 }
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002103 }
2104
Daniel Barkalowef00d152008-03-17 22:05:23 -04002105 for (rmp = &ref_map; *rmp; ) {
2106 if ((*rmp)->peer_ref) {
Christian Couder59556542013-11-30 21:55:40 +01002107 if (!starts_with((*rmp)->peer_ref->name, "refs/") ||
Junio C Hamano5c08c1f2012-05-04 15:35:18 -07002108 check_refname_format((*rmp)->peer_ref->name, 0)) {
Daniel Barkalowef00d152008-03-17 22:05:23 -04002109 struct ref *ignore = *rmp;
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01002110 error(_("* Ignoring funny ref '%s' locally"),
Daniel Barkalowef00d152008-03-17 22:05:23 -04002111 (*rmp)->peer_ref->name);
2112 *rmp = (*rmp)->next;
2113 free(ignore->peer_ref);
2114 free(ignore);
2115 continue;
2116 }
2117 }
2118 rmp = &((*rmp)->next);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002119 }
2120
Alex Riesen8f70a762007-10-12 22:40:04 +02002121 if (ref_map)
2122 tail_link_ref(ref_map, tail);
Daniel Barkalowd71ab172007-09-10 23:03:08 -04002123
2124 return 0;
2125}
Daniel Barkalowbe885d92008-04-26 15:53:12 -04002126
2127int resolve_remote_symref(struct ref *ref, struct ref *list)
2128{
2129 if (!ref->symref)
2130 return 0;
2131 for (; list; list = list->next)
2132 if (!strcmp(ref->symref, list->name)) {
brian m. carlsonf4e54d02015-11-10 02:22:20 +00002133 oidcpy(&ref->old_oid, &list->old_oid);
Daniel Barkalowbe885d92008-04-26 15:53:12 -04002134 return 0;
2135 }
2136 return 1;
2137}
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002138
2139/*
Damien Robertc646d092019-04-16 14:16:46 +02002140 * Compute the commit ahead/behind values for the pair branch_name, base.
Jeff Hostetlerd7d1b492018-01-09 18:50:15 +00002141 *
2142 * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
2143 * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
2144 * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
2145 * set to zero).
2146 *
Damien Robertc646d092019-04-16 14:16:46 +02002147 * Returns -1 if num_ours and num_theirs could not be filled in (e.g., ref
2148 * does not exist). Returns 0 if the commits are identical. Returns 1 if
2149 * commits are different.
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002150 */
Damien Robertc646d092019-04-16 14:16:46 +02002151
2152static int stat_branch_pair(const char *branch_name, const char *base,
2153 int *num_ours, int *num_theirs,
2154 enum ahead_behind_flags abf)
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002155{
brian m. carlsonfcd30b12015-11-10 02:22:30 +00002156 struct object_id oid;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002157 struct commit *ours, *theirs;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002158 struct rev_info revs;
Ævar Arnfjörð Bjarmasonf92dbdb2022-08-02 17:33:16 +02002159 struct setup_revision_opt opt = {
2160 .free_removed_argv_elements = 1,
2161 };
Jeff Kingc972bf42020-07-28 16:25:12 -04002162 struct strvec argv = STRVEC_INIT;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002163
Jiang Xinf2e08732013-08-26 15:02:48 +08002164 /* Cannot stat if what we used to build on no longer exists */
brian m. carlson34c290a2017-10-15 22:06:56 +00002165 if (read_ref(base, &oid))
Jiang Xinf2e08732013-08-26 15:02:48 +08002166 return -1;
Stefan Beller2122f672018-06-28 18:21:58 -07002167 theirs = lookup_commit_reference(the_repository, &oid);
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002168 if (!theirs)
Jiang Xinf2e08732013-08-26 15:02:48 +08002169 return -1;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002170
Damien Robertc646d092019-04-16 14:16:46 +02002171 if (read_ref(branch_name, &oid))
Jiang Xinf2e08732013-08-26 15:02:48 +08002172 return -1;
Stefan Beller2122f672018-06-28 18:21:58 -07002173 ours = lookup_commit_reference(the_repository, &oid);
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002174 if (!ours)
Jiang Xinf2e08732013-08-26 15:02:48 +08002175 return -1;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002176
Jeff Hostetlerd7d1b492018-01-09 18:50:15 +00002177 *num_theirs = *num_ours = 0;
2178
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002179 /* are we the same? */
Jeff Hostetlerd7d1b492018-01-09 18:50:15 +00002180 if (theirs == ours)
Jeff King979cb242015-05-21 20:49:11 -04002181 return 0;
Jeff Hostetlerd7d1b492018-01-09 18:50:15 +00002182 if (abf == AHEAD_BEHIND_QUICK)
2183 return 1;
Jeff Hostetlerfd9b5442018-01-09 18:50:16 +00002184 if (abf != AHEAD_BEHIND_FULL)
Damien Robertc646d092019-04-16 14:16:46 +02002185 BUG("stat_branch_pair: invalid abf '%d'", abf);
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002186
Junio C Hamano8fbf8792009-04-21 16:32:18 -07002187 /* Run "rev-list --left-right ours...theirs" internally... */
Jeff Kingc972bf42020-07-28 16:25:12 -04002188 strvec_push(&argv, ""); /* ignored */
2189 strvec_push(&argv, "--left-right");
2190 strvec_pushf(&argv, "%s...%s",
Jeff Kingf6d89422020-07-28 16:26:31 -04002191 oid_to_hex(&ours->object.oid),
2192 oid_to_hex(&theirs->object.oid));
Jeff Kingc972bf42020-07-28 16:25:12 -04002193 strvec_push(&argv, "--");
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002194
Nguyễn Thái Ngọc Duy2abf3502018-09-21 17:57:38 +02002195 repo_init_revisions(the_repository, &revs, NULL);
Ævar Arnfjörð Bjarmasonf92dbdb2022-08-02 17:33:16 +02002196 setup_revisions(argv.nr, argv.v, &revs, &opt);
Stefan Beller81c3ce32014-08-10 23:33:26 +02002197 if (prepare_revision_walk(&revs))
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01002198 die(_("revision walk setup failed"));
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002199
2200 /* ... and count the commits on each side. */
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002201 while (1) {
2202 struct commit *c = get_revision(&revs);
2203 if (!c)
2204 break;
2205 if (c->object.flags & SYMMETRIC_LEFT)
2206 (*num_ours)++;
2207 else
2208 (*num_theirs)++;
2209 }
Junio C Hamanoc0234b22008-07-03 12:09:48 -07002210
2211 /* clear object flags smudged by the above traversal */
2212 clear_commit_marks(ours, ALL_REV_FLAGS);
2213 clear_commit_marks(theirs, ALL_REV_FLAGS);
Jeff King0b282cc2015-09-24 17:07:58 -04002214
Jeff Kingc972bf42020-07-28 16:25:12 -04002215 strvec_clear(&argv);
Ævar Arnfjörð Bjarmason2108fe42022-04-13 22:01:36 +02002216 release_revisions(&revs);
Jeff Hostetlerd7d1b492018-01-09 18:50:15 +00002217 return 1;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002218}
2219
2220/*
Damien Robertc646d092019-04-16 14:16:46 +02002221 * Lookup the tracking branch for the given branch and if present, optionally
2222 * compute the commit ahead/behind values for the pair.
2223 *
2224 * If for_push is true, the tracking branch refers to the push branch,
2225 * otherwise it refers to the upstream branch.
2226 *
2227 * The name of the tracking branch (or NULL if it is not defined) is
2228 * returned via *tracking_name, if it is not itself NULL.
2229 *
2230 * If abf is AHEAD_BEHIND_FULL, compute the full ahead/behind and return the
2231 * counts in *num_ours and *num_theirs. If abf is AHEAD_BEHIND_QUICK, skip
2232 * the (potentially expensive) a/b computation (*num_ours and *num_theirs are
2233 * set to zero).
2234 *
2235 * Returns -1 if num_ours and num_theirs could not be filled in (e.g., no
2236 * upstream defined, or ref does not exist). Returns 0 if the commits are
2237 * identical. Returns 1 if commits are different.
2238 */
2239int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,
2240 const char **tracking_name, int for_push,
2241 enum ahead_behind_flags abf)
2242{
2243 const char *base;
2244
2245 /* Cannot stat unless we are marked to build on top of somebody else. */
2246 base = for_push ? branch_get_push(branch, NULL) :
2247 branch_get_upstream(branch, NULL);
2248 if (tracking_name)
2249 *tracking_name = base;
2250 if (!base)
2251 return -1;
2252
2253 return stat_branch_pair(branch->refname, base, num_ours, num_theirs, abf);
2254}
2255
2256/*
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002257 * Return true when there is anything to report, otherwise false.
2258 */
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002259int format_tracking_info(struct branch *branch, struct strbuf *sb,
2260 enum ahead_behind_flags abf)
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002261{
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002262 int ours, theirs, sti;
Jeff King979cb242015-05-21 20:49:11 -04002263 const char *full_base;
Stefan Beller2f50bab2014-08-10 21:43:33 +02002264 char *base;
Jiang Xinf2e08732013-08-26 15:02:48 +08002265 int upstream_is_gone = 0;
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002266
Damien Robertc646d092019-04-16 14:16:46 +02002267 sti = stat_tracking_info(branch, &ours, &theirs, &full_base, 0, abf);
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002268 if (sti < 0) {
Jeff King979cb242015-05-21 20:49:11 -04002269 if (!full_base)
2270 return 0;
Jiang Xinf2e08732013-08-26 15:02:48 +08002271 upstream_is_gone = 1;
Jiang Xinf2e08732013-08-26 15:02:48 +08002272 }
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002273
Jeff King979cb242015-05-21 20:49:11 -04002274 base = shorten_unambiguous_ref(full_base, 0);
Jiang Xinf2e08732013-08-26 15:02:48 +08002275 if (upstream_is_gone) {
2276 strbuf_addf(sb,
2277 _("Your branch is based on '%s', but the upstream is gone.\n"),
2278 base);
Ben Boeckeled9bff02021-08-23 12:44:00 +02002279 if (advice_enabled(ADVICE_STATUS_HINTS))
René Scharfea22ae752016-09-15 20:31:00 +02002280 strbuf_addstr(sb,
Jiang Xinf2e08732013-08-26 15:02:48 +08002281 _(" (use \"git branch --unset-upstream\" to fixup)\n"));
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002282 } else if (!sti) {
Jiang Xinf2234592013-08-26 15:02:49 +08002283 strbuf_addf(sb,
Martin Ågren7560f542017-08-23 19:49:35 +02002284 _("Your branch is up to date with '%s'.\n"),
Jiang Xinf2234592013-08-26 15:02:49 +08002285 base);
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002286 } else if (abf == AHEAD_BEHIND_QUICK) {
2287 strbuf_addf(sb,
2288 _("Your branch and '%s' refer to different commits.\n"),
2289 base);
Ben Boeckeled9bff02021-08-23 12:44:00 +02002290 if (advice_enabled(ADVICE_STATUS_HINTS))
Jeff Hostetlerf39a7572018-01-09 18:50:18 +00002291 strbuf_addf(sb, _(" (use \"%s\" for details)\n"),
2292 "git status --ahead-behind");
Jiang Xinf2e08732013-08-26 15:02:48 +08002293 } else if (!theirs) {
Jiang Xin8a5b7492012-02-02 10:02:23 +08002294 strbuf_addf(sb,
2295 Q_("Your branch is ahead of '%s' by %d commit.\n",
2296 "Your branch is ahead of '%s' by %d commits.\n",
Jiang Xinf2e08732013-08-26 15:02:48 +08002297 ours),
2298 base, ours);
Ben Boeckeled9bff02021-08-23 12:44:00 +02002299 if (advice_enabled(ADVICE_STATUS_HINTS))
René Scharfea22ae752016-09-15 20:31:00 +02002300 strbuf_addstr(sb,
Jeff King491e3072012-12-03 01:16:57 -05002301 _(" (use \"git push\" to publish your local commits)\n"));
Jiang Xinf2e08732013-08-26 15:02:48 +08002302 } else if (!ours) {
Jiang Xin8a5b7492012-02-02 10:02:23 +08002303 strbuf_addf(sb,
2304 Q_("Your branch is behind '%s' by %d commit, "
2305 "and can be fast-forwarded.\n",
2306 "Your branch is behind '%s' by %d commits, "
2307 "and can be fast-forwarded.\n",
Jiang Xinf2e08732013-08-26 15:02:48 +08002308 theirs),
2309 base, theirs);
Ben Boeckeled9bff02021-08-23 12:44:00 +02002310 if (advice_enabled(ADVICE_STATUS_HINTS))
René Scharfea22ae752016-09-15 20:31:00 +02002311 strbuf_addstr(sb,
Jeff King491e3072012-12-03 01:16:57 -05002312 _(" (use \"git pull\" to update your local branch)\n"));
Matthieu Moyc190ced2012-11-15 11:45:00 +01002313 } else {
Jiang Xin8a5b7492012-02-02 10:02:23 +08002314 strbuf_addf(sb,
2315 Q_("Your branch and '%s' have diverged,\n"
2316 "and have %d and %d different commit each, "
2317 "respectively.\n",
2318 "Your branch and '%s' have diverged,\n"
2319 "and have %d and %d different commits each, "
2320 "respectively.\n",
Nguyễn Thái Ngọc Duyf54bea42016-05-03 07:12:30 +07002321 ours + theirs),
Jiang Xinf2e08732013-08-26 15:02:48 +08002322 base, ours, theirs);
Ben Boeckeled9bff02021-08-23 12:44:00 +02002323 if (advice_enabled(ADVICE_STATUS_HINTS))
René Scharfea22ae752016-09-15 20:31:00 +02002324 strbuf_addstr(sb,
Jeff King491e3072012-12-03 01:16:57 -05002325 _(" (use \"git pull\" to merge the remote branch into yours)\n"));
Matthieu Moyc190ced2012-11-15 11:45:00 +01002326 }
Stefan Beller2f50bab2014-08-10 21:43:33 +02002327 free(base);
Junio C Hamano6d21bf92008-07-02 00:51:18 -07002328 return 1;
2329}
Jay Soffian454e2022009-02-25 03:32:11 -05002330
Michael Haggerty455ade62015-05-25 18:39:01 +00002331static int one_local_ref(const char *refname, const struct object_id *oid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02002332 int flag UNUSED,
Jeff King63e14ee2022-08-19 06:08:32 -04002333 void *cb_data)
Jay Soffian454e2022009-02-25 03:32:11 -05002334{
2335 struct ref ***local_tail = cb_data;
2336 struct ref *ref;
Jay Soffian454e2022009-02-25 03:32:11 -05002337
2338 /* we already know it starts with refs/ to get here */
Michael Haggerty8d9c5012011-09-15 23:10:25 +02002339 if (check_refname_format(refname + 5, 0))
Jay Soffian454e2022009-02-25 03:32:11 -05002340 return 0;
2341
Jeff King96ffc062016-02-22 17:44:32 -05002342 ref = alloc_ref(refname);
brian m. carlsonf4e54d02015-11-10 02:22:20 +00002343 oidcpy(&ref->new_oid, oid);
Jay Soffian454e2022009-02-25 03:32:11 -05002344 **local_tail = ref;
2345 *local_tail = &ref->next;
2346 return 0;
2347}
2348
2349struct ref *get_local_heads(void)
2350{
Nguyễn Thái Ngọc Duy55f05662009-04-17 08:16:23 +10002351 struct ref *local_refs = NULL, **local_tail = &local_refs;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +00002352
Jay Soffian454e2022009-02-25 03:32:11 -05002353 for_each_ref(one_local_ref, &local_tail);
2354 return local_refs;
2355}
Jay Soffian8ef51732009-02-25 03:32:13 -05002356
Jay Soffian4229f1f2009-02-27 14:10:05 -05002357struct ref *guess_remote_head(const struct ref *head,
2358 const struct ref *refs,
2359 int all)
Jay Soffian8ef51732009-02-25 03:32:13 -05002360{
Jay Soffian8ef51732009-02-25 03:32:13 -05002361 const struct ref *r;
Jay Soffian4229f1f2009-02-27 14:10:05 -05002362 struct ref *list = NULL;
2363 struct ref **tail = &list;
Jay Soffian8ef51732009-02-25 03:32:13 -05002364
Jay Soffian6cb4e6c2009-02-25 03:32:14 -05002365 if (!head)
Jay Soffian8ef51732009-02-25 03:32:13 -05002366 return NULL;
2367
Jeff Kingfbb074c2009-02-27 14:10:06 -05002368 /*
2369 * Some transports support directly peeking at
2370 * where HEAD points; if that is the case, then
2371 * we don't have to guess.
2372 */
2373 if (head->symref)
2374 return copy_ref(find_ref_by_name(refs, head->symref));
2375
Johannes Schindelina4712142020-06-24 14:46:35 +00002376 /* If a remote branch exists with the default branch name, let's use it. */
Jay Soffian4229f1f2009-02-27 14:10:05 -05002377 if (!all) {
Johannes Schindelincc0f13c2020-12-11 11:36:56 +00002378 char *ref = xstrfmt("refs/heads/%s",
2379 git_default_branch_name(0));
Johannes Schindelina4712142020-06-24 14:46:35 +00002380
2381 r = find_ref_by_name(refs, ref);
2382 free(ref);
2383 if (r && oideq(&r->old_oid, &head->old_oid))
2384 return copy_ref(r);
2385
2386 /* Fall back to the hard-coded historical default */
Jay Soffian4229f1f2009-02-27 14:10:05 -05002387 r = find_ref_by_name(refs, "refs/heads/master");
Jeff King4a7e27e2018-08-28 17:22:40 -04002388 if (r && oideq(&r->old_oid, &head->old_oid))
Jay Soffian4229f1f2009-02-27 14:10:05 -05002389 return copy_ref(r);
2390 }
Jay Soffian8ef51732009-02-25 03:32:13 -05002391
2392 /* Look for another ref that points there */
Jay Soffian4229f1f2009-02-27 14:10:05 -05002393 for (r = refs; r; r = r->next) {
Jeff King61adfd32011-06-03 01:11:13 -04002394 if (r != head &&
Christian Couder59556542013-11-30 21:55:40 +01002395 starts_with(r->name, "refs/heads/") &&
Jeff King4a7e27e2018-08-28 17:22:40 -04002396 oideq(&r->old_oid, &head->old_oid)) {
Jay Soffian4229f1f2009-02-27 14:10:05 -05002397 *tail = copy_ref(r);
2398 tail = &((*tail)->next);
2399 if (!all)
2400 break;
2401 }
2402 }
Jay Soffian8ef51732009-02-25 03:32:13 -05002403
Jay Soffian4229f1f2009-02-27 14:10:05 -05002404 return list;
Jay Soffian8ef51732009-02-25 03:32:13 -05002405}
Jay Soffianf2ef6072009-11-10 00:03:31 -05002406
2407struct stale_heads_info {
Jay Soffianf2ef6072009-11-10 00:03:31 -05002408 struct string_list *ref_names;
2409 struct ref **stale_refs_tail;
Brandon Williamsa2ac50c2018-05-16 15:58:10 -07002410 struct refspec *rs;
Jay Soffianf2ef6072009-11-10 00:03:31 -05002411};
2412
Michael Haggerty455ade62015-05-25 18:39:01 +00002413static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
2414 int flags, void *cb_data)
Jay Soffianf2ef6072009-11-10 00:03:31 -05002415{
2416 struct stale_heads_info *info = cb_data;
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002417 struct string_list matches = STRING_LIST_INIT_DUP;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07002418 struct refspec_item query;
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002419 int i, stale = 1;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -07002420 memset(&query, 0, sizeof(struct refspec_item));
Carlos Martín Nietoed43de62011-10-15 07:04:25 +02002421 query.dst = (char *)refname;
2422
Brandon Williamsa2ac50c2018-05-16 15:58:10 -07002423 query_refspecs_multiple(info->rs, &query, &matches);
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002424 if (matches.nr == 0)
2425 goto clean_exit; /* No matches */
Carlos Martín Nietoed43de62011-10-15 07:04:25 +02002426
2427 /*
2428 * If we did find a suitable refspec and it's not a symref and
2429 * it's not in the list of refs that currently exist in that
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002430 * remote, we consider it to be stale. In order to deal with
2431 * overlapping refspecs, we need to go over all of the
2432 * matching refs.
Carlos Martín Nietoed43de62011-10-15 07:04:25 +02002433 */
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002434 if (flags & REF_ISSYMREF)
2435 goto clean_exit;
2436
2437 for (i = 0; stale && i < matches.nr; i++)
2438 if (string_list_has_string(info->ref_names, matches.items[i].string))
2439 stale = 0;
2440
2441 if (stale) {
Carlos Martín Nietoed43de62011-10-15 07:04:25 +02002442 struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
brian m. carlsonf4e54d02015-11-10 02:22:20 +00002443 oidcpy(&ref->new_oid, oid);
Jay Soffianf2ef6072009-11-10 00:03:31 -05002444 }
Carlos Martín Nietoed43de62011-10-15 07:04:25 +02002445
Carlos Martín Nietoe6f63712014-02-27 10:00:10 +01002446clean_exit:
2447 string_list_clear(&matches, 0);
Jay Soffianf2ef6072009-11-10 00:03:31 -05002448 return 0;
2449}
2450
Brandon Williamsa2ac50c2018-05-16 15:58:10 -07002451struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map)
Jay Soffianf2ef6072009-11-10 00:03:31 -05002452{
2453 struct ref *ref, *stale_refs = NULL;
Thiago Farina183113a2010-07-04 16:46:19 -03002454 struct string_list ref_names = STRING_LIST_INIT_NODUP;
Jay Soffianf2ef6072009-11-10 00:03:31 -05002455 struct stale_heads_info info;
Michael Haggerty2b2a5be2015-05-25 18:38:28 +00002456
Jay Soffianf2ef6072009-11-10 00:03:31 -05002457 info.ref_names = &ref_names;
2458 info.stale_refs_tail = &stale_refs;
Brandon Williamsa2ac50c2018-05-16 15:58:10 -07002459 info.rs = rs;
Jay Soffianf2ef6072009-11-10 00:03:31 -05002460 for (ref = fetch_map; ref; ref = ref->next)
Julian Phillips1d2f80f2010-06-26 00:41:38 +01002461 string_list_append(&ref_names, ref->name);
Michael Haggerty3383e192014-11-25 09:02:35 +01002462 string_list_sort(&ref_names);
Jay Soffianf2ef6072009-11-10 00:03:31 -05002463 for_each_ref(get_stale_heads_cb, &info);
2464 string_list_clear(&ref_names, 0);
2465 return stale_refs;
2466}
Junio C Hamano28f5d172013-07-08 15:34:36 -07002467
2468/*
2469 * Compare-and-swap
2470 */
Junio C Hamanoa355b112015-01-14 14:58:44 -08002471static void clear_cas_option(struct push_cas_option *cas)
Junio C Hamano28f5d172013-07-08 15:34:36 -07002472{
2473 int i;
2474
2475 for (i = 0; i < cas->nr; i++)
2476 free(cas->entry[i].refname);
2477 free(cas->entry);
2478 memset(cas, 0, sizeof(*cas));
2479}
2480
2481static struct push_cas *add_cas_entry(struct push_cas_option *cas,
2482 const char *refname,
2483 size_t refnamelen)
2484{
2485 struct push_cas *entry;
2486 ALLOC_GROW(cas->entry, cas->nr + 1, cas->alloc);
2487 entry = &cas->entry[cas->nr++];
2488 memset(entry, 0, sizeof(*entry));
2489 entry->refname = xmemdupz(refname, refnamelen);
2490 return entry;
2491}
2492
Junio C Hamano86689762017-03-31 13:20:48 -07002493static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unset)
Junio C Hamano28f5d172013-07-08 15:34:36 -07002494{
2495 const char *colon;
2496 struct push_cas *entry;
2497
2498 if (unset) {
2499 /* "--no-<option>" */
2500 clear_cas_option(cas);
2501 return 0;
2502 }
2503
2504 if (!arg) {
2505 /* just "--<option>" */
2506 cas->use_tracking_for_rest = 1;
2507 return 0;
2508 }
2509
2510 /* "--<option>=refname" or "--<option>=refname:value" */
2511 colon = strchrnul(arg, ':');
2512 entry = add_cas_entry(cas, arg, colon - arg);
2513 if (!*colon)
2514 entry->use_tracking = 1;
John Keepingeee98e72016-07-26 21:44:44 +01002515 else if (!colon[1])
brian m. carlsonb8566f82017-07-13 23:49:21 +00002516 oidclr(&entry->expect);
Ævar Arnfjörð Bjarmasond850b7a2023-03-28 15:58:46 +02002517 else if (repo_get_oid(the_repository, colon + 1, &entry->expect))
Nguyễn Thái Ngọc Duy0b9c3af2018-11-10 06:16:09 +01002518 return error(_("cannot parse expected object name '%s'"),
2519 colon + 1);
Junio C Hamano28f5d172013-07-08 15:34:36 -07002520 return 0;
2521}
2522
2523int parseopt_push_cas_option(const struct option *opt, const char *arg, int unset)
2524{
2525 return parse_push_cas_option(opt->value, arg, unset);
2526}
Junio C Hamano91048a92013-07-09 11:01:06 -07002527
2528int is_empty_cas(const struct push_cas_option *cas)
2529{
2530 return !cas->use_tracking_for_rest && !cas->nr;
2531}
2532
2533/*
2534 * Look at remote.fetch refspec and see if we have a remote
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302535 * tracking branch for the refname there. Fill the name of
2536 * the remote-tracking branch in *dst_refname, and the name
2537 * of the commit object at its tip in oid[].
Junio C Hamano91048a92013-07-09 11:01:06 -07002538 * If we cannot do so, return negative to signal an error.
2539 */
2540static int remote_tracking(struct remote *remote, const char *refname,
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302541 struct object_id *oid, char **dst_refname)
Junio C Hamano91048a92013-07-09 11:01:06 -07002542{
2543 char *dst;
2544
Brandon Williamsd0004142018-05-16 15:58:11 -07002545 dst = apply_refspecs(&remote->fetch, refname);
Junio C Hamano91048a92013-07-09 11:01:06 -07002546 if (!dst)
2547 return -1; /* no tracking ref for refname at remote */
brian m. carlson34c290a2017-10-15 22:06:56 +00002548 if (read_ref(dst, oid))
Junio C Hamano91048a92013-07-09 11:01:06 -07002549 return -1; /* we know what the tracking ref is but we cannot read it */
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302550
2551 *dst_refname = dst;
Junio C Hamano91048a92013-07-09 11:01:06 -07002552 return 0;
2553}
2554
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302555/*
2556 * The struct "reflog_commit_array" and related helper functions
2557 * are used for collecting commits into an array during reflog
2558 * traversals in "check_and_collect_until()".
2559 */
2560struct reflog_commit_array {
2561 struct commit **item;
2562 size_t nr, alloc;
2563};
2564
Ævar Arnfjörð Bjarmason9865b6e2021-09-27 14:54:25 +02002565#define REFLOG_COMMIT_ARRAY_INIT { 0 }
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302566
2567/* Append a commit to the array. */
2568static void append_commit(struct reflog_commit_array *arr,
2569 struct commit *commit)
2570{
2571 ALLOC_GROW(arr->item, arr->nr + 1, arr->alloc);
2572 arr->item[arr->nr++] = commit;
2573}
2574
2575/* Free and reset the array. */
2576static void free_commit_array(struct reflog_commit_array *arr)
2577{
2578 FREE_AND_NULL(arr->item);
2579 arr->nr = arr->alloc = 0;
2580}
2581
2582struct check_and_collect_until_cb_data {
2583 struct commit *remote_commit;
2584 struct reflog_commit_array *local_commits;
2585 timestamp_t remote_reflog_timestamp;
2586};
2587
2588/* Get the timestamp of the latest entry. */
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02002589static int peek_reflog(struct object_id *o_oid UNUSED,
2590 struct object_id *n_oid UNUSED,
2591 const char *ident UNUSED,
2592 timestamp_t timestamp, int tz UNUSED,
2593 const char *message UNUSED, void *cb_data)
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302594{
2595 timestamp_t *ts = cb_data;
2596 *ts = timestamp;
2597 return 1;
2598}
2599
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02002600static int check_and_collect_until(struct object_id *o_oid UNUSED,
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302601 struct object_id *n_oid,
Ævar Arnfjörð Bjarmason5cf88fd2022-08-25 19:09:48 +02002602 const char *ident UNUSED,
2603 timestamp_t timestamp, int tz UNUSED,
2604 const char *message UNUSED, void *cb_data)
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302605{
2606 struct commit *commit;
2607 struct check_and_collect_until_cb_data *cb = cb_data;
2608
2609 /* An entry was found. */
2610 if (oideq(n_oid, &cb->remote_commit->object.oid))
2611 return 1;
2612
2613 if ((commit = lookup_commit_reference(the_repository, n_oid)))
2614 append_commit(cb->local_commits, commit);
2615
2616 /*
2617 * If the reflog entry timestamp is older than the remote ref's
2618 * latest reflog entry, there is no need to check or collect
2619 * entries older than this one.
2620 */
2621 if (timestamp < cb->remote_reflog_timestamp)
2622 return -1;
2623
2624 return 0;
2625}
2626
2627#define MERGE_BASES_BATCH_SIZE 8
2628
2629/*
2630 * Iterate through the reflog of the local ref to check if there is an entry
2631 * for the given remote-tracking ref; runs until the timestamp of an entry is
2632 * older than latest timestamp of remote-tracking ref's reflog. Any commits
2633 * are that seen along the way are collected into an array to check if the
2634 * remote-tracking ref is reachable from any of them.
2635 */
2636static int is_reachable_in_reflog(const char *local, const struct ref *remote)
2637{
2638 timestamp_t date;
2639 struct commit *commit;
2640 struct commit **chunk;
2641 struct check_and_collect_until_cb_data cb;
2642 struct reflog_commit_array arr = REFLOG_COMMIT_ARRAY_INIT;
2643 size_t size = 0;
2644 int ret = 0;
2645
2646 commit = lookup_commit_reference(the_repository, &remote->old_oid);
2647 if (!commit)
2648 goto cleanup_return;
2649
2650 /*
2651 * Get the timestamp from the latest entry
2652 * of the remote-tracking ref's reflog.
2653 */
2654 for_each_reflog_ent_reverse(remote->tracking_ref, peek_reflog, &date);
2655
2656 cb.remote_commit = commit;
2657 cb.local_commits = &arr;
2658 cb.remote_reflog_timestamp = date;
2659 ret = for_each_reflog_ent_reverse(local, check_and_collect_until, &cb);
2660
2661 /* We found an entry in the reflog. */
2662 if (ret > 0)
2663 goto cleanup_return;
2664
2665 /*
2666 * Check if the remote commit is reachable from any
2667 * of the commits in the collected array, in batches.
2668 */
2669 for (chunk = arr.item; chunk < arr.item + arr.nr; chunk += size) {
2670 size = arr.item + arr.nr - chunk;
2671 if (MERGE_BASES_BATCH_SIZE < size)
2672 size = MERGE_BASES_BATCH_SIZE;
2673
Ævar Arnfjörð Bjarmasoncb338c22023-03-28 15:58:47 +02002674 if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk)))
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302675 break;
2676 }
2677
2678cleanup_return:
2679 free_commit_array(&arr);
2680 return ret;
2681}
2682
2683/*
2684 * Check for reachability of a remote-tracking
2685 * ref in the reflog entries of its local ref.
2686 */
2687static void check_if_includes_upstream(struct ref *remote)
2688{
2689 struct ref *local = get_local_ref(remote->name);
2690 if (!local)
2691 return;
2692
2693 if (is_reachable_in_reflog(local->name, remote) <= 0)
2694 remote->unreachable = 1;
2695}
2696
Junio C Hamano91048a92013-07-09 11:01:06 -07002697static void apply_cas(struct push_cas_option *cas,
2698 struct remote *remote,
2699 struct ref *ref)
2700{
2701 int i;
2702
2703 /* Find an explicit --<option>=<name>[:<value>] entry */
2704 for (i = 0; i < cas->nr; i++) {
2705 struct push_cas *entry = &cas->entry[i];
Michael Haggerty54457fe2014-01-14 04:16:07 +01002706 if (!refname_match(entry->refname, ref->name))
Junio C Hamano91048a92013-07-09 11:01:06 -07002707 continue;
2708 ref->expect_old_sha1 = 1;
2709 if (!entry->use_tracking)
brian m. carlsonb8566f82017-07-13 23:49:21 +00002710 oidcpy(&ref->old_oid_expect, &entry->expect);
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302711 else if (remote_tracking(remote, ref->name,
2712 &ref->old_oid_expect,
2713 &ref->tracking_ref))
John Keeping64ac39a2016-07-26 21:44:45 +01002714 oidclr(&ref->old_oid_expect);
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302715 else
2716 ref->check_reachable = cas->use_force_if_includes;
Junio C Hamano91048a92013-07-09 11:01:06 -07002717 return;
2718 }
2719
2720 /* Are we using "--<option>" to cover all? */
2721 if (!cas->use_tracking_for_rest)
2722 return;
2723
2724 ref->expect_old_sha1 = 1;
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302725 if (remote_tracking(remote, ref->name,
2726 &ref->old_oid_expect,
2727 &ref->tracking_ref))
John Keeping64ac39a2016-07-26 21:44:45 +01002728 oidclr(&ref->old_oid_expect);
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302729 else
2730 ref->check_reachable = cas->use_force_if_includes;
Junio C Hamano91048a92013-07-09 11:01:06 -07002731}
2732
2733void apply_push_cas(struct push_cas_option *cas,
2734 struct remote *remote,
2735 struct ref *remote_refs)
2736{
2737 struct ref *ref;
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302738 for (ref = remote_refs; ref; ref = ref->next) {
Junio C Hamano91048a92013-07-09 11:01:06 -07002739 apply_cas(cas, remote, ref);
Srinidhi Kaushik99a1f9a2020-10-03 17:40:44 +05302740
2741 /*
2742 * If "compare-and-swap" is in "use_tracking[_for_rest]"
2743 * mode, and if "--force-if-includes" was specified, run
2744 * the check.
2745 */
2746 if (ref->check_reachable)
2747 check_if_includes_upstream(ref);
2748 }
Junio C Hamano91048a92013-07-09 11:01:06 -07002749}
Glen Choofd3cb052021-11-17 16:53:22 -08002750
2751struct remote_state *remote_state_new(void)
2752{
2753 struct remote_state *r = xmalloc(sizeof(*r));
2754
2755 memset(r, 0, sizeof(*r));
2756
2757 hashmap_init(&r->remotes_hash, remotes_hash_cmp, NULL, 0);
Glen Choo4a2dcb12021-11-17 16:53:25 -08002758 hashmap_init(&r->branches_hash, branches_hash_cmp, NULL, 0);
Glen Choofd3cb052021-11-17 16:53:22 -08002759 return r;
2760}
2761
2762void remote_state_clear(struct remote_state *remote_state)
2763{
2764 int i;
2765
Ævar Arnfjörð Bjarmason338959d2022-06-07 17:50:03 +02002766 for (i = 0; i < remote_state->remotes_nr; i++)
Glen Choofd3cb052021-11-17 16:53:22 -08002767 remote_clear(remote_state->remotes[i]);
Glen Choofd3cb052021-11-17 16:53:22 -08002768 FREE_AND_NULL(remote_state->remotes);
2769 remote_state->remotes_alloc = 0;
2770 remote_state->remotes_nr = 0;
2771
2772 hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
Glen Choo4a2dcb12021-11-17 16:53:25 -08002773 hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent);
Glen Choofd3cb052021-11-17 16:53:22 -08002774}
Derrick Stolee1d04e712022-05-16 20:11:03 +00002775
2776/*
2777 * Returns 1 if it was the last chop before ':'.
2778 */
2779static int chop_last_dir(char **remoteurl, int is_relative)
2780{
2781 char *rfind = find_last_dir_sep(*remoteurl);
2782 if (rfind) {
2783 *rfind = '\0';
2784 return 0;
2785 }
2786
2787 rfind = strrchr(*remoteurl, ':');
2788 if (rfind) {
2789 *rfind = '\0';
2790 return 1;
2791 }
2792
2793 if (is_relative || !strcmp(".", *remoteurl))
2794 die(_("cannot strip one component off url '%s'"),
2795 *remoteurl);
2796
2797 free(*remoteurl);
2798 *remoteurl = xstrdup(".");
2799 return 0;
2800}
2801
2802char *relative_url(const char *remote_url, const char *url,
2803 const char *up_path)
2804{
2805 int is_relative = 0;
2806 int colonsep = 0;
2807 char *out;
Derrick Stolee834e3522022-05-16 20:11:04 +00002808 char *remoteurl;
Derrick Stolee1d04e712022-05-16 20:11:03 +00002809 struct strbuf sb = STRBUF_INIT;
Derrick Stolee834e3522022-05-16 20:11:04 +00002810 size_t len;
Derrick Stolee1d04e712022-05-16 20:11:03 +00002811
Derrick Stolee834e3522022-05-16 20:11:04 +00002812 if (!url_is_local_not_ssh(url) || is_absolute_path(url))
2813 return xstrdup(url);
2814
2815 len = strlen(remote_url);
2816 if (!len)
2817 BUG("invalid empty remote_url");
2818
2819 remoteurl = xstrdup(remote_url);
Derrick Stolee1d04e712022-05-16 20:11:03 +00002820 if (is_dir_sep(remoteurl[len-1]))
2821 remoteurl[len-1] = '\0';
2822
2823 if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
2824 is_relative = 0;
2825 else {
2826 is_relative = 1;
2827 /*
2828 * Prepend a './' to ensure all relative
2829 * remoteurls start with './' or '../'
2830 */
2831 if (!starts_with_dot_slash_native(remoteurl) &&
2832 !starts_with_dot_dot_slash_native(remoteurl)) {
2833 strbuf_reset(&sb);
2834 strbuf_addf(&sb, "./%s", remoteurl);
2835 free(remoteurl);
2836 remoteurl = strbuf_detach(&sb, NULL);
2837 }
2838 }
2839 /*
2840 * When the url starts with '../', remove that and the
2841 * last directory in remoteurl.
2842 */
Johannes Schindelinc918f5c2022-06-15 23:35:44 +00002843 while (*url) {
Derrick Stolee1d04e712022-05-16 20:11:03 +00002844 if (starts_with_dot_dot_slash_native(url)) {
2845 url += 3;
2846 colonsep |= chop_last_dir(&remoteurl, is_relative);
2847 } else if (starts_with_dot_slash_native(url))
2848 url += 2;
2849 else
2850 break;
2851 }
2852 strbuf_reset(&sb);
2853 strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url);
2854 if (ends_with(url, "/"))
2855 strbuf_setlen(&sb, sb.len - 1);
2856 free(remoteurl);
2857
2858 if (starts_with_dot_slash_native(sb.buf))
2859 out = xstrdup(sb.buf + 2);
2860 else
2861 out = xstrdup(sb.buf);
2862
2863 if (!up_path || !is_relative) {
2864 strbuf_release(&sb);
2865 return out;
2866 }
2867
2868 strbuf_reset(&sb);
2869 strbuf_addf(&sb, "%s%s", up_path, out);
2870 free(out);
2871 return strbuf_detach(&sb, NULL);
2872}