@@ -1359,32 +1359,61 @@ static int update_branch_remote_config_entry(
1359
1359
}
1360
1360
1361
1361
static int rename_one_remote_reference (
1362
- git_reference * reference ,
1362
+ git_reference * reference_in ,
1363
1363
const char * old_remote_name ,
1364
1364
const char * new_remote_name )
1365
1365
{
1366
1366
int error ;
1367
+ git_reference * ref = NULL , * dummy = NULL ;
1368
+ git_buf namespace = GIT_BUF_INIT , old_namespace = GIT_BUF_INIT ;
1367
1369
git_buf new_name = GIT_BUF_INIT ;
1368
1370
git_buf log_message = GIT_BUF_INIT ;
1371
+ size_t pfx_len ;
1372
+ const char * target ;
1369
1373
1370
- if ((error = git_buf_printf (
1371
- & new_name ,
1372
- GIT_REFS_REMOTES_DIR "%s%s" ,
1373
- new_remote_name ,
1374
- reference -> name + strlen (GIT_REFS_REMOTES_DIR ) + strlen (old_remote_name ))) < 0 )
1374
+ if ((error = git_buf_printf (& namespace , GIT_REFS_REMOTES_DIR "%s/" , new_remote_name )) < 0 )
1375
+ return error ;
1376
+
1377
+ pfx_len = strlen (GIT_REFS_REMOTES_DIR ) + strlen (old_remote_name ) + 1 ;
1378
+ git_buf_puts (& new_name , namespace .ptr );
1379
+ if ((error = git_buf_puts (& new_name , git_reference_name (reference_in ) + pfx_len )) < 0 )
1375
1380
goto cleanup ;
1376
1381
1377
1382
if ((error = git_buf_printf (& log_message ,
1378
1383
"renamed remote %s to %s" ,
1379
1384
old_remote_name , new_remote_name )) < 0 )
1380
1385
goto cleanup ;
1381
1386
1382
- error = git_reference_rename (
1383
- NULL , reference , git_buf_cstr (& new_name ), 1 ,
1384
- NULL , git_buf_cstr (& log_message ));
1385
- git_reference_free (reference );
1387
+ if ((error = git_reference_rename (& ref , reference_in , git_buf_cstr (& new_name ), 1 ,
1388
+ NULL , git_buf_cstr (& log_message ))) < 0 )
1389
+ goto cleanup ;
1390
+
1391
+ if (git_reference_type (ref ) != GIT_REF_SYMBOLIC )
1392
+ goto cleanup ;
1393
+
1394
+ /* Handle refs like origin/HEAD -> origin/master */
1395
+ target = git_reference_symbolic_target (ref );
1396
+ if ((error = git_buf_printf (& old_namespace , GIT_REFS_REMOTES_DIR "%s/" , old_remote_name )) < 0 )
1397
+ goto cleanup ;
1398
+
1399
+ if (git__prefixcmp (target , old_namespace .ptr ))
1400
+ goto cleanup ;
1401
+
1402
+ git_buf_clear (& new_name );
1403
+ git_buf_puts (& new_name , namespace .ptr );
1404
+ if ((error = git_buf_puts (& new_name , target + pfx_len )) < 0 )
1405
+ goto cleanup ;
1406
+
1407
+ error = git_reference_symbolic_set_target (& dummy , ref , git_buf_cstr (& new_name ),
1408
+ NULL , git_buf_cstr (& log_message ));
1409
+
1410
+ git_reference_free (dummy );
1386
1411
1387
1412
cleanup :
1413
+ git_reference_free (reference_in );
1414
+ git_reference_free (ref );
1415
+ git_buf_free (& namespace );
1416
+ git_buf_free (& old_namespace );
1388
1417
git_buf_free (& new_name );
1389
1418
git_buf_free (& log_message );
1390
1419
return error ;
@@ -1419,11 +1448,7 @@ static int rename_remote_references(
1419
1448
return (error == GIT_ITEROVER ) ? 0 : error ;
1420
1449
}
1421
1450
1422
- static int rename_fetch_refspecs (
1423
- git_remote * remote ,
1424
- const char * new_name ,
1425
- int (* callback )(const char * problematic_refspec , void * payload ),
1426
- void * payload )
1451
+ static int rename_fetch_refspecs (git_vector * problems , git_remote * remote , const char * new_name )
1427
1452
{
1428
1453
git_config * config ;
1429
1454
git_buf base = GIT_BUF_INIT , var = GIT_BUF_INIT , val = GIT_BUF_INIT ;
@@ -1434,6 +1459,9 @@ static int rename_fetch_refspecs(
1434
1459
if ((error = git_repository_config__weakptr (& config , remote -> repo )) < 0 )
1435
1460
return error ;
1436
1461
1462
+ if ((error = git_vector_init (problems , 1 , NULL )) < 0 )
1463
+ return error ;
1464
+
1437
1465
if ((error = git_buf_printf (
1438
1466
& base , "+refs/heads/*:refs/remotes/%s/*" , remote -> name )) < 0 )
1439
1467
return error ;
@@ -1442,15 +1470,15 @@ static int rename_fetch_refspecs(
1442
1470
if (spec -> push )
1443
1471
continue ;
1444
1472
1445
- /* Every refspec is a problem refspec for an anonymous remote, OR */
1446
1473
/* Does the dst part of the refspec follow the expected format? */
1447
- if (! remote -> name ||
1448
- strcmp ( git_buf_cstr ( & base ), spec -> string )) {
1474
+ if (strcmp ( git_buf_cstr ( & base ), spec -> string )) {
1475
+ char * dup ;
1449
1476
1450
- if ((error = callback (spec -> string , payload )) != 0 ) {
1451
- giterr_set_after_callback (error );
1477
+ dup = git__strdup (spec -> string );
1478
+ GITERR_CHECK_ALLOC (dup );
1479
+
1480
+ if ((error = git_vector_insert (problems , dup )) < 0 )
1452
1481
break ;
1453
- }
1454
1482
1455
1483
continue ;
1456
1484
}
@@ -1476,18 +1504,25 @@ static int rename_fetch_refspecs(
1476
1504
git_buf_free (& base );
1477
1505
git_buf_free (& var );
1478
1506
git_buf_free (& val );
1507
+
1508
+ if (error < 0 ) {
1509
+ char * str ;
1510
+ git_vector_foreach (problems , i , str )
1511
+ git__free (str );
1512
+
1513
+ git_vector_free (problems );
1514
+ }
1515
+
1479
1516
return error ;
1480
1517
}
1481
1518
1482
- int git_remote_rename (
1483
- git_remote * remote ,
1484
- const char * new_name ,
1485
- git_remote_rename_problem_cb callback ,
1486
- void * payload )
1519
+ int git_remote_rename (git_strarray * out , git_remote * remote , const char * new_name )
1487
1520
{
1488
1521
int error ;
1522
+ git_vector problem_refspecs ;
1523
+ char * tmp , * dup ;
1489
1524
1490
- assert (remote && new_name );
1525
+ assert (out && remote && new_name );
1491
1526
1492
1527
if (!remote -> name ) {
1493
1528
giterr_set (GITERR_INVALID , "Can't rename an anonymous remote." );
@@ -1497,54 +1532,30 @@ int git_remote_rename(
1497
1532
if ((error = ensure_remote_name_is_valid (new_name )) < 0 )
1498
1533
return error ;
1499
1534
1500
- if (remote -> repo ) {
1501
- if ((error = ensure_remote_doesnot_exist (remote -> repo , new_name )) < 0 )
1502
- return error ;
1535
+ if ((error = ensure_remote_doesnot_exist (remote -> repo , new_name )) < 0 )
1536
+ return error ;
1537
+
1538
+ if ((error = rename_remote_config_section (remote -> repo , remote -> name , new_name )) < 0 )
1539
+ return error ;
1503
1540
1504
- if (!remote -> name ) {
1505
- if ((error = rename_fetch_refspecs (
1506
- remote ,
1507
- new_name ,
1508
- callback ,
1509
- payload )) < 0 )
1510
- return error ;
1541
+ if ((error = update_branch_remote_config_entry (remote -> repo , remote -> name , new_name )) < 0 )
1542
+ return error ;
1511
1543
1512
- remote -> name = git__strdup ( new_name );
1513
- GITERR_CHECK_ALLOC ( remote -> name ) ;
1544
+ if (( error = rename_remote_references ( remote -> repo , remote -> name , new_name )) < 0 )
1545
+ return error ;
1514
1546
1515
- return git_remote_save ( remote );
1516
- }
1547
+ if (( error = rename_fetch_refspecs ( & problem_refspecs , remote , new_name )) < 0 )
1548
+ return error ;
1517
1549
1518
- if ((error = rename_remote_config_section (
1519
- remote -> repo ,
1520
- remote -> name ,
1521
- new_name )) < 0 )
1522
- return error ;
1523
-
1524
- if ((error = update_branch_remote_config_entry (
1525
- remote -> repo ,
1526
- remote -> name ,
1527
- new_name )) < 0 )
1528
- return error ;
1529
-
1530
- if ((error = rename_remote_references (
1531
- remote -> repo ,
1532
- remote -> name ,
1533
- new_name )) < 0 )
1534
- return error ;
1535
-
1536
- if ((error = rename_fetch_refspecs (
1537
- remote ,
1538
- new_name ,
1539
- callback ,
1540
- payload )) < 0 )
1541
- return error ;
1542
- }
1550
+ out -> count = problem_refspecs .length ;
1551
+ out -> strings = (char * * ) problem_refspecs .contents ;
1543
1552
1544
- git__free (remote -> name );
1553
+ dup = git__strdup (new_name );
1554
+ GITERR_CHECK_ALLOC (dup );
1545
1555
1546
- remote -> name = git__strdup (new_name );
1547
- GITERR_CHECK_ALLOC (remote -> name );
1556
+ tmp = remote -> name ;
1557
+ remote -> name = dup ;
1558
+ git__free (tmp );
1548
1559
1549
1560
return 0 ;
1550
1561
}
@@ -1910,8 +1921,6 @@ int git_remote_delete(git_remote *remote)
1910
1921
repo , git_remote_name (remote ), NULL )) < 0 )
1911
1922
return error ;
1912
1923
1913
- git_remote_free (remote );
1914
-
1915
1924
return 0 ;
1916
1925
}
1917
1926
0 commit comments