Add git remote set-url
Add 'git remote set-url' for changing URL of remote repository with one "porcelain-level" command. Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Ilari Liusvaara committed
Jan 18, 2010 at 19:18 UTC
433f2be139710e2fc7c0693a8411b2773f1a4b38
3 files changed
+330
-1
Documentation/git-remote.txt
+17
@@ -14,6 +14,9 @@ SYNOPSIS
14
'git remote rename' <old> <new>
15
'git remote rm' <name>
16
'git remote set-head' <name> (-a | -d | <branch>)
17
+'git remote set-url' [--push] <name> <newurl> [<oldurl>]
18
+'git remote set-url --add' [--push] <name> <newurl>
19
+'git remote set-url --delete' [--push] <name> <url>
20
'git remote' [-v | --verbose] 'show' [-n] <name>
21
'git remote prune' [-n | --dry-run] <name>
22
'git remote' [-v | --verbose] 'update' [-p | --prune] [group | remote]...
@@ -101,6 +104,20 @@ remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
104
`refs/remotes/origin/master` already exists; if not it must be fetched first.
105
+
106
107
+'set-url'::
108
+
109
+Changes URL remote points to. Sets first URL remote points to matching
110
+regex <oldurl> (first URL if no <oldurl> is given) to <newurl>. If
111
+<oldurl> doesn't match any URL, error occurs and nothing is changed.
112
++
113
+With '--push', push URLs are manipulated instead of fetch URLs.
114
++
115
+With '--add', instead of changing some URL, new URL is added.
116
++
117
+With '--delete', instead of changing some URL, all URLs matching
118
+regex <url> are deleted. Trying to delete all non-push URLs is an
119
+error.
120
+
121
'show'::
122
123
Gives some information about the remote <name>.
builtin-remote.c
+98
@@ -16,6 +16,9 @@ static const char * const builtin_remote_usage[] = {
16
"git remote [-v | --verbose] show [-n] <name>",
17
"git remote prune [-n | --dry-run] <name>",
18
"git remote [-v | --verbose] update [-p | --prune] [group | remote]",
19
+ "git remote set-url <name> <newurl> [<oldurl>]",
20
+ "git remote set-url --add <name> <newurl>",
21
+ "git remote set-url --delete <name> <url>",
22
NULL
23
};
24
@@ -54,6 +57,13 @@ static const char * const builtin_remote_update_usage[] = {
57
NULL
58
};
59
60
+static const char * const builtin_remote_seturl_usage[] = {
61
+ "git remote set-url [--push] <name> <newurl> [<oldurl>]",
62
+ "git remote set-url --add <name> <newurl>",
63
+ "git remote set-url --delete <name> <url>",
64
+ NULL
65
+};
66
+
67
#define GET_REF_STATES (1<<0)
68
#define GET_HEAD_NAMES (1<<1)
69
#define GET_PUSH_REF_STATES (1<<2)
@@ -1255,6 +1265,92 @@ static int update(int argc, const char **argv)
1265
return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
1266
}
1267
1268
+static int set_url(int argc, const char **argv)
1269
+{
1270
+ int i, push_mode = 0, add_mode = 0, delete_mode = 0;
1271
+ int matches = 0, negative_matches = 0;
1272
+ const char *remotename = NULL;
1273
+ const char *newurl = NULL;
1274
+ const char *oldurl = NULL;
1275
+ struct remote *remote;
1276
+ regex_t old_regex;
1277
+ const char **urlset;
1278
+ int urlset_nr;
1279
+ struct strbuf name_buf = STRBUF_INIT;
1280
+ struct option options[] = {
1281
+ OPT_BOOLEAN('\0', "push", &push_mode,
1282
+ "manipulate push URLs"),
1283
+ OPT_BOOLEAN('\0', "add", &add_mode,
1284
+ "add URL"),
1285
+ OPT_BOOLEAN('\0', "delete", &delete_mode,
1286
+ "delete URLs"),
1287
+ OPT_END()
1288
+ };
1289
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
1290
+ PARSE_OPT_KEEP_ARGV0);
1291
+
1292
+ if (add_mode && delete_mode)
1293
+ die("--add --delete doesn't make sense");
1294
+
1295
+ if (argc < 3 || argc > 4 || ((add_mode || delete_mode) && argc != 3))
1296
+ usage_with_options(builtin_remote_seturl_usage, options);
1297
+
1298
+ remotename = argv[1];
1299
+ newurl = argv[2];
1300
+ if (argc > 3)
1301
+ oldurl = argv[3];
1302
+
1303
+ if (delete_mode)
1304
+ oldurl = newurl;
1305
+
1306
+ if (!remote_is_configured(remotename))
1307
+ die("No such remote '%s'", remotename);
1308
+ remote = remote_get(remotename);
1309
+
1310
+ if (push_mode) {
1311
+ strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
1312
+ urlset = remote->pushurl;
1313
+ urlset_nr = remote->pushurl_nr;
1314
+ } else {
1315
+ strbuf_addf(&name_buf, "remote.%s.url", remotename);
1316
+ urlset = remote->url;
1317
+ urlset_nr = remote->url_nr;
1318
+ }
1319
+
1320
+ /* Special cases that add new entry. */
1321
+ if ((!oldurl && !delete_mode) || add_mode) {
1322
+ if (add_mode)
1323
+ git_config_set_multivar(name_buf.buf, newurl,
1324
+ "^$", 0);
1325
+ else
1326
+ git_config_set(name_buf.buf, newurl);
1327
+ strbuf_release(&name_buf);
1328
+ return 0;
1329
+ }
1330
+
1331
+ /* Old URL specified. Demand that one matches. */
1332
+ if (regcomp(&old_regex, oldurl, REG_EXTENDED))
1333
+ die("Invalid old URL pattern: %s", oldurl);
1334
+
1335
+ for (i = 0; i < urlset_nr; i++)
1336
+ if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
1337
+ matches++;
1338
+ else
1339
+ negative_matches++;
1340
+ if (!delete_mode && !matches)
1341
+ die("No such URL found: %s", oldurl);
1342
+ if (delete_mode && !negative_matches && !push_mode)
1343
+ die("Will not delete all non-push URLs");
1344
+
1345
+ regfree(&old_regex);
1346
+
1347
+ if (!delete_mode)
1348
+ git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
1349
+ else
1350
+ git_config_set_multivar(name_buf.buf, NULL, oldurl, 1);
1351
+ return 0;
1352
+}
1353
+
1354
static int get_one_entry(struct remote *remote, void *priv)
1355
{
1356
struct string_list *list = priv;
@@ -1334,6 +1430,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
1430
result = rm(argc, argv);
1431
else if (!strcmp(argv[0], "set-head"))
1432
result = set_head(argc, argv);
1433
+ else if (!strcmp(argv[0], "set-url"))
1434
+ result = set_url(argc, argv);
1435
else if (!strcmp(argv[0], "show"))
1436
result = show(argc, argv);
1437
else if (!strcmp(argv[0], "prune"))
t/t5505-remote.sh
+215
-1
@@ -533,5 +533,219 @@ test_expect_success 'show empty remote' '
533
)
534
'
535
536
-test_done
536
+test_expect_success 'new remote' '
537
+(
538
+ git remote add someremote foo &&
539
+ echo foo >expect &&
540
+ git config --get-all remote.someremote.url >actual &&
541
+ cmp expect actual
542
+)
543
+'
544
+
545
+test_expect_success 'remote set-url bar' '
546
+(
547
+ git remote set-url someremote bar &&
548
+ echo bar >expect &&
549
+ git config --get-all remote.someremote.url >actual &&
550
+ cmp expect actual
551
+)
552
+'
553
554
+test_expect_success 'remote set-url baz bar' '
555
+(
556
+ git remote set-url someremote baz bar &&
557
+ echo baz >expect &&
558
+ git config --get-all remote.someremote.url >actual &&
559
+ cmp expect actual
560
+)
561
+'
562
+
563
+test_expect_success 'remote set-url zot bar' '
564
+(
565
+ test_must_fail git remote set-url someremote zot bar &&
566
+ echo baz >expect &&
567
+ git config --get-all remote.someremote.url >actual &&
568
+ cmp expect actual
569
+)
570
+'
571
+
572
+test_expect_success 'remote set-url --push zot baz' '
573
+(
574
+ test_must_fail git remote set-url --push someremote zot baz &&
575
+ echo "YYY" >expect &&
576
+ echo baz >>expect &&
577
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
578
+ echo "YYY" >>actual &&
579
+ git config --get-all remote.someremote.url >>actual &&
580
+ cmp expect actual
581
+)
582
+'
583
+
584
+test_expect_success 'remote set-url --push zot' '
585
+(
586
+ git remote set-url --push someremote zot &&
587
+ echo zot >expect &&
588
+ echo "YYY" >>expect &&
589
+ echo baz >>expect &&
590
+ git config --get-all remote.someremote.pushurl >actual &&
591
+ echo "YYY" >>actual &&
592
+ git config --get-all remote.someremote.url >>actual &&
593
+ cmp expect actual
594
+)
595
+'
596
+
597
+test_expect_success 'remote set-url --push qux zot' '
598
+(
599
+ git remote set-url --push someremote qux zot &&
600
+ echo qux >expect &&
601
+ echo "YYY" >>expect &&
602
+ echo baz >>expect &&
603
+ git config --get-all remote.someremote.pushurl >actual &&
604
+ echo "YYY" >>actual &&
605
+ git config --get-all remote.someremote.url >>actual &&
606
+ cmp expect actual
607
+)
608
+'
609
+
610
+test_expect_success 'remote set-url --push foo qu+x' '
611
+(
612
+ git remote set-url --push someremote foo qu+x &&
613
+ echo foo >expect &&
614
+ echo "YYY" >>expect &&
615
+ echo baz >>expect &&
616
+ git config --get-all remote.someremote.pushurl >actual &&
617
+ echo "YYY" >>actual &&
618
+ git config --get-all remote.someremote.url >>actual &&
619
+ cmp expect actual
620
+)
621
+'
622
+
623
+test_expect_success 'remote set-url --push --add aaa' '
624
+(
625
+ git remote set-url --push --add someremote aaa &&
626
+ echo foo >expect &&
627
+ echo aaa >>expect &&
628
+ echo "YYY" >>expect &&
629
+ echo baz >>expect &&
630
+ git config --get-all remote.someremote.pushurl >actual &&
631
+ echo "YYY" >>actual &&
632
+ git config --get-all remote.someremote.url >>actual &&
633
+ cmp expect actual
634
+)
635
+'
636
+
637
+test_expect_success 'remote set-url --push bar aaa' '
638
+(
639
+ git remote set-url --push someremote bar aaa &&
640
+ echo foo >expect &&
641
+ echo bar >>expect &&
642
+ echo "YYY" >>expect &&
643
+ echo baz >>expect &&
644
+ git config --get-all remote.someremote.pushurl >actual &&
645
+ echo "YYY" >>actual &&
646
+ git config --get-all remote.someremote.url >>actual &&
647
+ cmp expect actual
648
+)
649
+'
650
+
651
+test_expect_success 'remote set-url --push --delete bar' '
652
+(
653
+ git remote set-url --push --delete someremote bar &&
654
+ echo foo >expect &&
655
+ echo "YYY" >>expect &&
656
+ echo baz >>expect &&
657
+ git config --get-all remote.someremote.pushurl >actual &&
658
+ echo "YYY" >>actual &&
659
+ git config --get-all remote.someremote.url >>actual &&
660
+ cmp expect actual
661
+)
662
+'
663
+
664
+test_expect_success 'remote set-url --push --delete foo' '
665
+(
666
+ git remote set-url --push --delete someremote foo &&
667
+ echo "YYY" >expect &&
668
+ echo baz >>expect &&
669
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
670
+ echo "YYY" >>actual &&
671
+ git config --get-all remote.someremote.url >>actual &&
672
+ cmp expect actual
673
+)
674
+'
675
+
676
+test_expect_success 'remote set-url --add bbb' '
677
+(
678
+ git remote set-url --add someremote bbb &&
679
+ echo "YYY" >expect &&
680
+ echo baz >>expect &&
681
+ echo bbb >>expect &&
682
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
683
+ echo "YYY" >>actual &&
684
+ git config --get-all remote.someremote.url >>actual &&
685
+ cmp expect actual
686
+)
687
+'
688
+
689
+test_expect_success 'remote set-url --delete .*' '
690
+(
691
+ test_must_fail git remote set-url --delete someremote .* &&
692
+ echo "YYY" >expect &&
693
+ echo baz >>expect &&
694
+ echo bbb >>expect &&
695
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
696
+ echo "YYY" >>actual &&
697
+ git config --get-all remote.someremote.url >>actual &&
698
+ cmp expect actual
699
+)
700
+'
701
+
702
+test_expect_success 'remote set-url --delete bbb' '
703
+(
704
+ git remote set-url --delete someremote bbb &&
705
+ echo "YYY" >expect &&
706
+ echo baz >>expect &&
707
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
708
+ echo "YYY" >>actual &&
709
+ git config --get-all remote.someremote.url >>actual &&
710
+ cmp expect actual
711
+)
712
+'
713
+
714
+test_expect_success 'remote set-url --delete baz' '
715
+(
716
+ test_must_fail git remote set-url --delete someremote baz &&
717
+ echo "YYY" >expect &&
718
+ echo baz >>expect &&
719
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
720
+ echo "YYY" >>actual &&
721
+ git config --get-all remote.someremote.url >>actual &&
722
+ cmp expect actual
723
+)
724
+'
725
+
726
+test_expect_success 'remote set-url --add ccc' '
727
+(
728
+ git remote set-url --add someremote ccc &&
729
+ echo "YYY" >expect &&
730
+ echo baz >>expect &&
731
+ echo ccc >>expect &&
732
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
733
+ echo "YYY" >>actual &&
734
+ git config --get-all remote.someremote.url >>actual &&
735
+ cmp expect actual
736
+)
737
+'
738
+
739
+test_expect_success 'remote set-url --delete baz' '
740
+(
741
+ git remote set-url --delete someremote baz &&
742
+ echo "YYY" >expect &&
743
+ echo ccc >>expect &&
744
+ test_must_fail git config --get-all remote.someremote.pushurl >actual &&
745
+ echo "YYY" >>actual &&
746
+ git config --get-all remote.someremote.url >>actual &&
747
+ cmp expect actual
748
+)
749
+'
750
+
751
+test_done