blob: 5f4cde9d784e310e939dc7952e4096e45f60cbb7 [file] [log] [blame]
Stephen Boydc2e86ad2011-03-22 00:51:05 -07001#include "builtin.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Johannes Schindelin211c8962008-02-29 01:45:45 +00003#include "parse-options.h"
4#include "transport.h"
5#include "remote.h"
Johannes Schindelinc455c872008-07-21 19:03:49 +01006#include "string-list.h"
Johannes Schindelin211c8962008-02-29 01:45:45 +00007#include "strbuf.h"
8#include "run-command.h"
Bert Wesarg88f85762020-01-27 08:04:27 +01009#include "rebase.h"
Johannes Schindelin211c8962008-02-29 01:45:45 +000010#include "refs.h"
Brandon Williamsec0cb492018-05-16 15:57:48 -070011#include "refspec.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -070012#include "object-store.h"
Jeff Kingdbbcd442020-07-28 16:23:39 -040013#include "strvec.h"
Derrick Stolee1d614d42018-07-20 16:33:06 +000014#include "commit-reach.h"
Taylor Blau56710a72022-03-03 17:25:18 -050015#include "progress.h"
Johannes Schindelin211c8962008-02-29 01:45:45 +000016
17static const char * const builtin_remote_usage[] = {
Jean-Noël Avila959d6702022-01-31 22:07:48 +000018 "git remote [-v | --verbose]",
Alex Henrie9c9b4f22015-01-13 00:44:47 -070019 N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
Taylor Blau56710a72022-03-03 17:25:18 -050020 N_("git remote rename [--[no-]progress] <old> <new>"),
Junio C Hamano90585602012-09-12 14:21:58 -070021 N_("git remote remove <name>"),
Alex Henrie9c9b4f22015-01-13 00:44:47 -070022 N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"),
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070023 N_("git remote [-v | --verbose] show [-n] <name>"),
24 N_("git remote prune [-n | --dry-run] <name>"),
25 N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"),
26 N_("git remote set-branches [--add] <name> <branch>..."),
Ben Boeckel96f78d32015-09-15 21:53:47 -040027 N_("git remote get-url [--push] [--all] <name>"),
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070028 N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
29 N_("git remote set-url --add <name> <newurl>"),
30 N_("git remote set-url --delete <name> <url>"),
Johannes Schindelin211c8962008-02-29 01:45:45 +000031 NULL
32};
33
Tim Henigan45041072009-11-20 18:43:13 -050034static const char * const builtin_remote_add_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070035 N_("git remote add [<options>] <name> <url>"),
Tim Henigan45041072009-11-20 18:43:13 -050036 NULL
37};
38
39static const char * const builtin_remote_rename_usage[] = {
Taylor Blau56710a72022-03-03 17:25:18 -050040 N_("git remote rename [--[no-]progress] <old> <new>"),
Tim Henigan45041072009-11-20 18:43:13 -050041 NULL
42};
43
44static const char * const builtin_remote_rm_usage[] = {
Junio C Hamano90585602012-09-12 14:21:58 -070045 N_("git remote remove <name>"),
Tim Henigan45041072009-11-20 18:43:13 -050046 NULL
47};
48
49static const char * const builtin_remote_sethead_usage[] = {
Philip Oakleye49c8f32013-09-21 16:51:46 +010050 N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"),
Tim Henigan45041072009-11-20 18:43:13 -050051 NULL
52};
53
Jonathan Nieder3d8b6942010-05-19 13:38:50 -050054static const char * const builtin_remote_setbranches_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070055 N_("git remote set-branches <name> <branch>..."),
56 N_("git remote set-branches --add <name> <branch>..."),
Jonathan Nieder3d8b6942010-05-19 13:38:50 -050057 NULL
58};
59
Tim Henigan45041072009-11-20 18:43:13 -050060static const char * const builtin_remote_show_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070061 N_("git remote show [<options>] <name>"),
Tim Henigan45041072009-11-20 18:43:13 -050062 NULL
63};
64
65static const char * const builtin_remote_prune_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070066 N_("git remote prune [<options>] <name>"),
Tim Henigan45041072009-11-20 18:43:13 -050067 NULL
68};
69
70static const char * const builtin_remote_update_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070071 N_("git remote update [<options>] [<group> | <remote>]..."),
Tim Henigan45041072009-11-20 18:43:13 -050072 NULL
73};
74
Ben Boeckel96f78d32015-09-15 21:53:47 -040075static const char * const builtin_remote_geturl_usage[] = {
76 N_("git remote get-url [--push] [--all] <name>"),
77 NULL
78};
79
Ilari Liusvaara433f2be2010-01-18 19:18:02 +020080static const char * const builtin_remote_seturl_usage[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +070081 N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
82 N_("git remote set-url --add <name> <newurl>"),
83 N_("git remote set-url --delete <name> <url>"),
Ilari Liusvaara433f2be2010-01-18 19:18:02 +020084 NULL
85};
86
Jay Soffiane61e0cc2009-02-25 03:32:24 -050087#define GET_REF_STATES (1<<0)
88#define GET_HEAD_NAMES (1<<1)
Jay Soffiane5dcbfd2009-02-25 03:32:28 -050089#define GET_PUSH_REF_STATES (1<<2)
Jay Soffiane61e0cc2009-02-25 03:32:24 -050090
Johannes Schindelin211c8962008-02-29 01:45:45 +000091static int verbose;
92
Johannes Schindelin211c8962008-02-29 01:45:45 +000093static int fetch_remote(const char *name)
94{
Cheng Renquandbbd56f2008-11-18 19:04:02 +080095 const char *argv[] = { "fetch", name, NULL, NULL };
96 if (verbose) {
97 argv[1] = "-v";
98 argv[2] = name;
99 }
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700100 printf_ln(_("Updating %s"), name);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000101 if (run_command_v_opt(argv, RUN_GIT_CMD))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700102 return error(_("Could not fetch %s"), name);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000103 return 0;
104}
105
Samuel Tardieu111fb852010-04-20 01:31:31 +0200106enum {
107 TAGS_UNSET = 0,
108 TAGS_DEFAULT = 1,
109 TAGS_SET = 2
110};
111
Jeff Kinga9f5a352011-03-30 15:53:19 -0400112#define MIRROR_NONE 0
113#define MIRROR_FETCH 1
114#define MIRROR_PUSH 2
115#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
116
Patrick Steinhardtab5e4b62016-02-22 12:23:29 +0100117static void add_branch(const char *key, const char *branchname,
118 const char *remotename, int mirror, struct strbuf *tmp)
Jonathan Nieder3d8b6942010-05-19 13:38:50 -0500119{
120 strbuf_reset(tmp);
121 strbuf_addch(tmp, '+');
122 if (mirror)
123 strbuf_addf(tmp, "refs/%s:refs/%s",
124 branchname, branchname);
125 else
126 strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s",
127 branchname, remotename, branchname);
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100128 git_config_set_multivar(key, tmp->buf, "^$", 0);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -0500129}
130
Jeff King09902482011-03-30 15:53:39 -0400131static const char mirror_advice[] =
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700132N_("--mirror is dangerous and deprecated; please\n"
133 "\t use --mirror=fetch or --mirror=push instead");
Jeff King09902482011-03-30 15:53:39 -0400134
Jeff Kinga9f5a352011-03-30 15:53:19 -0400135static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
136{
137 unsigned *mirror = opt->value;
138 if (not)
139 *mirror = MIRROR_NONE;
Jeff King09902482011-03-30 15:53:39 -0400140 else if (!arg) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700141 warning("%s", _(mirror_advice));
Jeff Kinga9f5a352011-03-30 15:53:19 -0400142 *mirror = MIRROR_BOTH;
Jeff King09902482011-03-30 15:53:39 -0400143 }
Jeff Kinga9f5a352011-03-30 15:53:19 -0400144 else if (!strcmp(arg, "fetch"))
145 *mirror = MIRROR_FETCH;
146 else if (!strcmp(arg, "push"))
147 *mirror = MIRROR_PUSH;
148 else
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700149 return error(_("unknown mirror argument: %s"), arg);
Jeff Kinga9f5a352011-03-30 15:53:19 -0400150 return 0;
151}
152
Johannes Schindelin211c8962008-02-29 01:45:45 +0000153static int add(int argc, const char **argv)
154{
Jeff Kinga9f5a352011-03-30 15:53:19 -0400155 int fetch = 0, fetch_tags = TAGS_DEFAULT;
156 unsigned mirror = MIRROR_NONE;
Thiago Farina183113a2010-07-04 16:46:19 -0300157 struct string_list track = STRING_LIST_INIT_NODUP;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000158 const char *master = NULL;
159 struct remote *remote;
Brandon Caseyf285a2d2008-10-09 14:12:12 -0500160 struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000161 const char *name, *url;
162 int i;
163
164 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +0200165 OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")),
Samuel Tardieu111fb852010-04-20 01:31:31 +0200166 OPT_SET_INT(0, "tags", &fetch_tags,
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +0700167 N_("import all tags and associated objects when fetching"),
Samuel Tardieu111fb852010-04-20 01:31:31 +0200168 TAGS_SET),
169 OPT_SET_INT(0, NULL, &fetch_tags,
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +0700170 N_("or do not fetch any tag at all (--no-tags)"), TAGS_UNSET),
171 OPT_STRING_LIST('t', "track", &track, N_("branch"),
172 N_("branch(es) to track")),
173 OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")),
Denton Liu203c8532020-04-28 04:36:28 -0400174 OPT_CALLBACK_F(0, "mirror", &mirror, "(push|fetch)",
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +0700175 N_("set up remote as a mirror to push to or fetch from"),
Denton Liu203c8532020-04-28 04:36:28 -0400176 PARSE_OPT_OPTARG | PARSE_OPT_COMP_ARG, parse_mirror_opt),
Johannes Schindelin211c8962008-02-29 01:45:45 +0000177 OPT_END()
178 };
179
Tim Henigan45041072009-11-20 18:43:13 -0500180 argc = parse_options(argc, argv, NULL, options, builtin_remote_add_usage,
Stephen Boyd37782922009-05-23 11:53:12 -0700181 0);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000182
Thomas Rast2d2e3d22013-04-24 15:54:36 +0200183 if (argc != 2)
Tim Henigan45041072009-11-20 18:43:13 -0500184 usage_with_options(builtin_remote_add_usage, options);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000185
Jeff King13fc2c12011-03-30 15:52:52 -0400186 if (mirror && master)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700187 die(_("specifying a master branch makes no sense with --mirror"));
Jeff King3eafdc92011-05-26 11:11:00 -0400188 if (mirror && !(mirror & MIRROR_FETCH) && track.nr)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700189 die(_("specifying branches to track makes sense only with fetch mirrors"));
Jeff King13fc2c12011-03-30 15:52:52 -0400190
Johannes Schindelin211c8962008-02-29 01:45:45 +0000191 name = argv[0];
192 url = argv[1];
193
194 remote = remote_get(name);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +0100195 if (remote_is_configured(remote, 1)) {
196 error(_("remote %s already exists."), name);
197 exit(3);
198 }
Johannes Schindelin211c8962008-02-29 01:45:45 +0000199
Sean Baragf2c6fda2020-10-01 03:46:13 +0000200 if (!valid_remote_name(name))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700201 die(_("'%s' is not a valid remote name"), name);
Jonas Fonseca24b61772008-04-13 11:56:54 +0200202
Johannes Schindelin211c8962008-02-29 01:45:45 +0000203 strbuf_addf(&buf, "remote.%s.url", name);
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100204 git_config_set(buf.buf, url);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000205
Jeff Kinga9f5a352011-03-30 15:53:19 -0400206 if (!mirror || mirror & MIRROR_FETCH) {
207 strbuf_reset(&buf);
208 strbuf_addf(&buf, "remote.%s.fetch", name);
209 if (track.nr == 0)
210 string_list_append(&track, "*");
211 for (i = 0; i < track.nr; i++) {
Patrick Steinhardtab5e4b62016-02-22 12:23:29 +0100212 add_branch(buf.buf, track.items[i].string,
213 name, mirror, &buf2);
Jeff Kinga9f5a352011-03-30 15:53:19 -0400214 }
Johannes Schindelin211c8962008-02-29 01:45:45 +0000215 }
216
Jeff Kinga9f5a352011-03-30 15:53:19 -0400217 if (mirror & MIRROR_PUSH) {
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200218 strbuf_reset(&buf);
219 strbuf_addf(&buf, "remote.%s.mirror", name);
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100220 git_config_set(buf.buf, "true");
Paolo Bonzini84bb2df2008-04-17 13:17:20 +0200221 }
222
Samuel Tardieu111fb852010-04-20 01:31:31 +0200223 if (fetch_tags != TAGS_DEFAULT) {
224 strbuf_reset(&buf);
Ævar Arnfjörð Bjarmasonbfa91482021-02-25 02:21:16 +0100225 strbuf_addf(&buf, "remote.%s.tagOpt", name);
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100226 git_config_set(buf.buf,
227 fetch_tags == TAGS_SET ? "--tags" : "--no-tags");
Samuel Tardieu111fb852010-04-20 01:31:31 +0200228 }
229
Johannes Schindelin211c8962008-02-29 01:45:45 +0000230 if (fetch && fetch_remote(name))
231 return 1;
232
233 if (master) {
234 strbuf_reset(&buf);
235 strbuf_addf(&buf, "refs/remotes/%s/HEAD", name);
236
237 strbuf_reset(&buf2);
238 strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
239
240 if (create_symref(buf.buf, buf2.buf, "remote add"))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700241 return error(_("Could not setup master '%s'"), master);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000242 }
243
244 strbuf_release(&buf);
245 strbuf_release(&buf2);
Johannes Schindelinc455c872008-07-21 19:03:49 +0100246 string_list_clear(&track, 0);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000247
248 return 0;
249}
250
251struct branch_info {
Jay Soffiane0cc81e2009-02-25 03:32:21 -0500252 char *remote_name;
Johannes Schindelinc455c872008-07-21 19:03:49 +0100253 struct string_list merge;
Bert Wesarg88f85762020-01-27 08:04:27 +0100254 enum rebase_type rebase;
Bert Wesarg923d4a52020-01-27 08:04:30 +0100255 char *push_remote_name;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000256};
257
Jeff King2721ce22016-06-13 06:04:20 -0400258static struct string_list branch_list = STRING_LIST_INIT_NODUP;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000259
Junio C Hamano72972eb2008-07-17 21:30:33 -0700260static const char *abbrev_ref(const char *name, const char *prefix)
261{
Jeff Kingcf4fff52014-06-18 15:44:19 -0400262 skip_prefix(name, prefix, &name);
Junio C Hamano72972eb2008-07-17 21:30:33 -0700263 return name;
264}
265#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
266
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100267static int config_read_branches(const char *key, const char *value, void *cb)
Johannes Schindelin211c8962008-02-29 01:45:45 +0000268{
Bert Wesarg1a830682020-01-27 08:04:28 +0100269 const char *orig_key = key;
270 char *name;
271 struct string_list_item *item;
272 struct branch_info *info;
Bert Wesarg923d4a52020-01-27 08:04:30 +0100273 enum { REMOTE, MERGE, REBASE, PUSH_REMOTE } type;
Bert Wesarg1a830682020-01-27 08:04:28 +0100274 size_t key_len;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000275
Bert Wesarg1a830682020-01-27 08:04:28 +0100276 if (!starts_with(key, "branch."))
277 return 0;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000278
Bert Wesargceff1a12020-01-27 08:04:29 +0100279 key += strlen("branch.");
280 if (strip_suffix(key, ".remote", &key_len))
Bert Wesarg1a830682020-01-27 08:04:28 +0100281 type = REMOTE;
Bert Wesargceff1a12020-01-27 08:04:29 +0100282 else if (strip_suffix(key, ".merge", &key_len))
Bert Wesarg1a830682020-01-27 08:04:28 +0100283 type = MERGE;
Bert Wesargceff1a12020-01-27 08:04:29 +0100284 else if (strip_suffix(key, ".rebase", &key_len))
Bert Wesarg1a830682020-01-27 08:04:28 +0100285 type = REBASE;
Bert Wesarg923d4a52020-01-27 08:04:30 +0100286 else if (strip_suffix(key, ".pushremote", &key_len))
287 type = PUSH_REMOTE;
Bert Wesargceff1a12020-01-27 08:04:29 +0100288 else
Bert Wesarg1a830682020-01-27 08:04:28 +0100289 return 0;
Bert Wesargceff1a12020-01-27 08:04:29 +0100290 name = xmemdupz(key, key_len);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000291
Bert Wesarg1a830682020-01-27 08:04:28 +0100292 item = string_list_insert(&branch_list, name);
293
294 if (!item->util)
295 item->util = xcalloc(1, sizeof(struct branch_info));
296 info = item->util;
Bert Wesargceff1a12020-01-27 08:04:29 +0100297 switch (type) {
298 case REMOTE:
Bert Wesarg1a830682020-01-27 08:04:28 +0100299 if (info->remote_name)
300 warning(_("more than one %s"), orig_key);
301 info->remote_name = xstrdup(value);
Bert Wesargceff1a12020-01-27 08:04:29 +0100302 break;
303 case MERGE: {
Bert Wesarg1a830682020-01-27 08:04:28 +0100304 char *space = strchr(value, ' ');
305 value = abbrev_branch(value);
306 while (space) {
307 char *merge;
308 merge = xstrndup(value, space - value);
309 string_list_append(&info->merge, merge);
310 value = abbrev_branch(space + 1);
311 space = strchr(value, ' ');
312 }
313 string_list_append(&info->merge, xstrdup(value));
Bert Wesargceff1a12020-01-27 08:04:29 +0100314 break;
315 }
316 case REBASE:
Bert Wesarg1a830682020-01-27 08:04:28 +0100317 /*
318 * Consider invalid values as false and check the
319 * truth value with >= REBASE_TRUE.
320 */
321 info->rebase = rebase_parse_value(value);
Johannes Schindelinab7c7c22021-09-07 21:05:03 +0000322 if (info->rebase == REBASE_INVALID)
323 warning(_("unhandled branch.%s.rebase=%s; assuming "
324 "'true'"), name, value);
Bert Wesargceff1a12020-01-27 08:04:29 +0100325 break;
Bert Wesarg923d4a52020-01-27 08:04:30 +0100326 case PUSH_REMOTE:
327 if (info->push_remote_name)
328 warning(_("more than one %s"), orig_key);
329 info->push_remote_name = xstrdup(value);
330 break;
Bert Wesargceff1a12020-01-27 08:04:29 +0100331 default:
332 BUG("unexpected type=%d", type);
333 }
Bert Wesarg1a830682020-01-27 08:04:28 +0100334
Johannes Schindelin211c8962008-02-29 01:45:45 +0000335 return 0;
336}
337
338static void read_branches(void)
339{
340 if (branch_list.nr)
341 return;
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100342 git_config(config_read_branches, NULL);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000343}
344
345struct ref_states {
346 struct remote *remote;
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800347 struct string_list new_refs, stale, tracked, heads, push;
Jay Soffian7ecbbf82009-02-25 03:32:27 -0500348 int queried;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000349};
350
Ævar Arnfjörð Bjarmason0bc77872021-10-01 12:27:34 +0200351#define REF_STATES_INIT { \
352 .new_refs = STRING_LIST_INIT_DUP, \
353 .stale = STRING_LIST_INIT_DUP, \
354 .tracked = STRING_LIST_INIT_DUP, \
355 .heads = STRING_LIST_INIT_DUP, \
356 .push = STRING_LIST_INIT_DUP, \
357}
358
Jay Soffiane0cc81e2009-02-25 03:32:21 -0500359static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
Johannes Schindelin211c8962008-02-29 01:45:45 +0000360{
361 struct ref *fetch_map = NULL, **tail = &fetch_map;
Jay Soffianf2ef6072009-11-10 00:03:31 -0500362 struct ref *ref, *stale_refs;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000363 int i;
364
Brandon Williamse5349ab2018-05-16 15:58:01 -0700365 for (i = 0; i < states->remote->fetch.nr; i++)
366 if (get_fetch_map(remote_refs, &states->remote->fetch.items[i], &tail, 1))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700367 die(_("Could not get fetch map for refspec %s"),
Brandon Williamse5349ab2018-05-16 15:58:01 -0700368 states->remote->fetch.raw[i]);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000369
Johannes Schindelin211c8962008-02-29 01:45:45 +0000370 for (ref = fetch_map; ref; ref = ref->next) {
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +0700371 if (!ref->peer_ref || !ref_exists(ref->peer_ref->name))
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800372 string_list_append(&states->new_refs, abbrev_branch(ref->name));
Jay Soffian7b9a5e22009-02-25 03:32:20 -0500373 else
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100374 string_list_append(&states->tracked, abbrev_branch(ref->name));
Johannes Schindelin211c8962008-02-29 01:45:45 +0000375 }
Brandon Williamsa2ac50c2018-05-16 15:58:10 -0700376 stale_refs = get_stale_heads(&states->remote->fetch, fetch_map);
Jay Soffianf2ef6072009-11-10 00:03:31 -0500377 for (ref = stale_refs; ref; ref = ref->next) {
378 struct string_list_item *item =
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100379 string_list_append(&states->stale, abbrev_branch(ref->name));
Jay Soffianf2ef6072009-11-10 00:03:31 -0500380 item->util = xstrdup(ref->name);
381 }
382 free_refs(stale_refs);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000383 free_refs(fetch_map);
384
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800385 string_list_sort(&states->new_refs);
Michael Haggerty3383e192014-11-25 09:02:35 +0100386 string_list_sort(&states->tracked);
387 string_list_sort(&states->stale);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000388
389 return 0;
390}
391
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500392struct push_info {
393 char *dest;
394 int forced;
395 enum {
396 PUSH_STATUS_CREATE = 0,
397 PUSH_STATUS_DELETE,
398 PUSH_STATUS_UPTODATE,
399 PUSH_STATUS_FASTFORWARD,
400 PUSH_STATUS_OUTOFDATE,
Gary V. Vaughan4b055482010-05-14 09:31:35 +0000401 PUSH_STATUS_NOTQUERIED
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500402 } status;
403};
404
405static int get_push_ref_states(const struct ref *remote_refs,
406 struct ref_states *states)
407{
408 struct remote *remote = states->remote;
Clemens Buchacher6d2bf962009-05-31 16:26:48 +0200409 struct ref *ref, *local_refs, *push_map;
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500410 if (remote->mirror)
411 return 0;
412
413 local_refs = get_local_heads();
Clemens Buchacher6a015542009-05-27 22:13:43 +0200414 push_map = copy_ref_list(remote_refs);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500415
Brandon Williams5c7ec842018-05-16 15:58:21 -0700416 match_push_refs(local_refs, &push_map, &remote->push, MATCH_REFS_NONE);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500417
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500418 for (ref = push_map; ref; ref = ref->next) {
419 struct string_list_item *item;
420 struct push_info *info;
421
422 if (!ref->peer_ref)
423 continue;
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000424 oidcpy(&ref->new_oid, &ref->peer_ref->new_oid);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500425
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100426 item = string_list_append(&states->push,
427 abbrev_branch(ref->peer_ref->name));
Brian Gesiak38069452014-05-27 00:33:44 +0900428 item->util = xcalloc(1, sizeof(struct push_info));
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500429 info = item->util;
430 info->forced = ref->force;
431 info->dest = xstrdup(abbrev_branch(ref->name));
432
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000433 if (is_null_oid(&ref->new_oid)) {
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500434 info->status = PUSH_STATUS_DELETE;
Jeff King4a7e27e2018-08-28 17:22:40 -0400435 } else if (oideq(&ref->old_oid, &ref->new_oid))
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500436 info->status = PUSH_STATUS_UPTODATE;
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000437 else if (is_null_oid(&ref->old_oid))
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500438 info->status = PUSH_STATUS_CREATE;
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000439 else if (has_object_file(&ref->old_oid) &&
brian m. carlson6f3d57b2015-11-10 02:22:25 +0000440 ref_newer(&ref->new_oid, &ref->old_oid))
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500441 info->status = PUSH_STATUS_FASTFORWARD;
442 else
443 info->status = PUSH_STATUS_OUTOFDATE;
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500444 }
445 free_refs(local_refs);
446 free_refs(push_map);
447 return 0;
448}
449
450static int get_push_ref_states_noquery(struct ref_states *states)
451{
452 int i;
453 struct remote *remote = states->remote;
454 struct string_list_item *item;
455 struct push_info *info;
456
457 if (remote->mirror)
458 return 0;
459
Brandon Williams6bdb3042018-05-16 15:58:00 -0700460 if (!remote->push.nr) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700461 item = string_list_append(&states->push, _("(matching)"));
Brian Gesiak38069452014-05-27 00:33:44 +0900462 info = item->util = xcalloc(1, sizeof(struct push_info));
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500463 info->status = PUSH_STATUS_NOTQUERIED;
464 info->dest = xstrdup(item->string);
465 }
Brandon Williams6bdb3042018-05-16 15:58:00 -0700466 for (i = 0; i < remote->push.nr; i++) {
467 const struct refspec_item *spec = &remote->push.items[i];
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500468 if (spec->matching)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700469 item = string_list_append(&states->push, _("(matching)"));
Junio C Hamano5ad6b022009-03-08 00:12:33 -0800470 else if (strlen(spec->src))
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100471 item = string_list_append(&states->push, spec->src);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500472 else
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700473 item = string_list_append(&states->push, _("(delete)"));
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500474
Brian Gesiak38069452014-05-27 00:33:44 +0900475 info = item->util = xcalloc(1, sizeof(struct push_info));
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500476 info->forced = spec->force;
477 info->status = PUSH_STATUS_NOTQUERIED;
Junio C Hamano5ad6b022009-03-08 00:12:33 -0800478 info->dest = xstrdup(spec->dst ? spec->dst : item->string);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500479 }
480 return 0;
481}
482
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500483static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
484{
485 struct ref *ref, *matches;
486 struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -0700487 struct refspec_item refspec;
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500488
Jacob Keller95e7c382020-08-14 17:25:08 -0700489 memset(&refspec, 0, sizeof(refspec));
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500490 refspec.force = 0;
491 refspec.pattern = 1;
Junio C Hamano5ad6b022009-03-08 00:12:33 -0800492 refspec.src = refspec.dst = "refs/heads/*";
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500493 get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
494 matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
495 fetch_map, 1);
Brian Gianforcaroeeefa7c2009-09-01 01:35:10 -0400496 for (ref = matches; ref; ref = ref->next)
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100497 string_list_append(&states->heads, abbrev_branch(ref->name));
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500498
499 free_refs(fetch_map);
500 free_refs(matches);
501
502 return 0;
503}
504
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400505struct known_remote {
506 struct known_remote *next;
507 struct remote *remote;
508};
509
510struct known_remotes {
511 struct remote *to_delete;
512 struct known_remote *list;
513};
514
515static int add_known_remote(struct remote *remote, void *cb_data)
516{
517 struct known_remotes *all = cb_data;
518 struct known_remote *r;
519
520 if (!strcmp(all->to_delete->name, remote->name))
521 return 0;
522
523 r = xmalloc(sizeof(*r));
524 r->remote = remote;
525 r->next = all->list;
526 all->list = r;
527 return 0;
528}
529
Johannes Schindelin211c8962008-02-29 01:45:45 +0000530struct branches_for_remote {
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400531 struct remote *remote;
Jay Soffian441adf02009-02-04 11:06:07 -0500532 struct string_list *branches, *skipped;
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400533 struct known_remotes *keep;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000534};
535
536static int add_branch_for_removal(const char *refname,
Michael Haggerty45690a52015-05-25 18:38:41 +0000537 const struct object_id *oid, int flags, void *cb_data)
Johannes Schindelin211c8962008-02-29 01:45:45 +0000538{
539 struct branches_for_remote *branches = cb_data;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -0700540 struct refspec_item refspec;
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400541 struct known_remote *kr;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000542
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400543 memset(&refspec, 0, sizeof(refspec));
544 refspec.dst = (char *)refname;
545 if (remote_find_tracking(branches->remote, &refspec))
546 return 0;
Johannes Schindelin3b9dcff2008-03-08 23:40:42 +0100547
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400548 /* don't delete a branch if another remote also uses it */
549 for (kr = branches->keep->list; kr; kr = kr->next) {
550 memset(&refspec, 0, sizeof(refspec));
551 refspec.dst = (char *)refname;
552 if (!remote_find_tracking(kr->remote, &refspec))
553 return 0;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000554 }
555
Matthieu Moy13931232010-11-02 16:31:25 +0100556 /* don't delete non-remote-tracking refs */
Christian Couder59556542013-11-30 21:55:40 +0100557 if (!starts_with(refname, "refs/remotes/")) {
Jay Soffian441adf02009-02-04 11:06:07 -0500558 /* advise user how to delete local branches */
Christian Couder59556542013-11-30 21:55:40 +0100559 if (starts_with(refname, "refs/heads/"))
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100560 string_list_append(branches->skipped,
561 abbrev_branch(refname));
Jay Soffian441adf02009-02-04 11:06:07 -0500562 /* silently skip over other non-remote refs */
563 return 0;
564 }
565
Michael Haggertye26cdf92015-05-25 18:38:42 +0000566 string_list_append(branches->branches, refname);
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400567
Johannes Schindelin211c8962008-02-29 01:45:45 +0000568 return 0;
569}
570
Miklos Vajnabf984212008-11-03 19:26:18 +0100571struct rename_info {
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800572 const char *old_name;
573 const char *new_name;
Miklos Vajnabf984212008-11-03 19:26:18 +0100574 struct string_list *remote_branches;
Taylor Blau56710a72022-03-03 17:25:18 -0500575 uint32_t symrefs_nr;
Miklos Vajnabf984212008-11-03 19:26:18 +0100576};
577
578static int read_remote_branches(const char *refname,
Michael Haggerty53dc95b2015-05-25 18:38:43 +0000579 const struct object_id *oid, int flags, void *cb_data)
Miklos Vajnabf984212008-11-03 19:26:18 +0100580{
581 struct rename_info *rename = cb_data;
582 struct strbuf buf = STRBUF_INIT;
583 struct string_list_item *item;
584 int flag;
Miklos Vajnabf984212008-11-03 19:26:18 +0100585 const char *symref;
586
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800587 strbuf_addf(&buf, "refs/remotes/%s/", rename->old_name);
Christian Couder59556542013-11-30 21:55:40 +0100588 if (starts_with(refname, buf.buf)) {
René Scharfefe583c62018-08-01 12:19:07 +0200589 item = string_list_append(rename->remote_branches, refname);
Ronnie Sahlberg7695d112014-07-15 12:59:36 -0700590 symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING,
René Scharfe744c0402017-09-23 11:45:04 +0200591 NULL, &flag);
Taylor Blau56710a72022-03-03 17:25:18 -0500592 if (symref && (flag & REF_ISSYMREF)) {
Miklos Vajnabf984212008-11-03 19:26:18 +0100593 item->util = xstrdup(symref);
Taylor Blau56710a72022-03-03 17:25:18 -0500594 rename->symrefs_nr++;
595 } else {
Miklos Vajnabf984212008-11-03 19:26:18 +0100596 item->util = NULL;
Taylor Blau56710a72022-03-03 17:25:18 -0500597 }
Miklos Vajnabf984212008-11-03 19:26:18 +0100598 }
Rene Scharfee2581b72017-08-30 20:00:25 +0200599 strbuf_release(&buf);
Miklos Vajnabf984212008-11-03 19:26:18 +0100600
601 return 0;
602}
603
Miklos Vajna1dd12392008-11-10 21:43:01 +0100604static int migrate_file(struct remote *remote)
605{
606 struct strbuf buf = STRBUF_INIT;
607 int i;
Miklos Vajna1dd12392008-11-10 21:43:01 +0100608
609 strbuf_addf(&buf, "remote.%s.url", remote->name);
610 for (i = 0; i < remote->url_nr; i++)
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100611 git_config_set_multivar(buf.buf, remote->url[i], "^$", 0);
Miklos Vajna1dd12392008-11-10 21:43:01 +0100612 strbuf_reset(&buf);
613 strbuf_addf(&buf, "remote.%s.push", remote->name);
Brandon Williams6bdb3042018-05-16 15:58:00 -0700614 for (i = 0; i < remote->push.raw_nr; i++)
615 git_config_set_multivar(buf.buf, remote->push.raw[i], "^$", 0);
Miklos Vajna1dd12392008-11-10 21:43:01 +0100616 strbuf_reset(&buf);
617 strbuf_addf(&buf, "remote.%s.fetch", remote->name);
Brandon Williamse5349ab2018-05-16 15:58:01 -0700618 for (i = 0; i < remote->fetch.raw_nr; i++)
619 git_config_set_multivar(buf.buf, remote->fetch.raw[i], "^$", 0);
Miklos Vajna1dd12392008-11-10 21:43:01 +0100620 if (remote->origin == REMOTE_REMOTES)
Jeff Kingb21a5d62015-08-10 05:35:49 -0400621 unlink_or_warn(git_path("remotes/%s", remote->name));
Miklos Vajna1dd12392008-11-10 21:43:01 +0100622 else if (remote->origin == REMOTE_BRANCHES)
Jeff Kingb21a5d62015-08-10 05:35:49 -0400623 unlink_or_warn(git_path("branches/%s", remote->name));
Rene Scharfeb95c8ce2017-08-30 20:00:26 +0200624 strbuf_release(&buf);
Patrick Steinhardtc397deb2016-02-22 12:23:30 +0100625
Miklos Vajna1dd12392008-11-10 21:43:01 +0100626 return 0;
627}
628
Bert Wesargb3fd6cb2020-02-01 10:34:09 +0100629struct push_default_info
630{
631 const char *old_name;
632 enum config_scope scope;
633 struct strbuf origin;
634 int linenr;
635};
636
637static int config_read_push_default(const char *key, const char *value,
638 void *cb)
639{
640 struct push_default_info* info = cb;
641 if (strcmp(key, "remote.pushdefault") ||
642 !value || strcmp(value, info->old_name))
643 return 0;
644
645 info->scope = current_config_scope();
646 strbuf_reset(&info->origin);
647 strbuf_addstr(&info->origin, current_config_name());
648 info->linenr = current_config_line();
649
650 return 0;
651}
652
653static void handle_push_default(const char* old_name, const char* new_name)
654{
655 struct push_default_info push_default = {
656 old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 };
657 git_config(config_read_push_default, &push_default);
658 if (push_default.scope >= CONFIG_SCOPE_COMMAND)
659 ; /* pass */
660 else if (push_default.scope >= CONFIG_SCOPE_LOCAL) {
661 int result = git_config_set_gently("remote.pushDefault",
662 new_name);
663 if (new_name && result && result != CONFIG_NOTHING_SET)
664 die(_("could not set '%s'"), "remote.pushDefault");
665 else if (!new_name && result && result != CONFIG_NOTHING_SET)
666 die(_("could not unset '%s'"), "remote.pushDefault");
667 } else if (push_default.scope >= CONFIG_SCOPE_SYSTEM) {
668 /* warn */
669 warning(_("The %s configuration remote.pushDefault in:\n"
670 "\t%s:%d\n"
671 "now names the non-existent remote '%s'"),
672 config_scope_name(push_default.scope),
673 push_default.origin.buf, push_default.linenr,
674 old_name);
675 }
676}
677
678
Miklos Vajnabf984212008-11-03 19:26:18 +0100679static int mv(int argc, const char **argv)
680{
Taylor Blau56710a72022-03-03 17:25:18 -0500681 int show_progress = isatty(2);
Miklos Vajnabf984212008-11-03 19:26:18 +0100682 struct option options[] = {
Taylor Blau56710a72022-03-03 17:25:18 -0500683 OPT_BOOL(0, "progress", &show_progress, N_("force progress reporting")),
Miklos Vajnabf984212008-11-03 19:26:18 +0100684 OPT_END()
685 };
686 struct remote *oldremote, *newremote;
Martin von Zweigbergk28f555f2011-09-01 20:50:33 -0400687 struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
688 old_remote_context = STRBUF_INIT;
René Scharfefe583c62018-08-01 12:19:07 +0200689 struct string_list remote_branches = STRING_LIST_INIT_DUP;
Miklos Vajnabf984212008-11-03 19:26:18 +0100690 struct rename_info rename;
Taylor Blau56710a72022-03-03 17:25:18 -0500691 int i, refs_renamed_nr = 0, refspec_updated = 0;
692 struct progress *progress = NULL;
Miklos Vajnabf984212008-11-03 19:26:18 +0100693
Taylor Blauc6dddb32022-03-03 17:25:16 -0500694 argc = parse_options(argc, argv, NULL, options,
695 builtin_remote_rename_usage, 0);
696
697 if (argc != 2)
Tim Henigan45041072009-11-20 18:43:13 -0500698 usage_with_options(builtin_remote_rename_usage, options);
Miklos Vajnabf984212008-11-03 19:26:18 +0100699
Taylor Blauc6dddb32022-03-03 17:25:16 -0500700 rename.old_name = argv[0];
701 rename.new_name = argv[1];
Miklos Vajnabf984212008-11-03 19:26:18 +0100702 rename.remote_branches = &remote_branches;
Taylor Blau56710a72022-03-03 17:25:18 -0500703 rename.symrefs_nr = 0;
Miklos Vajnabf984212008-11-03 19:26:18 +0100704
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800705 oldremote = remote_get(rename.old_name);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +0100706 if (!remote_is_configured(oldremote, 1)) {
707 error(_("No such remote: '%s'"), rename.old_name);
708 exit(2);
709 }
Miklos Vajnabf984212008-11-03 19:26:18 +0100710
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800711 if (!strcmp(rename.old_name, rename.new_name) && oldremote->origin != REMOTE_CONFIG)
Miklos Vajna1dd12392008-11-10 21:43:01 +0100712 return migrate_file(oldremote);
713
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800714 newremote = remote_get(rename.new_name);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +0100715 if (remote_is_configured(newremote, 1)) {
716 error(_("remote %s already exists."), rename.new_name);
717 exit(3);
718 }
Miklos Vajnabf984212008-11-03 19:26:18 +0100719
Sean Baragf2c6fda2020-10-01 03:46:13 +0000720 if (!valid_remote_name(rename.new_name))
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800721 die(_("'%s' is not a valid remote name"), rename.new_name);
Miklos Vajnabf984212008-11-03 19:26:18 +0100722
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800723 strbuf_addf(&buf, "remote.%s", rename.old_name);
724 strbuf_addf(&buf2, "remote.%s", rename.new_name);
Miklos Vajnabf984212008-11-03 19:26:18 +0100725 if (git_config_rename_section(buf.buf, buf2.buf) < 1)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700726 return error(_("Could not rename config section '%s' to '%s'"),
Miklos Vajnabf984212008-11-03 19:26:18 +0100727 buf.buf, buf2.buf);
728
729 strbuf_reset(&buf);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800730 strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
Derrick Stolee504ee122020-11-25 22:12:49 +0000731 git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800732 strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
Brandon Williamse5349ab2018-05-16 15:58:01 -0700733 for (i = 0; i < oldremote->fetch.raw_nr; i++) {
Miklos Vajnabf984212008-11-03 19:26:18 +0100734 char *ptr;
735
736 strbuf_reset(&buf2);
Brandon Williamse5349ab2018-05-16 15:58:01 -0700737 strbuf_addstr(&buf2, oldremote->fetch.raw[i]);
Martin von Zweigbergk28f555f2011-09-01 20:50:33 -0400738 ptr = strstr(buf2.buf, old_remote_context.buf);
Martin von Zweigbergkb52d00a2011-09-10 15:39:23 -0400739 if (ptr) {
740 refspec_updated = 1;
Martin von Zweigbergk28f555f2011-09-01 20:50:33 -0400741 strbuf_splice(&buf2,
742 ptr-buf2.buf + strlen(":refs/remotes/"),
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800743 strlen(rename.old_name), rename.new_name,
744 strlen(rename.new_name));
Martin von Zweigbergkb52d00a2011-09-10 15:39:23 -0400745 } else
Ralf Thielowaa3bb872012-05-18 18:46:01 +0200746 warning(_("Not updating non-default fetch refspec\n"
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700747 "\t%s\n"
748 "\tPlease update the configuration manually if necessary."),
Martin von Zweigbergk1822b862011-09-03 11:26:59 -0400749 buf2.buf);
750
Patrick Steinhardt3d180642016-02-22 12:23:36 +0100751 git_config_set_multivar(buf.buf, buf2.buf, "^$", 0);
Miklos Vajnabf984212008-11-03 19:26:18 +0100752 }
753
754 read_branches();
755 for (i = 0; i < branch_list.nr; i++) {
756 struct string_list_item *item = branch_list.items + i;
757 struct branch_info *info = item->util;
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800758 if (info->remote_name && !strcmp(info->remote_name, rename.old_name)) {
Miklos Vajnabf984212008-11-03 19:26:18 +0100759 strbuf_reset(&buf);
760 strbuf_addf(&buf, "branch.%s.remote", item->string);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800761 git_config_set(buf.buf, rename.new_name);
Miklos Vajnabf984212008-11-03 19:26:18 +0100762 }
Bert Wesarg923d4a52020-01-27 08:04:30 +0100763 if (info->push_remote_name && !strcmp(info->push_remote_name, rename.old_name)) {
764 strbuf_reset(&buf);
Ævar Arnfjörð Bjarmason0f1da602021-02-25 02:21:17 +0100765 strbuf_addf(&buf, "branch.%s.pushRemote", item->string);
Bert Wesarg923d4a52020-01-27 08:04:30 +0100766 git_config_set(buf.buf, rename.new_name);
767 }
Miklos Vajnabf984212008-11-03 19:26:18 +0100768 }
769
Martin von Zweigbergkb52d00a2011-09-10 15:39:23 -0400770 if (!refspec_updated)
771 return 0;
772
Miklos Vajnabf984212008-11-03 19:26:18 +0100773 /*
774 * First remove symrefs, then rename the rest, finally create
775 * the new symrefs.
776 */
Michael Haggerty53dc95b2015-05-25 18:38:43 +0000777 for_each_ref(read_remote_branches, &rename);
Taylor Blau56710a72022-03-03 17:25:18 -0500778 if (show_progress) {
779 /*
780 * Count symrefs twice, since "renaming" them is done by
781 * deleting and recreating them in two separate passes.
782 */
783 progress = start_progress(_("Renaming remote references"),
784 rename.remote_branches->nr + rename.symrefs_nr);
785 }
Miklos Vajnabf984212008-11-03 19:26:18 +0100786 for (i = 0; i < remote_branches.nr; i++) {
787 struct string_list_item *item = remote_branches.items + i;
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +0100788 struct strbuf referent = STRBUF_INIT;
Miklos Vajnabf984212008-11-03 19:26:18 +0100789
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +0100790 if (refs_read_symbolic_ref(get_main_ref_store(the_repository), item->string,
791 &referent))
Miklos Vajnabf984212008-11-03 19:26:18 +0100792 continue;
Michael Haggerty91774af2017-11-05 09:42:06 +0100793 if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700794 die(_("deleting '%s' failed"), item->string);
Patrick Steinhardt1553f5e2022-03-01 10:33:50 +0100795
796 strbuf_release(&referent);
Taylor Blau56710a72022-03-03 17:25:18 -0500797 display_progress(progress, ++refs_renamed_nr);
Miklos Vajnabf984212008-11-03 19:26:18 +0100798 }
799 for (i = 0; i < remote_branches.nr; i++) {
800 struct string_list_item *item = remote_branches.items + i;
801
802 if (item->util)
803 continue;
804 strbuf_reset(&buf);
805 strbuf_addstr(&buf, item->string);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800806 strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
807 rename.new_name, strlen(rename.new_name));
Miklos Vajnabf984212008-11-03 19:26:18 +0100808 strbuf_reset(&buf2);
809 strbuf_addf(&buf2, "remote: renamed %s to %s",
810 item->string, buf.buf);
811 if (rename_ref(item->string, buf.buf, buf2.buf))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700812 die(_("renaming '%s' failed"), item->string);
Taylor Blau56710a72022-03-03 17:25:18 -0500813 display_progress(progress, ++refs_renamed_nr);
Miklos Vajnabf984212008-11-03 19:26:18 +0100814 }
815 for (i = 0; i < remote_branches.nr; i++) {
816 struct string_list_item *item = remote_branches.items + i;
817
818 if (!item->util)
819 continue;
820 strbuf_reset(&buf);
821 strbuf_addstr(&buf, item->string);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800822 strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
823 rename.new_name, strlen(rename.new_name));
Miklos Vajnabf984212008-11-03 19:26:18 +0100824 strbuf_reset(&buf2);
825 strbuf_addstr(&buf2, item->util);
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800826 strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old_name),
827 rename.new_name, strlen(rename.new_name));
Miklos Vajnabf984212008-11-03 19:26:18 +0100828 strbuf_reset(&buf3);
829 strbuf_addf(&buf3, "remote: renamed %s to %s",
830 item->string, buf.buf);
831 if (create_symref(buf.buf, buf2.buf, buf3.buf))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700832 die(_("creating '%s' failed"), buf.buf);
Taylor Blau56710a72022-03-03 17:25:18 -0500833 display_progress(progress, ++refs_renamed_nr);
Miklos Vajnabf984212008-11-03 19:26:18 +0100834 }
Taylor Blau56710a72022-03-03 17:25:18 -0500835 stop_progress(&progress);
René Scharfefe583c62018-08-01 12:19:07 +0200836 string_list_clear(&remote_branches, 1);
Bert Wesargb3fd6cb2020-02-01 10:34:09 +0100837
838 handle_push_default(rename.old_name, rename.new_name);
839
Miklos Vajnabf984212008-11-03 19:26:18 +0100840 return 0;
841}
842
Johannes Schindelin211c8962008-02-29 01:45:45 +0000843static int rm(int argc, const char **argv)
844{
845 struct option options[] = {
846 OPT_END()
847 };
848 struct remote *remote;
Brandon Caseyf285a2d2008-10-09 14:12:12 -0500849 struct strbuf buf = STRBUF_INIT;
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400850 struct known_remotes known_remotes = { NULL, NULL };
Thiago Farina183113a2010-07-04 16:46:19 -0300851 struct string_list branches = STRING_LIST_INIT_DUP;
852 struct string_list skipped = STRING_LIST_INIT_DUP;
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000853 struct branches_for_remote cb_data;
Jay Soffiane02f1762009-02-03 12:51:12 -0500854 int i, result;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000855
Gary V. Vaughan66dbfd52010-05-14 09:31:33 +0000856 memset(&cb_data, 0, sizeof(cb_data));
857 cb_data.branches = &branches;
858 cb_data.skipped = &skipped;
859 cb_data.keep = &known_remotes;
860
Johannes Schindelin211c8962008-02-29 01:45:45 +0000861 if (argc != 2)
Tim Henigan45041072009-11-20 18:43:13 -0500862 usage_with_options(builtin_remote_rm_usage, options);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000863
864 remote = remote_get(argv[1]);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +0100865 if (!remote_is_configured(remote, 1)) {
866 error(_("No such remote: '%s'"), argv[1]);
867 exit(2);
868 }
Johannes Schindelin211c8962008-02-29 01:45:45 +0000869
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400870 known_remotes.to_delete = remote;
871 for_each_remote(add_known_remote, &known_remotes);
872
Johannes Schindelin211c8962008-02-29 01:45:45 +0000873 read_branches();
874 for (i = 0; i < branch_list.nr; i++) {
Johannes Schindelinc455c872008-07-21 19:03:49 +0100875 struct string_list_item *item = branch_list.items + i;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000876 struct branch_info *info = item->util;
Jay Soffiane0cc81e2009-02-25 03:32:21 -0500877 if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
Johannes Schindelin211c8962008-02-29 01:45:45 +0000878 const char *keys[] = { "remote", "merge", NULL }, **k;
879 for (k = keys; *k; k++) {
880 strbuf_reset(&buf);
881 strbuf_addf(&buf, "branch.%s.%s",
Johannes Schindelinc455c872008-07-21 19:03:49 +0100882 item->string, *k);
Ross Lagerwall20690b22017-02-18 00:23:41 +0000883 result = git_config_set_gently(buf.buf, NULL);
884 if (result && result != CONFIG_NOTHING_SET)
885 die(_("could not unset '%s'"), buf.buf);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000886 }
887 }
Bert Wesarg923d4a52020-01-27 08:04:30 +0100888 if (info->push_remote_name && !strcmp(info->push_remote_name, remote->name)) {
889 strbuf_reset(&buf);
890 strbuf_addf(&buf, "branch.%s.pushremote", item->string);
891 result = git_config_set_gently(buf.buf, NULL);
892 if (result && result != CONFIG_NOTHING_SET)
893 die(_("could not unset '%s'"), buf.buf);
894 }
Johannes Schindelin211c8962008-02-29 01:45:45 +0000895 }
896
897 /*
898 * We cannot just pass a function to for_each_ref() which deletes
899 * the branches one by one, since for_each_ref() relies on cached
900 * refs, which are invalidated when deleting a branch.
901 */
Shawn O. Pearce7ad24582008-06-01 00:28:04 -0400902 cb_data.remote = remote;
Michael Haggerty45690a52015-05-25 18:38:41 +0000903 result = for_each_ref(add_branch_for_removal, &cb_data);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000904 strbuf_release(&buf);
905
Jay Soffiane02f1762009-02-03 12:51:12 -0500906 if (!result)
Michael Haggerty91774af2017-11-05 09:42:06 +0100907 result = delete_refs("remote: remove", &branches, REF_NO_DEREF);
Michael Haggertye26cdf92015-05-25 18:38:42 +0000908 string_list_clear(&branches, 0);
Johannes Schindelin211c8962008-02-29 01:45:45 +0000909
Jay Soffian441adf02009-02-04 11:06:07 -0500910 if (skipped.nr) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +0700911 fprintf_ln(stderr,
912 Q_("Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
913 "to delete it, use:",
914 "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
915 "to delete them, use:",
916 skipped.nr));
Jay Soffian441adf02009-02-04 11:06:07 -0500917 for (i = 0; i < skipped.nr; i++)
918 fprintf(stderr, " git branch -d %s\n",
919 skipped.items[i].string);
920 }
921 string_list_clear(&skipped, 0);
922
Jens Lindströmb07bdd32014-05-23 12:28:43 +0200923 if (!result) {
924 strbuf_addf(&buf, "remote.%s", remote->name);
925 if (git_config_rename_section(buf.buf, NULL) < 1)
926 return error(_("Could not remove config section '%s'"), buf.buf);
Bert Wesargb3fd6cb2020-02-01 10:34:09 +0100927
928 handle_push_default(remote->name, NULL);
Jens Lindströmb07bdd32014-05-23 12:28:43 +0200929 }
930
Jay Soffiane02f1762009-02-03 12:51:12 -0500931 return result;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000932}
933
Linus Torvalds2af202b2009-06-18 10:28:43 -0700934static void clear_push_info(void *util, const char *string)
Johannes Schindelin211c8962008-02-29 01:45:45 +0000935{
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500936 struct push_info *info = util;
937 free(info->dest);
938 free(info);
939}
Johannes Schindelin211c8962008-02-29 01:45:45 +0000940
Jay Soffian88733232009-02-25 03:32:19 -0500941static void free_remote_ref_states(struct ref_states *states)
942{
Brandon Williamsb537e0b2018-02-14 10:59:35 -0800943 string_list_clear(&states->new_refs, 0);
Bert Wesarg92f676f2009-12-01 00:57:27 +0100944 string_list_clear(&states->stale, 1);
Jay Soffian88733232009-02-25 03:32:19 -0500945 string_list_clear(&states->tracked, 0);
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500946 string_list_clear(&states->heads, 0);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500947 string_list_clear_func(&states->push, clear_push_info);
Jay Soffian88733232009-02-25 03:32:19 -0500948}
Johannes Schindelin211c8962008-02-29 01:45:45 +0000949
Jay Soffiancca7c972009-02-25 03:32:22 -0500950static int append_ref_to_tracked_list(const char *refname,
Michael Haggerty53dc95b2015-05-25 18:38:43 +0000951 const struct object_id *oid, int flags, void *cb_data)
Jay Soffiancca7c972009-02-25 03:32:22 -0500952{
953 struct ref_states *states = cb_data;
Brandon Williams0ad4a5f2018-05-16 15:57:49 -0700954 struct refspec_item refspec;
Jay Soffiancca7c972009-02-25 03:32:22 -0500955
Jay Soffian3bd92562009-02-25 03:32:23 -0500956 if (flags & REF_ISSYMREF)
957 return 0;
958
Jay Soffiancca7c972009-02-25 03:32:22 -0500959 memset(&refspec, 0, sizeof(refspec));
960 refspec.dst = (char *)refname;
961 if (!remote_find_tracking(states->remote, &refspec))
Julian Phillips1d2f80f2010-06-26 00:41:38 +0100962 string_list_append(&states->tracked, abbrev_branch(refspec.src));
Jay Soffiancca7c972009-02-25 03:32:22 -0500963
964 return 0;
Johannes Schindelin211c8962008-02-29 01:45:45 +0000965}
966
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200967static int get_remote_ref_states(const char *name,
968 struct ref_states *states,
969 int query)
970{
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200971 states->remote = remote_get(name);
972 if (!states->remote)
Shulhan50254252018-09-13 20:18:33 +0700973 return error(_("No such remote: '%s'"), name);
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200974
975 read_branches();
976
977 if (query) {
Andrzej Hunt68ffe092021-03-21 16:58:37 +0000978 struct transport *transport;
979 const struct ref *remote_refs;
980
Chris Frey345a3802009-06-25 17:21:35 -0400981 transport = transport_get(states->remote, states->remote->url_nr > 0 ?
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200982 states->remote->url[0] : NULL);
Brandon Williams1af8ae12018-03-15 10:31:23 -0700983 remote_refs = transport_get_remote_refs(transport, NULL);
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200984
Jay Soffian7ecbbf82009-02-25 03:32:27 -0500985 states->queried = 1;
Jay Soffiane61e0cc2009-02-25 03:32:24 -0500986 if (query & GET_REF_STATES)
987 get_ref_states(remote_refs, states);
988 if (query & GET_HEAD_NAMES)
989 get_head_names(remote_refs, states);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500990 if (query & GET_PUSH_REF_STATES)
991 get_push_ref_states(remote_refs, states);
Andrzej Hunt68ffe092021-03-21 16:58:37 +0000992 transport_disconnect(transport);
Jay Soffian3bd92562009-02-25 03:32:23 -0500993 } else {
Michael Haggerty53dc95b2015-05-25 18:38:43 +0000994 for_each_ref(append_ref_to_tracked_list, states);
Michael Haggerty3383e192014-11-25 09:02:35 +0100995 string_list_sort(&states->tracked);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -0500996 get_push_ref_states_noquery(states);
Olivier Marin67a7e2d2008-06-10 16:51:21 +0200997 }
998
999 return 0;
1000}
1001
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001002struct show_info {
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001003 struct string_list list;
1004 struct ref_states states;
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001005 int width, width2;
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001006 int any_rebase;
1007};
1008
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001009#define SHOW_INFO_INIT { \
1010 .list = STRING_LIST_INIT_DUP, \
1011 .states = REF_STATES_INIT, \
1012}
1013
Linus Torvalds2af202b2009-06-18 10:28:43 -07001014static int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
Olivier Marine7d5a972008-06-11 00:54:49 +02001015{
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001016 struct show_info *info = cb_data;
1017 int n = strlen(item->string);
1018 if (n > info->width)
1019 info->width = n;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001020 string_list_insert(&info->list, item->string);
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001021 return 0;
1022}
Olivier Marine7d5a972008-06-11 00:54:49 +02001023
Linus Torvalds2af202b2009-06-18 10:28:43 -07001024static int show_remote_info_item(struct string_list_item *item, void *cb_data)
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001025{
1026 struct show_info *info = cb_data;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001027 struct ref_states *states = &info->states;
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001028 const char *name = item->string;
Olivier Marine7d5a972008-06-11 00:54:49 +02001029
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001030 if (states->queried) {
1031 const char *fmt = "%s";
1032 const char *arg = "";
Brandon Williamsb537e0b2018-02-14 10:59:35 -08001033 if (string_list_has_string(&states->new_refs, name)) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001034 fmt = _(" new (next fetch will store in remotes/%s)");
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001035 arg = states->remote->name;
1036 } else if (string_list_has_string(&states->tracked, name))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001037 arg = _(" tracked");
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001038 else if (string_list_has_string(&states->stale, name))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001039 arg = _(" stale (use 'git remote prune' to remove)");
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001040 else
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001041 arg = _(" ???");
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001042 printf(" %-*s", info->width, name);
1043 printf(fmt, arg);
1044 printf("\n");
1045 } else
1046 printf(" %s\n", name);
1047
1048 return 0;
1049}
1050
Linus Torvalds2af202b2009-06-18 10:28:43 -07001051static int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001052{
1053 struct show_info *show_info = cb_data;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001054 struct ref_states *states = &show_info->states;
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001055 struct branch_info *branch_info = branch_item->util;
1056 struct string_list_item *item;
1057 int n;
1058
1059 if (!branch_info->merge.nr || !branch_info->remote_name ||
1060 strcmp(states->remote->name, branch_info->remote_name))
1061 return 0;
1062 if ((n = strlen(branch_item->string)) > show_info->width)
1063 show_info->width = n;
Bert Wesarg88f85762020-01-27 08:04:27 +01001064 if (branch_info->rebase >= REBASE_TRUE)
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001065 show_info->any_rebase = 1;
1066
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001067 item = string_list_insert(&show_info->list, branch_item->string);
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001068 item->util = branch_info;
1069
1070 return 0;
1071}
1072
Linus Torvalds2af202b2009-06-18 10:28:43 -07001073static int show_local_info_item(struct string_list_item *item, void *cb_data)
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001074{
1075 struct show_info *show_info = cb_data;
1076 struct branch_info *branch_info = item->util;
1077 struct string_list *merge = &branch_info->merge;
Vasco Almeidaa1b467a2016-06-17 20:21:22 +00001078 int width = show_info->width + 4;
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001079 int i;
1080
Bert Wesarg88f85762020-01-27 08:04:27 +01001081 if (branch_info->rebase >= REBASE_TRUE && branch_info->merge.nr > 1) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001082 error(_("invalid branch.%s.merge; cannot rebase onto > 1 branch"),
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001083 item->string);
1084 return 0;
1085 }
1086
1087 printf(" %-*s ", show_info->width, item->string);
Bert Wesarg88f85762020-01-27 08:04:27 +01001088 if (branch_info->rebase >= REBASE_TRUE) {
Johannes Schindelin1131ec92018-04-25 14:29:38 +02001089 const char *msg;
Bert Wesarg88f85762020-01-27 08:04:27 +01001090 if (branch_info->rebase == REBASE_INTERACTIVE)
Johannes Schindelin1131ec92018-04-25 14:29:38 +02001091 msg = _("rebases interactively onto remote %s");
1092 else if (branch_info->rebase == REBASE_MERGES)
1093 msg = _("rebases interactively (with merges) onto "
1094 "remote %s");
1095 else
1096 msg = _("rebases onto remote %s");
1097 printf_ln(msg, merge->items[0].string);
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001098 return 0;
1099 } else if (show_info->any_rebase) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001100 printf_ln(_(" merges with remote %s"), merge->items[0].string);
Vasco Almeidaa1b467a2016-06-17 20:21:22 +00001101 width++;
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001102 } else {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001103 printf_ln(_("merges with remote %s"), merge->items[0].string);
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001104 }
1105 for (i = 1; i < merge->nr; i++)
Vasco Almeidaa1b467a2016-06-17 20:21:22 +00001106 printf(_("%-*s and with remote %s\n"), width, "",
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001107 merge->items[i].string);
1108
1109 return 0;
1110}
1111
Linus Torvalds2af202b2009-06-18 10:28:43 -07001112static int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001113{
1114 struct show_info *show_info = cb_data;
1115 struct push_info *push_info = push_item->util;
1116 struct string_list_item *item;
1117 int n;
1118 if ((n = strlen(push_item->string)) > show_info->width)
1119 show_info->width = n;
1120 if ((n = strlen(push_info->dest)) > show_info->width2)
1121 show_info->width2 = n;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001122 item = string_list_append(&show_info->list, push_item->string);
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001123 item->util = push_item->util;
1124 return 0;
1125}
1126
Jeff King48ef5632009-03-22 04:59:20 -04001127/*
1128 * Sorting comparison for a string list that has push_info
1129 * structs in its util field
1130 */
1131static int cmp_string_with_push(const void *va, const void *vb)
1132{
1133 const struct string_list_item *a = va;
1134 const struct string_list_item *b = vb;
1135 const struct push_info *a_push = a->util;
1136 const struct push_info *b_push = b->util;
1137 int cmp = strcmp(a->string, b->string);
1138 return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
1139}
1140
Linus Torvalds2af202b2009-06-18 10:28:43 -07001141static int show_push_info_item(struct string_list_item *item, void *cb_data)
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001142{
1143 struct show_info *show_info = cb_data;
1144 struct push_info *push_info = item->util;
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001145 const char *src = item->string, *status = NULL;
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001146
1147 switch (push_info->status) {
1148 case PUSH_STATUS_CREATE:
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001149 status = _("create");
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001150 break;
1151 case PUSH_STATUS_DELETE:
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001152 status = _("delete");
1153 src = _("(none)");
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001154 break;
1155 case PUSH_STATUS_UPTODATE:
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001156 status = _("up to date");
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001157 break;
1158 case PUSH_STATUS_FASTFORWARD:
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001159 status = _("fast-forwardable");
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001160 break;
1161 case PUSH_STATUS_OUTOFDATE:
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001162 status = _("local out of date");
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001163 break;
1164 case PUSH_STATUS_NOTQUERIED:
1165 break;
1166 }
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001167 if (status) {
1168 if (push_info->forced)
1169 printf_ln(_(" %-*s forces to %-*s (%s)"), show_info->width, src,
1170 show_info->width2, push_info->dest, status);
1171 else
1172 printf_ln(_(" %-*s pushes to %-*s (%s)"), show_info->width, src,
1173 show_info->width2, push_info->dest, status);
1174 } else {
1175 if (push_info->forced)
1176 printf_ln(_(" %-*s forces to %s"), show_info->width, src,
1177 push_info->dest);
1178 else
1179 printf_ln(_(" %-*s pushes to %s"), show_info->width, src,
1180 push_info->dest);
1181 }
Olivier Marine7d5a972008-06-11 00:54:49 +02001182 return 0;
1183}
1184
Michael Haggertyce2223f2013-10-30 06:33:02 +01001185static int get_one_entry(struct remote *remote, void *priv)
1186{
1187 struct string_list *list = priv;
1188 struct strbuf url_buf = STRBUF_INIT;
1189 const char **url;
1190 int i, url_nr;
1191
1192 if (remote->url_nr > 0) {
1193 strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
1194 string_list_append(list, remote->name)->util =
1195 strbuf_detach(&url_buf, NULL);
1196 } else
1197 string_list_append(list, remote->name)->util = NULL;
1198 if (remote->pushurl_nr) {
1199 url = remote->pushurl;
1200 url_nr = remote->pushurl_nr;
1201 } else {
1202 url = remote->url;
1203 url_nr = remote->url_nr;
1204 }
1205 for (i = 0; i < url_nr; i++)
1206 {
1207 strbuf_addf(&url_buf, "%s (push)", url[i]);
1208 string_list_append(list, remote->name)->util =
1209 strbuf_detach(&url_buf, NULL);
1210 }
1211
1212 return 0;
1213}
1214
1215static int show_all(void)
1216{
1217 struct string_list list = STRING_LIST_INIT_NODUP;
1218 int result;
1219
1220 list.strdup_strings = 1;
1221 result = for_each_remote(get_one_entry, &list);
1222
1223 if (!result) {
1224 int i;
1225
Michael Haggerty3383e192014-11-25 09:02:35 +01001226 string_list_sort(&list);
Michael Haggertyce2223f2013-10-30 06:33:02 +01001227 for (i = 0; i < list.nr; i++) {
1228 struct string_list_item *item = list.items + i;
1229 if (verbose)
1230 printf("%s\t%s\n", item->string,
1231 item->util ? (const char *)item->util : "");
1232 else {
1233 if (i && !strcmp((item - 1)->string, item->string))
1234 continue;
1235 printf("%s\n", item->string);
1236 }
1237 }
1238 }
1239 string_list_clear(&list, 1);
1240 return result;
1241}
1242
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001243static int show(int argc, const char **argv)
Johannes Schindelin211c8962008-02-29 01:45:45 +00001244{
Jay Soffiane61e0cc2009-02-25 03:32:24 -05001245 int no_query = 0, result = 0, query_flag = 0;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001246 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +02001247 OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
Johannes Schindelin211c8962008-02-29 01:45:45 +00001248 OPT_END()
1249 };
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001250 struct show_info info = SHOW_INFO_INIT;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001251
Tim Henigan45041072009-11-20 18:43:13 -05001252 argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
Stephen Boyd37782922009-05-23 11:53:12 -07001253 0);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001254
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001255 if (argc < 1)
1256 return show_all();
Johannes Schindelin211c8962008-02-29 01:45:45 +00001257
Jay Soffiane61e0cc2009-02-25 03:32:24 -05001258 if (!no_query)
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001259 query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
Jay Soffiane61e0cc2009-02-25 03:32:24 -05001260
Johannes Schindelin211c8962008-02-29 01:45:45 +00001261 for (; argc; argc--, argv++) {
Olivier Marin0ecfcb32008-06-10 16:51:08 +02001262 int i;
Michael J Gruber857f8c32009-06-13 18:29:10 +02001263 const char **url;
1264 int url_nr;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001265
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001266 get_remote_ref_states(*argv, &info.states, query_flag);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001267
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001268 printf_ln(_("* remote %s"), *argv);
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001269 printf_ln(_(" Fetch URL: %s"), info.states.remote->url_nr > 0 ?
1270 info.states.remote->url[0] : _("(no URL)"));
1271 if (info.states.remote->pushurl_nr) {
1272 url = info.states.remote->pushurl;
1273 url_nr = info.states.remote->pushurl_nr;
Michael J Gruber857f8c32009-06-13 18:29:10 +02001274 } else {
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001275 url = info.states.remote->url;
1276 url_nr = info.states.remote->url_nr;
Michael J Gruber857f8c32009-06-13 18:29:10 +02001277 }
Junio C Hamanocd2b8ae2011-08-25 14:46:52 -07001278 for (i = 0; i < url_nr; i++)
Ævar Arnfjörð Bjarmason66f5f6d2017-05-11 21:20:12 +00001279 /*
1280 * TRANSLATORS: the colon ':' should align
1281 * with the one in " Fetch URL: %s"
1282 * translation.
1283 */
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001284 printf_ln(_(" Push URL: %s"), url[i]);
Michael J Gruber857f8c32009-06-13 18:29:10 +02001285 if (!i)
Vasco Almeida7ba7b9a2016-06-17 20:21:21 +00001286 printf_ln(_(" Push URL: %s"), _("(no URL)"));
Olivier Marine7d5a972008-06-11 00:54:49 +02001287 if (no_query)
Vasco Almeida7ba7b9a2016-06-17 20:21:21 +00001288 printf_ln(_(" HEAD branch: %s"), _("(not queried)"));
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001289 else if (!info.states.heads.nr)
Vasco Almeida7ba7b9a2016-06-17 20:21:21 +00001290 printf_ln(_(" HEAD branch: %s"), _("(unknown)"));
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001291 else if (info.states.heads.nr == 1)
1292 printf_ln(_(" HEAD branch: %s"), info.states.heads.items[0].string);
Jay Soffiane61e0cc2009-02-25 03:32:24 -05001293 else {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001294 printf(_(" HEAD branch (remote HEAD is ambiguous,"
1295 " may be one of the following):\n"));
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001296 for (i = 0; i < info.states.heads.nr; i++)
1297 printf(" %s\n", info.states.heads.items[i].string);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001298 }
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001299
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001300 /* remote branch info */
1301 info.width = 0;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001302 for_each_string_list(&info.states.new_refs, add_remote_to_show_info, &info);
1303 for_each_string_list(&info.states.tracked, add_remote_to_show_info, &info);
1304 for_each_string_list(&info.states.stale, add_remote_to_show_info, &info);
1305 if (info.list.nr)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001306 printf_ln(Q_(" Remote branch:%s",
1307 " Remote branches:%s",
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001308 info.list.nr),
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001309 no_query ? _(" (status not queried)") : "");
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001310 for_each_string_list(&info.list, show_remote_info_item, &info);
1311 string_list_clear(&info.list, 0);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001312
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001313 /* git pull info */
1314 info.width = 0;
1315 info.any_rebase = 0;
Julian Phillipsb684e972010-06-26 00:41:34 +01001316 for_each_string_list(&branch_list, add_local_to_show_info, &info);
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001317 if (info.list.nr)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001318 printf_ln(Q_(" Local branch configured for 'git pull':",
1319 " Local branches configured for 'git pull':",
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001320 info.list.nr));
1321 for_each_string_list(&info.list, show_local_info_item, &info);
1322 string_list_clear(&info.list, 0);
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001323
Jay Soffian7ecbbf82009-02-25 03:32:27 -05001324 /* git push info */
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001325 if (info.states.remote->mirror)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001326 printf_ln(_(" Local refs will be mirrored by 'git push'"));
Jay Soffiane5dcbfd2009-02-25 03:32:28 -05001327
1328 info.width = info.width2 = 0;
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001329 for_each_string_list(&info.states.push, add_push_to_show_info, &info);
1330 QSORT(info.list.items, info.list.nr, cmp_string_with_push);
1331 if (info.list.nr)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001332 printf_ln(Q_(" Local ref configured for 'git push'%s:",
1333 " Local refs configured for 'git push'%s:",
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001334 info.list.nr),
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001335 no_query ? _(" (status not queried)") : "");
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001336 for_each_string_list(&info.list, show_push_info_item, &info);
1337 string_list_clear(&info.list, 0);
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001338
Ævar Arnfjörð Bjarmason0000e812021-10-01 12:27:35 +02001339 free_remote_ref_states(&info.states);
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001340 }
1341
1342 return result;
1343}
1344
Jay Soffianbc14fac2009-02-25 03:32:25 -05001345static int set_head(int argc, const char **argv)
1346{
1347 int i, opt_a = 0, opt_d = 0, result = 0;
1348 struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
1349 char *head_name = NULL;
1350
1351 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +02001352 OPT_BOOL('a', "auto", &opt_a,
1353 N_("set refs/remotes/<name>/HEAD according to remote")),
1354 OPT_BOOL('d', "delete", &opt_d,
1355 N_("delete refs/remotes/<name>/HEAD")),
Jay Soffianbc14fac2009-02-25 03:32:25 -05001356 OPT_END()
1357 };
Tim Henigan45041072009-11-20 18:43:13 -05001358 argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
Stephen Boyd37782922009-05-23 11:53:12 -07001359 0);
Jay Soffianbc14fac2009-02-25 03:32:25 -05001360 if (argc)
1361 strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
1362
1363 if (!opt_a && !opt_d && argc == 2) {
1364 head_name = xstrdup(argv[1]);
1365 } else if (opt_a && !opt_d && argc == 1) {
Ævar Arnfjörð Bjarmason0bc77872021-10-01 12:27:34 +02001366 struct ref_states states = REF_STATES_INIT;
Jay Soffianbc14fac2009-02-25 03:32:25 -05001367 get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
1368 if (!states.heads.nr)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001369 result |= error(_("Cannot determine remote HEAD"));
Jay Soffianbc14fac2009-02-25 03:32:25 -05001370 else if (states.heads.nr > 1) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001371 result |= error(_("Multiple remote HEAD branches. "
1372 "Please choose one explicitly with:"));
Jay Soffianbc14fac2009-02-25 03:32:25 -05001373 for (i = 0; i < states.heads.nr; i++)
1374 fprintf(stderr, " git remote set-head %s %s\n",
1375 argv[0], states.heads.items[i].string);
1376 } else
1377 head_name = xstrdup(states.heads.items[0].string);
1378 free_remote_ref_states(&states);
1379 } else if (opt_d && !opt_a && argc == 1) {
Michael Haggerty91774af2017-11-05 09:42:06 +01001380 if (delete_ref(NULL, buf.buf, NULL, REF_NO_DEREF))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001381 result |= error(_("Could not delete %s"), buf.buf);
Jay Soffianbc14fac2009-02-25 03:32:25 -05001382 } else
Tim Henigan45041072009-11-20 18:43:13 -05001383 usage_with_options(builtin_remote_sethead_usage, options);
Jay Soffianbc14fac2009-02-25 03:32:25 -05001384
1385 if (head_name) {
Jay Soffianbc14fac2009-02-25 03:32:25 -05001386 strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
1387 /* make sure it's valid */
Nguyễn Thái Ngọc Duyc6893322011-11-13 17:22:14 +07001388 if (!ref_exists(buf2.buf))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001389 result |= error(_("Not a valid ref: %s"), buf2.buf);
Jay Soffianbc14fac2009-02-25 03:32:25 -05001390 else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001391 result |= error(_("Could not setup %s"), buf.buf);
Christian Schlack5a07c6c2020-09-17 15:27:38 +00001392 else if (opt_a)
Jay Soffianbc14fac2009-02-25 03:32:25 -05001393 printf("%s/HEAD set to %s\n", argv[0], head_name);
1394 free(head_name);
1395 }
1396
1397 strbuf_release(&buf);
1398 strbuf_release(&buf2);
1399 return result;
1400}
1401
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001402static int prune_remote(const char *remote, int dry_run)
1403{
Michael Haggerty85529432014-11-25 09:02:34 +01001404 int result = 0;
Ævar Arnfjörð Bjarmason0bc77872021-10-01 12:27:34 +02001405 struct ref_states states = REF_STATES_INIT;
Michael Haggertyfcce0da2014-11-25 09:02:33 +01001406 struct string_list refs_to_prune = STRING_LIST_INIT_NODUP;
Michael Haggerty85529432014-11-25 09:02:34 +01001407 struct string_list_item *item;
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001408 const char *dangling_msg = dry_run
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001409 ? _(" %s will become dangling!")
1410 : _(" %s has become dangling!");
Junio C Hamanof8948e22009-02-08 23:27:10 -08001411
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001412 get_remote_ref_states(remote, &states, GET_REF_STATES);
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001413
Michael Haggerty16d4fa32014-11-25 09:02:29 +01001414 if (!states.stale.nr) {
1415 free_remote_ref_states(&states);
1416 return 0;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001417 }
1418
Michael Haggerty16d4fa32014-11-25 09:02:29 +01001419 printf_ln(_("Pruning %s"), remote);
1420 printf_ln(_("URL: %s"),
1421 states.remote->url_nr
1422 ? states.remote->url[0]
1423 : _("(no URL)"));
1424
Michael Haggerty85529432014-11-25 09:02:34 +01001425 for_each_string_list_item(item, &states.stale)
1426 string_list_append(&refs_to_prune, item->util);
Michael Haggerty3383e192014-11-25 09:02:35 +01001427 string_list_sort(&refs_to_prune);
Michael Haggerty28d3f212014-11-25 09:02:30 +01001428
Michael Haggertya1223662015-06-22 16:02:58 +02001429 if (!dry_run)
Michael Haggerty64da4192017-05-22 16:17:38 +02001430 result |= delete_refs("remote: prune", &refs_to_prune, 0);
Michael Haggerty16d4fa32014-11-25 09:02:29 +01001431
Michael Haggerty85529432014-11-25 09:02:34 +01001432 for_each_string_list_item(item, &states.stale) {
1433 const char *refname = item->util;
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001434
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001435 if (dry_run)
1436 printf_ln(_(" * [would prune] %s"),
1437 abbrev_ref(refname, "refs/remotes/"));
1438 else
1439 printf_ln(_(" * [pruned] %s"),
1440 abbrev_ref(refname, "refs/remotes/"));
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001441 }
1442
Michael Haggertyfcce0da2014-11-25 09:02:33 +01001443 warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune);
Jens Lindströme6bea662014-05-23 12:30:25 +02001444
Michael Haggertyfcce0da2014-11-25 09:02:33 +01001445 string_list_clear(&refs_to_prune, 0);
Finn Arne Gangstadb92c5f22009-04-03 11:02:37 +02001446 free_remote_ref_states(&states);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001447 return result;
1448}
1449
Michael Haggertyce2223f2013-10-30 06:33:02 +01001450static int prune(int argc, const char **argv)
1451{
1452 int dry_run = 0, result = 0;
1453 struct option options[] = {
1454 OPT__DRY_RUN(&dry_run, N_("dry run")),
1455 OPT_END()
1456 };
1457
1458 argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
1459 0);
1460
1461 if (argc < 1)
1462 usage_with_options(builtin_remote_prune_usage, options);
1463
1464 for (; argc; argc--, argv++)
1465 result |= prune_remote(*argv, dry_run);
1466
1467 return result;
1468}
1469
Björn Gustavsson8db35592009-11-10 09:21:32 +01001470static int get_remote_default(const char *key, const char *value, void *priv)
Johannes Schindelin211c8962008-02-29 01:45:45 +00001471{
Björn Gustavsson8db35592009-11-10 09:21:32 +01001472 if (strcmp(key, "remotes.default") == 0) {
1473 int *found = priv;
1474 *found = 1;
Johannes Schindelin84521ed2008-03-04 11:23:53 +00001475 }
Johannes Schindelin211c8962008-02-29 01:45:45 +00001476 return 0;
1477}
1478
1479static int update(int argc, const char **argv)
1480{
Michael Haggerty90765fa2013-10-30 06:33:04 +01001481 int i, prune = -1;
Finn Arne Gangstadefa54802009-04-03 11:03:44 +02001482 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +02001483 OPT_BOOL('p', "prune", &prune,
1484 N_("prune remotes after fetching")),
Finn Arne Gangstadefa54802009-04-03 11:03:44 +02001485 OPT_END()
1486 };
Jeff King22f9b7f2020-07-28 16:24:27 -04001487 struct strvec fetch_argv = STRVEC_INIT;
Björn Gustavsson8db35592009-11-10 09:21:32 +01001488 int default_defined = 0;
Michael Haggerty86075902013-10-30 06:33:03 +01001489 int retval;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001490
Tim Henigan45041072009-11-20 18:43:13 -05001491 argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
Finn Arne Gangstadefa54802009-04-03 11:03:44 +02001492 PARSE_OPT_KEEP_ARGV0);
Björn Gustavsson8db35592009-11-10 09:21:32 +01001493
Jeff King22f9b7f2020-07-28 16:24:27 -04001494 strvec_push(&fetch_argv, "fetch");
Björn Gustavsson8db35592009-11-10 09:21:32 +01001495
Michael Haggerty90765fa2013-10-30 06:33:04 +01001496 if (prune != -1)
Jeff King22f9b7f2020-07-28 16:24:27 -04001497 strvec_push(&fetch_argv, prune ? "--prune" : "--no-prune");
Björn Gustavsson8db35592009-11-10 09:21:32 +01001498 if (verbose)
Jeff King22f9b7f2020-07-28 16:24:27 -04001499 strvec_push(&fetch_argv, "-v");
1500 strvec_push(&fetch_argv, "--multiple");
Björn Gustavsson4f2e8422009-12-31 10:43:17 +01001501 if (argc < 2)
Jeff King22f9b7f2020-07-28 16:24:27 -04001502 strvec_push(&fetch_argv, "default");
Björn Gustavsson4f2e8422009-12-31 10:43:17 +01001503 for (i = 1; i < argc; i++)
Jeff King22f9b7f2020-07-28 16:24:27 -04001504 strvec_push(&fetch_argv, argv[i]);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001505
Jeff Kingd70a9eb2020-07-28 20:37:20 -04001506 if (strcmp(fetch_argv.v[fetch_argv.nr-1], "default") == 0) {
Björn Gustavsson8db35592009-11-10 09:21:32 +01001507 git_config(get_remote_default, &default_defined);
Michael Haggerty86075902013-10-30 06:33:03 +01001508 if (!default_defined) {
Jeff King22f9b7f2020-07-28 16:24:27 -04001509 strvec_pop(&fetch_argv);
1510 strvec_push(&fetch_argv, "--all");
Michael Haggerty86075902013-10-30 06:33:03 +01001511 }
Johannes Schindelin84521ed2008-03-04 11:23:53 +00001512 }
1513
Jeff Kingd70a9eb2020-07-28 20:37:20 -04001514 retval = run_command_v_opt(fetch_argv.v, RUN_GIT_CMD);
Jeff King22f9b7f2020-07-28 16:24:27 -04001515 strvec_clear(&fetch_argv);
Michael Haggerty86075902013-10-30 06:33:03 +01001516 return retval;
Johannes Schindelin211c8962008-02-29 01:45:45 +00001517}
1518
Jeff King113c29a2019-05-09 17:31:46 -04001519static int remove_all_fetch_refspecs(const char *key)
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001520{
Derrick Stolee504ee122020-11-25 22:12:49 +00001521 return git_config_set_multivar_gently(key, NULL, NULL,
1522 CONFIG_FLAGS_MULTI_REPLACE);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001523}
1524
Patrick Steinhardtab5e4b62016-02-22 12:23:29 +01001525static void add_branches(struct remote *remote, const char **branches,
1526 const char *key)
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001527{
1528 const char *remotename = remote->name;
1529 int mirror = remote->mirror;
1530 struct strbuf refspec = STRBUF_INIT;
1531
1532 for (; *branches; branches++)
Patrick Steinhardtab5e4b62016-02-22 12:23:29 +01001533 add_branch(key, *branches, remotename, mirror, &refspec);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001534
1535 strbuf_release(&refspec);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001536}
1537
1538static int set_remote_branches(const char *remotename, const char **branches,
1539 int add_mode)
1540{
1541 struct strbuf key = STRBUF_INIT;
1542 struct remote *remote;
1543
1544 strbuf_addf(&key, "remote.%s.fetch", remotename);
1545
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001546 remote = remote_get(remotename);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +01001547 if (!remote_is_configured(remote, 1)) {
1548 error(_("No such remote '%s'"), remotename);
1549 exit(2);
1550 }
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001551
Jeff King113c29a2019-05-09 17:31:46 -04001552 if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001553 strbuf_release(&key);
1554 return 1;
1555 }
Patrick Steinhardtab5e4b62016-02-22 12:23:29 +01001556 add_branches(remote, branches, key.buf);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001557
1558 strbuf_release(&key);
1559 return 0;
1560}
1561
1562static int set_branches(int argc, const char **argv)
1563{
1564 int add_mode = 0;
1565 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +02001566 OPT_BOOL('\0', "add", &add_mode, N_("add branch")),
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001567 OPT_END()
1568 };
1569
1570 argc = parse_options(argc, argv, NULL, options,
1571 builtin_remote_setbranches_usage, 0);
1572 if (argc == 0) {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001573 error(_("no remote specified"));
Junio C Hamano656cdf02011-11-06 21:12:59 -08001574 usage_with_options(builtin_remote_setbranches_usage, options);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001575 }
1576 argv[argc] = NULL;
1577
1578 return set_remote_branches(argv[0], argv + 1, add_mode);
1579}
1580
Ben Boeckel96f78d32015-09-15 21:53:47 -04001581static int get_url(int argc, const char **argv)
1582{
1583 int i, push_mode = 0, all_mode = 0;
1584 const char *remotename = NULL;
1585 struct remote *remote;
1586 const char **url;
1587 int url_nr;
1588 struct option options[] = {
1589 OPT_BOOL('\0', "push", &push_mode,
1590 N_("query push URLs rather than fetch URLs")),
1591 OPT_BOOL('\0', "all", &all_mode,
1592 N_("return all URLs")),
1593 OPT_END()
1594 };
1595 argc = parse_options(argc, argv, NULL, options, builtin_remote_geturl_usage, 0);
1596
1597 if (argc != 1)
1598 usage_with_options(builtin_remote_geturl_usage, options);
1599
1600 remotename = argv[0];
1601
Ben Boeckel96f78d32015-09-15 21:53:47 -04001602 remote = remote_get(remotename);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +01001603 if (!remote_is_configured(remote, 1)) {
1604 error(_("No such remote '%s'"), remotename);
1605 exit(2);
1606 }
Ben Boeckel96f78d32015-09-15 21:53:47 -04001607
1608 url_nr = 0;
1609 if (push_mode) {
1610 url = remote->pushurl;
1611 url_nr = remote->pushurl_nr;
1612 }
1613 /* else fetch mode */
1614
1615 /* Use the fetch URL when no push URLs were found or requested. */
1616 if (!url_nr) {
1617 url = remote->url;
1618 url_nr = remote->url_nr;
1619 }
1620
1621 if (!url_nr)
1622 die(_("no URLs configured for remote '%s'"), remotename);
1623
1624 if (all_mode) {
1625 for (i = 0; i < url_nr; i++)
1626 printf_ln("%s", url[i]);
1627 } else {
1628 printf_ln("%s", *url);
1629 }
1630
1631 return 0;
1632}
1633
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001634static int set_url(int argc, const char **argv)
1635{
1636 int i, push_mode = 0, add_mode = 0, delete_mode = 0;
1637 int matches = 0, negative_matches = 0;
1638 const char *remotename = NULL;
1639 const char *newurl = NULL;
1640 const char *oldurl = NULL;
1641 struct remote *remote;
1642 regex_t old_regex;
1643 const char **urlset;
1644 int urlset_nr;
1645 struct strbuf name_buf = STRBUF_INIT;
1646 struct option options[] = {
Stefan Bellerd5d09d42013-08-03 13:51:19 +02001647 OPT_BOOL('\0', "push", &push_mode,
1648 N_("manipulate push URLs")),
1649 OPT_BOOL('\0', "add", &add_mode,
1650 N_("add URL")),
1651 OPT_BOOL('\0', "delete", &delete_mode,
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +07001652 N_("delete URLs")),
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001653 OPT_END()
1654 };
Felipe Contrerasc49904e2011-11-07 05:36:57 +02001655 argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001656 PARSE_OPT_KEEP_ARGV0);
1657
1658 if (add_mode && delete_mode)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001659 die(_("--add --delete doesn't make sense"));
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001660
1661 if (argc < 3 || argc > 4 || ((add_mode || delete_mode) && argc != 3))
1662 usage_with_options(builtin_remote_seturl_usage, options);
1663
1664 remotename = argv[1];
1665 newurl = argv[2];
1666 if (argc > 3)
1667 oldurl = argv[3];
1668
1669 if (delete_mode)
1670 oldurl = newurl;
1671
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001672 remote = remote_get(remotename);
Ævar Arnfjörð Bjarmason9144ba42020-10-27 10:41:36 +01001673 if (!remote_is_configured(remote, 1)) {
1674 error(_("No such remote '%s'"), remotename);
1675 exit(2);
1676 }
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001677
1678 if (push_mode) {
1679 strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
1680 urlset = remote->pushurl;
1681 urlset_nr = remote->pushurl_nr;
1682 } else {
1683 strbuf_addf(&name_buf, "remote.%s.url", remotename);
1684 urlset = remote->url;
1685 urlset_nr = remote->url_nr;
1686 }
1687
1688 /* Special cases that add new entry. */
1689 if ((!oldurl && !delete_mode) || add_mode) {
1690 if (add_mode)
1691 git_config_set_multivar(name_buf.buf, newurl,
Patrick Steinhardt45ebdcc2016-02-22 12:23:28 +01001692 "^$", 0);
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001693 else
1694 git_config_set(name_buf.buf, newurl);
Rene Scharfe85af9f72017-08-30 20:00:27 +02001695 goto out;
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001696 }
1697
1698 /* Old URL specified. Demand that one matches. */
1699 if (regcomp(&old_regex, oldurl, REG_EXTENDED))
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001700 die(_("Invalid old URL pattern: %s"), oldurl);
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001701
1702 for (i = 0; i < urlset_nr; i++)
1703 if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
1704 matches++;
1705 else
1706 negative_matches++;
1707 if (!delete_mode && !matches)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001708 die(_("No such URL found: %s"), oldurl);
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001709 if (delete_mode && !negative_matches && !push_mode)
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001710 die(_("Will not delete all non-push URLs"));
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001711
1712 regfree(&old_regex);
1713
1714 if (!delete_mode)
1715 git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
1716 else
Derrick Stolee504ee122020-11-25 22:12:49 +00001717 git_config_set_multivar(name_buf.buf, NULL, oldurl,
1718 CONFIG_FLAGS_MULTI_REPLACE);
Rene Scharfe85af9f72017-08-30 20:00:27 +02001719out:
1720 strbuf_release(&name_buf);
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001721 return 0;
1722}
1723
Johannes Schindelin211c8962008-02-29 01:45:45 +00001724int cmd_remote(int argc, const char **argv, const char *prefix)
1725{
1726 struct option options[] = {
Nguyễn Thái Ngọc Duyfbbae142012-08-20 19:32:35 +07001727 OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
Johannes Schindelin211c8962008-02-29 01:45:45 +00001728 OPT_END()
1729 };
1730 int result;
1731
Stephen Boyd37782922009-05-23 11:53:12 -07001732 argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
Johannes Schindelin211c8962008-02-29 01:45:45 +00001733 PARSE_OPT_STOP_AT_NON_OPTION);
1734
1735 if (argc < 1)
1736 result = show_all();
1737 else if (!strcmp(argv[0], "add"))
1738 result = add(argc, argv);
Miklos Vajnabf984212008-11-03 19:26:18 +01001739 else if (!strcmp(argv[0], "rename"))
1740 result = mv(argc, argv);
Nguyễn Thái Ngọc Duye17dba82012-09-06 19:25:23 +07001741 else if (!strcmp(argv[0], "rm") || !strcmp(argv[0], "remove"))
Johannes Schindelin211c8962008-02-29 01:45:45 +00001742 result = rm(argc, argv);
Jay Soffianbc14fac2009-02-25 03:32:25 -05001743 else if (!strcmp(argv[0], "set-head"))
1744 result = set_head(argc, argv);
Jonathan Nieder3d8b6942010-05-19 13:38:50 -05001745 else if (!strcmp(argv[0], "set-branches"))
1746 result = set_branches(argc, argv);
Ben Boeckel96f78d32015-09-15 21:53:47 -04001747 else if (!strcmp(argv[0], "get-url"))
1748 result = get_url(argc, argv);
Ilari Liusvaara433f2be2010-01-18 19:18:02 +02001749 else if (!strcmp(argv[0], "set-url"))
1750 result = set_url(argc, argv);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001751 else if (!strcmp(argv[0], "show"))
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001752 result = show(argc, argv);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001753 else if (!strcmp(argv[0], "prune"))
Olivier Marin67a7e2d2008-06-10 16:51:21 +02001754 result = prune(argc, argv);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001755 else if (!strcmp(argv[0], "update"))
1756 result = update(argc, argv);
1757 else {
Nguyễn Thái Ngọc Duybb16d5d2012-04-23 19:30:26 +07001758 error(_("Unknown subcommand: %s"), argv[0]);
Johannes Schindelin211c8962008-02-29 01:45:45 +00001759 usage_with_options(builtin_remote_usage, options);
1760 }
1761
1762 return result ? 1 : 0;
1763}