@@ -91,8 +91,8 @@ struct checkout_opts {
9191};
9292
9393struct 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 */
9696 struct commit * commit ; /* The named commit */
9797 char * refname ; /* The full name of the ref being checked out. */
9898 struct object_id oid ; /* The object ID of the commit being checked out. */
@@ -103,6 +103,14 @@ struct branch_info {
103103 char * checkout ;
104104};
105105
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+
106114static int post_checkout_hook (struct commit * old_commit , struct commit * new_commit ,
107115 int changed )
108116{
@@ -688,9 +696,12 @@ static void setup_branch_path(struct branch_info *branch)
688696 repo_get_oid_committish (the_repository , branch -> name , & branch -> oid );
689697
690698 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 );
692701 branch -> name = xstrdup (buf .buf );
702+ }
693703 strbuf_splice (& buf , 0 , 0 , "refs/heads/" , 11 );
704+ free (branch -> path );
694705 branch -> path = strbuf_detach (& buf , NULL );
695706}
696707
@@ -894,7 +905,9 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
894905 opts -> new_branch_log ,
895906 opts -> quiet ,
896907 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 );
898911 setup_branch_path (new_branch_info );
899912 }
900913
@@ -1062,34 +1075,40 @@ static int switch_branches(const struct checkout_opts *opts,
10621075 struct branch_info * new_branch_info )
10631076{
10641077 int ret = 0 ;
1065- struct branch_info old_branch_info ;
1066- void * path_to_free ;
1078+ struct branch_info old_branch_info = { 0 };
10671079 struct object_id rev ;
10681080 int flag , writeout_error = 0 ;
10691081 int do_merge = 1 ;
10701082
10711083 trace2_cmd_mode ("branch" );
10721084
10731085 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 );
10751087 if (old_branch_info .path )
10761088 old_branch_info .commit = lookup_commit_reference_gently (the_repository , & rev , 1 );
10771089 if (!(flag & REF_ISSYMREF ))
1078- old_branch_info .path = NULL ;
1090+ FREE_AND_NULL ( old_branch_info .path ) ;
10791091
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+ }
10821101
10831102 if (opts -> new_orphan_branch && opts -> orphan_from_empty_tree ) {
10841103 if (new_branch_info -> name )
10851104 BUG ("'switch --orphan' should never accept a commit as starting point" );
10861105 new_branch_info -> commit = NULL ;
1087- new_branch_info -> name = "(empty)" ;
1106+ new_branch_info -> name = xstrdup ( "(empty)" ) ;
10881107 do_merge = 1 ;
10891108 }
10901109
10911110 if (!new_branch_info -> name ) {
1092- new_branch_info -> name = "HEAD" ;
1111+ new_branch_info -> name = xstrdup ( "HEAD" ) ;
10931112 new_branch_info -> commit = old_branch_info .commit ;
10941113 if (!new_branch_info -> commit )
10951114 die (_ ("You are on a branch yet to be born" ));
@@ -1102,7 +1121,7 @@ static int switch_branches(const struct checkout_opts *opts,
11021121 if (do_merge ) {
11031122 ret = merge_working_tree (opts , & old_branch_info , new_branch_info , & writeout_error );
11041123 if (ret ) {
1105- free ( path_to_free );
1124+ branch_info_release ( & old_branch_info );
11061125 return ret ;
11071126 }
11081127 }
@@ -1113,7 +1132,8 @@ static int switch_branches(const struct checkout_opts *opts,
11131132 update_refs_for_switch (opts , & old_branch_info , new_branch_info );
11141133
11151134 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+
11171137 return ret || writeout_error ;
11181138}
11191139
@@ -1145,16 +1165,15 @@ static void setup_new_branch_info_and_source_tree(
11451165 struct tree * * source_tree = & opts -> source_tree ;
11461166 struct object_id branch_rev ;
11471167
1148- new_branch_info -> name = arg ;
1168+ new_branch_info -> name = xstrdup ( arg ) ;
11491169 setup_branch_path (new_branch_info );
11501170
11511171 if (!check_refname_format (new_branch_info -> path , 0 ) &&
11521172 !read_ref (new_branch_info -> path , & branch_rev ))
11531173 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 );
11581177
11591178 new_branch_info -> commit = lookup_commit_reference_gently (the_repository , rev , 1 );
11601179 if (!new_branch_info -> commit ) {
@@ -1574,12 +1593,11 @@ static char cb_option = 'b';
15741593
15751594static int checkout_main (int argc , const char * * argv , const char * prefix ,
15761595 struct checkout_opts * opts , struct option * options ,
1577- const char * const usagestr [])
1596+ const char * const usagestr [],
1597+ struct branch_info * new_branch_info )
15781598{
1579- struct branch_info new_branch_info ;
15801599 int parseopt_flags = 0 ;
15811600
1582- memset (& new_branch_info , 0 , sizeof (new_branch_info ));
15831601 opts -> overwrite_ignore = 1 ;
15841602 opts -> prefix = prefix ;
15851603 opts -> show_progress = -1 ;
@@ -1688,7 +1706,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
16881706 opts -> track == BRANCH_TRACK_UNSPECIFIED &&
16891707 !opts -> new_branch ;
16901708 int n = parse_branchname_arg (argc , argv , dwim_ok ,
1691- & new_branch_info , opts , & rev );
1709+ new_branch_info , opts , & rev );
16921710 argv += n ;
16931711 argc -= n ;
16941712 } else if (!opts -> accept_ref && opts -> from_treeish ) {
@@ -1697,7 +1715,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
16971715 if (get_oid_mb (opts -> from_treeish , & rev ))
16981716 die (_ ("could not resolve %s" ), opts -> from_treeish );
16991717
1700- setup_new_branch_info_and_source_tree (& new_branch_info ,
1718+ setup_new_branch_info_and_source_tree (new_branch_info ,
17011719 opts , & rev ,
17021720 opts -> from_treeish );
17031721
@@ -1717,7 +1735,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
17171735 * Try to give more helpful suggestion.
17181736 * new_branch && argc > 1 will be caught later.
17191737 */
1720- if (opts -> new_branch && argc == 1 && !new_branch_info . commit )
1738+ if (opts -> new_branch && argc == 1 && !new_branch_info -> commit )
17211739 die (_ ("'%s' is not a commit and a branch '%s' cannot be created from it" ),
17221740 argv [0 ], opts -> new_branch );
17231741
@@ -1766,11 +1784,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
17661784 strbuf_release (& buf );
17671785 }
17681786
1769- UNLEAK (opts );
17701787 if (opts -> patch_mode || opts -> pathspec .nr )
1771- return checkout_paths (opts , & new_branch_info );
1788+ return checkout_paths (opts , new_branch_info );
17721789 else
1773- return checkout_branch (opts , & new_branch_info );
1790+ return checkout_branch (opts , new_branch_info );
17741791}
17751792
17761793int 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)
17891806 OPT_END ()
17901807 };
17911808 int ret ;
1809+ struct branch_info new_branch_info = { 0 };
17921810
17931811 memset (& opts , 0 , sizeof (opts ));
17941812 opts .dwim_new_local_branch = 1 ;
@@ -1819,7 +1837,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
18191837 options = add_checkout_path_options (& opts , options );
18201838
18211839 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 );
18231843 FREE_AND_NULL (options );
18241844 return ret ;
18251845}
@@ -1840,6 +1860,7 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
18401860 OPT_END ()
18411861 };
18421862 int ret ;
1863+ struct branch_info new_branch_info = { 0 };
18431864
18441865 memset (& opts , 0 , sizeof (opts ));
18451866 opts .dwim_new_local_branch = 1 ;
@@ -1859,7 +1880,8 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
18591880 cb_option = 'c' ;
18601881
18611882 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 );
18631885 FREE_AND_NULL (options );
18641886 return ret ;
18651887}
@@ -1881,6 +1903,7 @@ int cmd_restore(int argc, const char **argv, const char *prefix)
18811903 OPT_END ()
18821904 };
18831905 int ret ;
1906+ struct branch_info new_branch_info = { 0 };
18841907
18851908 memset (& opts , 0 , sizeof (opts ));
18861909 opts .accept_ref = 0 ;
@@ -1896,7 +1919,8 @@ int cmd_restore(int argc, const char **argv, const char *prefix)
18961919 options = add_checkout_path_options (& opts , options );
18971920
18981921 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 );
19001924 FREE_AND_NULL (options );
19011925 return ret ;
19021926}
0 commit comments