@@ -35,35 +35,75 @@ static void add_refspec(const char *ref)
3535 refspec [refspec_nr - 1 ] = ref ;
3636}
3737
38- static void set_refspecs (const char * * refs , int nr )
38+ static const char * map_refspec (const char * ref ,
39+ struct remote * remote , struct ref * local_refs )
3940{
41+ struct ref * matched = NULL ;
42+
43+ /* Does "ref" uniquely name our ref? */
44+ if (count_refspec_match (ref , local_refs , & matched ) != 1 )
45+ return ref ;
46+
47+ if (remote -> push ) {
48+ struct refspec query ;
49+ memset (& query , 0 , sizeof (struct refspec ));
50+ query .src = matched -> name ;
51+ if (!query_refspecs (remote -> push , remote -> push_refspec_nr , & query ) &&
52+ query .dst ) {
53+ struct strbuf buf = STRBUF_INIT ;
54+ strbuf_addf (& buf , "%s%s:%s" ,
55+ query .force ? "+" : "" ,
56+ query .src , query .dst );
57+ return strbuf_detach (& buf , NULL );
58+ }
59+ }
60+
61+ if (push_default == PUSH_DEFAULT_UPSTREAM &&
62+ !prefixcmp (matched -> name , "refs/heads/" )) {
63+ struct branch * branch = branch_get (matched -> name + 11 );
64+ if (branch -> merge_nr == 1 && branch -> merge [0 ]-> src ) {
65+ struct strbuf buf = STRBUF_INIT ;
66+ strbuf_addf (& buf , "%s:%s" ,
67+ ref , branch -> merge [0 ]-> src );
68+ return strbuf_detach (& buf , NULL );
69+ }
70+ }
71+
72+ return ref ;
73+ }
74+
75+ static void set_refspecs (const char * * refs , int nr , const char * repo )
76+ {
77+ struct remote * remote = NULL ;
78+ struct ref * local_refs = NULL ;
4079 int i ;
80+
4181 for (i = 0 ; i < nr ; i ++ ) {
4282 const char * ref = refs [i ];
4383 if (!strcmp ("tag" , ref )) {
44- char * tag ;
45- int len ;
84+ struct strbuf tagref = STRBUF_INIT ;
4685 if (nr <= ++ i )
4786 die (_ ("tag shorthand without <tag>" ));
48- len = strlen (refs [i ]) + 11 ;
49- if (deleterefs ) {
50- tag = xmalloc (len + 1 );
51- strcpy (tag , ":refs/tags/" );
52- } else {
53- tag = xmalloc (len );
54- strcpy (tag , "refs/tags/" );
87+ ref = refs [i ];
88+ if (deleterefs )
89+ strbuf_addf (& tagref , ":refs/tags/%s" , ref );
90+ else
91+ strbuf_addf (& tagref , "refs/tags/%s" , ref );
92+ ref = strbuf_detach (& tagref , NULL );
93+ } else if (deleterefs ) {
94+ struct strbuf delref = STRBUF_INIT ;
95+ if (strchr (ref , ':' ))
96+ die (_ ("--delete only accepts plain target ref names" ));
97+ strbuf_addf (& delref , ":%s" , ref );
98+ ref = strbuf_detach (& delref , NULL );
99+ } else if (!strchr (ref , ':' )) {
100+ if (!remote ) {
101+ /* lazily grab remote and local_refs */
102+ remote = remote_get (repo );
103+ local_refs = get_local_heads ();
55104 }
56- strcat (tag , refs [i ]);
57- ref = tag ;
58- } else if (deleterefs && !strchr (ref , ':' )) {
59- char * delref ;
60- int len = strlen (ref )+ 1 ;
61- delref = xmalloc (len + 1 );
62- strcpy (delref , ":" );
63- strcat (delref , ref );
64- ref = delref ;
65- } else if (deleterefs )
66- die (_ ("--delete only accepts plain target ref names" ));
105+ ref = map_refspec (ref , remote , local_refs );
106+ }
67107 add_refspec (ref );
68108 }
69109}
@@ -501,7 +541,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
501541
502542 if (argc > 0 ) {
503543 repo = argv [0 ];
504- set_refspecs (argv + 1 , argc - 1 );
544+ set_refspecs (argv + 1 , argc - 1 , repo );
505545 }
506546
507547 rc = do_push (repo , flags );
0 commit comments