@@ -91,8 +91,8 @@ struct checkout_opts {
91
91
};
92
92
93
93
struct branch_info {
94
- const char * name ; /* The short name used */
95
- const char * path ; /* The full name of a real branch */
94
+ char * name ; /* The short name used */
95
+ char * path ; /* The full name of a real branch */
96
96
struct commit * commit ; /* The named commit */
97
97
char * refname ; /* The full name of the ref being checked out. */
98
98
struct object_id oid ; /* The object ID of the commit being checked out. */
@@ -103,6 +103,14 @@ struct branch_info {
103
103
char * checkout ;
104
104
};
105
105
106
+ static void branch_info_release (struct branch_info * info )
107
+ {
108
+ free (info -> name );
109
+ free (info -> path );
110
+ free (info -> refname );
111
+ free (info -> checkout );
112
+ }
113
+
106
114
static int post_checkout_hook (struct commit * old_commit , struct commit * new_commit ,
107
115
int changed )
108
116
{
@@ -688,9 +696,12 @@ static void setup_branch_path(struct branch_info *branch)
688
696
repo_get_oid_committish (the_repository , branch -> name , & branch -> oid );
689
697
690
698
strbuf_branchname (& buf , branch -> name , INTERPRET_BRANCH_LOCAL );
691
- if (strcmp (buf .buf , branch -> name ))
699
+ if (strcmp (buf .buf , branch -> name )) {
700
+ free (branch -> name );
692
701
branch -> name = xstrdup (buf .buf );
702
+ }
693
703
strbuf_splice (& buf , 0 , 0 , "refs/heads/" , 11 );
704
+ free (branch -> path );
694
705
branch -> path = strbuf_detach (& buf , NULL );
695
706
}
696
707
@@ -894,7 +905,9 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
894
905
opts -> new_branch_log ,
895
906
opts -> quiet ,
896
907
opts -> track );
897
- new_branch_info -> name = opts -> new_branch ;
908
+ free (new_branch_info -> name );
909
+ free (new_branch_info -> refname );
910
+ new_branch_info -> name = xstrdup (opts -> new_branch );
898
911
setup_branch_path (new_branch_info );
899
912
}
900
913
@@ -1062,34 +1075,40 @@ static int switch_branches(const struct checkout_opts *opts,
1062
1075
struct branch_info * new_branch_info )
1063
1076
{
1064
1077
int ret = 0 ;
1065
- struct branch_info old_branch_info ;
1066
- void * path_to_free ;
1078
+ struct branch_info old_branch_info = { 0 };
1067
1079
struct object_id rev ;
1068
1080
int flag , writeout_error = 0 ;
1069
1081
int do_merge = 1 ;
1070
1082
1071
1083
trace2_cmd_mode ("branch" );
1072
1084
1073
1085
memset (& old_branch_info , 0 , sizeof (old_branch_info ));
1074
- old_branch_info .path = path_to_free = resolve_refdup ("HEAD" , 0 , & rev , & flag );
1086
+ old_branch_info .path = resolve_refdup ("HEAD" , 0 , & rev , & flag );
1075
1087
if (old_branch_info .path )
1076
1088
old_branch_info .commit = lookup_commit_reference_gently (the_repository , & rev , 1 );
1077
1089
if (!(flag & REF_ISSYMREF ))
1078
- old_branch_info .path = NULL ;
1090
+ FREE_AND_NULL ( old_branch_info .path ) ;
1079
1091
1080
- if (old_branch_info .path )
1081
- skip_prefix (old_branch_info .path , "refs/heads/" , & old_branch_info .name );
1092
+ if (old_branch_info .path ) {
1093
+ const char * const prefix = "refs/heads/" ;
1094
+ const char * p ;
1095
+ if (skip_prefix (old_branch_info .path , prefix , & p ))
1096
+ old_branch_info .name = xstrdup (p );
1097
+ else
1098
+ BUG ("should be able to skip past '%s' in '%s'!" ,
1099
+ prefix , old_branch_info .path );
1100
+ }
1082
1101
1083
1102
if (opts -> new_orphan_branch && opts -> orphan_from_empty_tree ) {
1084
1103
if (new_branch_info -> name )
1085
1104
BUG ("'switch --orphan' should never accept a commit as starting point" );
1086
1105
new_branch_info -> commit = NULL ;
1087
- new_branch_info -> name = "(empty)" ;
1106
+ new_branch_info -> name = xstrdup ( "(empty)" ) ;
1088
1107
do_merge = 1 ;
1089
1108
}
1090
1109
1091
1110
if (!new_branch_info -> name ) {
1092
- new_branch_info -> name = "HEAD" ;
1111
+ new_branch_info -> name = xstrdup ( "HEAD" ) ;
1093
1112
new_branch_info -> commit = old_branch_info .commit ;
1094
1113
if (!new_branch_info -> commit )
1095
1114
die (_ ("You are on a branch yet to be born" ));
@@ -1102,7 +1121,7 @@ static int switch_branches(const struct checkout_opts *opts,
1102
1121
if (do_merge ) {
1103
1122
ret = merge_working_tree (opts , & old_branch_info , new_branch_info , & writeout_error );
1104
1123
if (ret ) {
1105
- free ( path_to_free );
1124
+ branch_info_release ( & old_branch_info );
1106
1125
return ret ;
1107
1126
}
1108
1127
}
@@ -1113,7 +1132,8 @@ static int switch_branches(const struct checkout_opts *opts,
1113
1132
update_refs_for_switch (opts , & old_branch_info , new_branch_info );
1114
1133
1115
1134
ret = post_checkout_hook (old_branch_info .commit , new_branch_info -> commit , 1 );
1116
- free (path_to_free );
1135
+ branch_info_release (& old_branch_info );
1136
+
1117
1137
return ret || writeout_error ;
1118
1138
}
1119
1139
@@ -1145,16 +1165,15 @@ static void setup_new_branch_info_and_source_tree(
1145
1165
struct tree * * source_tree = & opts -> source_tree ;
1146
1166
struct object_id branch_rev ;
1147
1167
1148
- new_branch_info -> name = arg ;
1168
+ new_branch_info -> name = xstrdup ( arg ) ;
1149
1169
setup_branch_path (new_branch_info );
1150
1170
1151
1171
if (!check_refname_format (new_branch_info -> path , 0 ) &&
1152
1172
!read_ref (new_branch_info -> path , & branch_rev ))
1153
1173
oidcpy (rev , & branch_rev );
1154
- else {
1155
- free ((char * )new_branch_info -> path );
1156
- new_branch_info -> path = NULL ; /* not an existing branch */
1157
- }
1174
+ else
1175
+ /* not an existing branch */
1176
+ FREE_AND_NULL (new_branch_info -> path );
1158
1177
1159
1178
new_branch_info -> commit = lookup_commit_reference_gently (the_repository , rev , 1 );
1160
1179
if (!new_branch_info -> commit ) {
@@ -1574,12 +1593,11 @@ static char cb_option = 'b';
1574
1593
1575
1594
static int checkout_main (int argc , const char * * argv , const char * prefix ,
1576
1595
struct checkout_opts * opts , struct option * options ,
1577
- const char * const usagestr [])
1596
+ const char * const usagestr [],
1597
+ struct branch_info * new_branch_info )
1578
1598
{
1579
- struct branch_info new_branch_info ;
1580
1599
int parseopt_flags = 0 ;
1581
1600
1582
- memset (& new_branch_info , 0 , sizeof (new_branch_info ));
1583
1601
opts -> overwrite_ignore = 1 ;
1584
1602
opts -> prefix = prefix ;
1585
1603
opts -> show_progress = -1 ;
@@ -1688,7 +1706,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1688
1706
opts -> track == BRANCH_TRACK_UNSPECIFIED &&
1689
1707
!opts -> new_branch ;
1690
1708
int n = parse_branchname_arg (argc , argv , dwim_ok ,
1691
- & new_branch_info , opts , & rev );
1709
+ new_branch_info , opts , & rev );
1692
1710
argv += n ;
1693
1711
argc -= n ;
1694
1712
} else if (!opts -> accept_ref && opts -> from_treeish ) {
@@ -1697,7 +1715,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1697
1715
if (get_oid_mb (opts -> from_treeish , & rev ))
1698
1716
die (_ ("could not resolve %s" ), opts -> from_treeish );
1699
1717
1700
- setup_new_branch_info_and_source_tree (& new_branch_info ,
1718
+ setup_new_branch_info_and_source_tree (new_branch_info ,
1701
1719
opts , & rev ,
1702
1720
opts -> from_treeish );
1703
1721
@@ -1717,7 +1735,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1717
1735
* Try to give more helpful suggestion.
1718
1736
* new_branch && argc > 1 will be caught later.
1719
1737
*/
1720
- if (opts -> new_branch && argc == 1 && !new_branch_info . commit )
1738
+ if (opts -> new_branch && argc == 1 && !new_branch_info -> commit )
1721
1739
die (_ ("'%s' is not a commit and a branch '%s' cannot be created from it" ),
1722
1740
argv [0 ], opts -> new_branch );
1723
1741
@@ -1766,11 +1784,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
1766
1784
strbuf_release (& buf );
1767
1785
}
1768
1786
1769
- UNLEAK (opts );
1770
1787
if (opts -> patch_mode || opts -> pathspec .nr )
1771
- return checkout_paths (opts , & new_branch_info );
1788
+ return checkout_paths (opts , new_branch_info );
1772
1789
else
1773
- return checkout_branch (opts , & new_branch_info );
1790
+ return checkout_branch (opts , new_branch_info );
1774
1791
}
1775
1792
1776
1793
int cmd_checkout (int argc , const char * * argv , const char * prefix )
@@ -1789,6 +1806,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1789
1806
OPT_END ()
1790
1807
};
1791
1808
int ret ;
1809
+ struct branch_info new_branch_info = { 0 };
1792
1810
1793
1811
memset (& opts , 0 , sizeof (opts ));
1794
1812
opts .dwim_new_local_branch = 1 ;
@@ -1819,7 +1837,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
1819
1837
options = add_checkout_path_options (& opts , options );
1820
1838
1821
1839
ret = checkout_main (argc , argv , prefix , & opts ,
1822
- options , checkout_usage );
1840
+ options , checkout_usage , & new_branch_info );
1841
+ branch_info_release (& new_branch_info );
1842
+ clear_pathspec (& opts .pathspec );
1823
1843
FREE_AND_NULL (options );
1824
1844
return ret ;
1825
1845
}
@@ -1840,6 +1860,7 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
1840
1860
OPT_END ()
1841
1861
};
1842
1862
int ret ;
1863
+ struct branch_info new_branch_info = { 0 };
1843
1864
1844
1865
memset (& opts , 0 , sizeof (opts ));
1845
1866
opts .dwim_new_local_branch = 1 ;
@@ -1859,7 +1880,8 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
1859
1880
cb_option = 'c' ;
1860
1881
1861
1882
ret = checkout_main (argc , argv , prefix , & opts ,
1862
- options , switch_branch_usage );
1883
+ options , switch_branch_usage , & new_branch_info );
1884
+ branch_info_release (& new_branch_info );
1863
1885
FREE_AND_NULL (options );
1864
1886
return ret ;
1865
1887
}
@@ -1881,6 +1903,7 @@ int cmd_restore(int argc, const char **argv, const char *prefix)
1881
1903
OPT_END ()
1882
1904
};
1883
1905
int ret ;
1906
+ struct branch_info new_branch_info = { 0 };
1884
1907
1885
1908
memset (& opts , 0 , sizeof (opts ));
1886
1909
opts .accept_ref = 0 ;
@@ -1896,7 +1919,8 @@ int cmd_restore(int argc, const char **argv, const char *prefix)
1896
1919
options = add_checkout_path_options (& opts , options );
1897
1920
1898
1921
ret = checkout_main (argc , argv , prefix , & opts ,
1899
- options , restore_usage );
1922
+ options , restore_usage , & new_branch_info );
1923
+ branch_info_release (& new_branch_info );
1900
1924
FREE_AND_NULL (options );
1901
1925
return ret ;
1902
1926
}
0 commit comments