22#include "refs.h"
33#include "builtin.h"
44#include "parse-options.h"
5+ #include "quote.h"
6+ #include "argv-array.h"
57
68static const char * const git_update_ref_usage [] = {
79 N_ ("git update-ref [options] -d <refname> [<oldval>]" ),
810 N_ ("git update-ref [options] <refname> <newval> [<oldval>]" ),
11+ N_ ("git update-ref [options] --stdin [-z]" ),
912 NULL
1013};
1114
15+ static int updates_alloc ;
16+ static int updates_count ;
17+ static const struct ref_update * * updates ;
18+
19+ static char line_termination = '\n' ;
20+ static int update_flags ;
21+
22+ static struct ref_update * update_alloc (void )
23+ {
24+ struct ref_update * update ;
25+
26+ /* Allocate and zero-init a struct ref_update */
27+ update = xcalloc (1 , sizeof (* update ));
28+ ALLOC_GROW (updates , updates_count + 1 , updates_alloc );
29+ updates [updates_count ++ ] = update ;
30+
31+ /* Store and reset accumulated options */
32+ update -> flags = update_flags ;
33+ update_flags = 0 ;
34+
35+ return update ;
36+ }
37+
38+ static void update_store_ref_name (struct ref_update * update ,
39+ const char * ref_name )
40+ {
41+ if (check_refname_format (ref_name , REFNAME_ALLOW_ONELEVEL ))
42+ die ("invalid ref format: %s" , ref_name );
43+ update -> ref_name = xstrdup (ref_name );
44+ }
45+
46+ static void update_store_new_sha1 (struct ref_update * update ,
47+ const char * newvalue )
48+ {
49+ if (* newvalue && get_sha1 (newvalue , update -> new_sha1 ))
50+ die ("invalid new value for ref %s: %s" ,
51+ update -> ref_name , newvalue );
52+ }
53+
54+ static void update_store_old_sha1 (struct ref_update * update ,
55+ const char * oldvalue )
56+ {
57+ if (* oldvalue && get_sha1 (oldvalue , update -> old_sha1 ))
58+ die ("invalid old value for ref %s: %s" ,
59+ update -> ref_name , oldvalue );
60+
61+ /* We have an old value if non-empty, or if empty without -z */
62+ update -> have_old = * oldvalue || line_termination ;
63+ }
64+
65+ static const char * parse_arg (const char * next , struct strbuf * arg )
66+ {
67+ /* Parse SP-terminated, possibly C-quoted argument */
68+ if (* next != '"' )
69+ while (* next && !isspace (* next ))
70+ strbuf_addch (arg , * next ++ );
71+ else if (unquote_c_style (arg , next , & next ))
72+ die ("badly quoted argument: %s" , next );
73+
74+ /* Return position after the argument */
75+ return next ;
76+ }
77+
78+ static const char * parse_first_arg (const char * next , struct strbuf * arg )
79+ {
80+ /* Parse argument immediately after "command SP" */
81+ strbuf_reset (arg );
82+ if (line_termination ) {
83+ /* Without -z, use the next argument */
84+ next = parse_arg (next , arg );
85+ } else {
86+ /* With -z, use rest of first NUL-terminated line */
87+ strbuf_addstr (arg , next );
88+ next = next + arg -> len ;
89+ }
90+ return next ;
91+ }
92+
93+ static const char * parse_next_arg (const char * next , struct strbuf * arg )
94+ {
95+ /* Parse next SP-terminated or NUL-terminated argument, if any */
96+ strbuf_reset (arg );
97+ if (line_termination ) {
98+ /* Without -z, consume SP and use next argument */
99+ if (!* next )
100+ return NULL ;
101+ if (* next != ' ' )
102+ die ("expected SP but got: %s" , next );
103+ next = parse_arg (next + 1 , arg );
104+ } else {
105+ /* With -z, read the next NUL-terminated line */
106+ if (* next )
107+ die ("expected NUL but got: %s" , next );
108+ if (strbuf_getline (arg , stdin , '\0' ) == EOF )
109+ return NULL ;
110+ next = arg -> buf + arg -> len ;
111+ }
112+ return next ;
113+ }
114+
115+ static void parse_cmd_update (const char * next )
116+ {
117+ struct strbuf ref = STRBUF_INIT ;
118+ struct strbuf newvalue = STRBUF_INIT ;
119+ struct strbuf oldvalue = STRBUF_INIT ;
120+ struct ref_update * update ;
121+
122+ update = update_alloc ();
123+
124+ if ((next = parse_first_arg (next , & ref )) != NULL && ref .buf [0 ])
125+ update_store_ref_name (update , ref .buf );
126+ else
127+ die ("update line missing <ref>" );
128+
129+ if ((next = parse_next_arg (next , & newvalue )) != NULL )
130+ update_store_new_sha1 (update , newvalue .buf );
131+ else
132+ die ("update %s missing <newvalue>" , ref .buf );
133+
134+ if ((next = parse_next_arg (next , & oldvalue )) != NULL )
135+ update_store_old_sha1 (update , oldvalue .buf );
136+ else if (!line_termination )
137+ die ("update %s missing [<oldvalue>] NUL" , ref .buf );
138+
139+ if (next && * next )
140+ die ("update %s has extra input: %s" , ref .buf , next );
141+ }
142+
143+ static void parse_cmd_create (const char * next )
144+ {
145+ struct strbuf ref = STRBUF_INIT ;
146+ struct strbuf newvalue = STRBUF_INIT ;
147+ struct ref_update * update ;
148+
149+ update = update_alloc ();
150+
151+ if ((next = parse_first_arg (next , & ref )) != NULL && ref .buf [0 ])
152+ update_store_ref_name (update , ref .buf );
153+ else
154+ die ("create line missing <ref>" );
155+
156+ if ((next = parse_next_arg (next , & newvalue )) != NULL )
157+ update_store_new_sha1 (update , newvalue .buf );
158+ else
159+ die ("create %s missing <newvalue>" , ref .buf );
160+ if (is_null_sha1 (update -> new_sha1 ))
161+ die ("create %s given zero new value" , ref .buf );
162+
163+ if (next && * next )
164+ die ("create %s has extra input: %s" , ref .buf , next );
165+ }
166+
167+ static void parse_cmd_delete (const char * next )
168+ {
169+ struct strbuf ref = STRBUF_INIT ;
170+ struct strbuf oldvalue = STRBUF_INIT ;
171+ struct ref_update * update ;
172+
173+ update = update_alloc ();
174+
175+ if ((next = parse_first_arg (next , & ref )) != NULL && ref .buf [0 ])
176+ update_store_ref_name (update , ref .buf );
177+ else
178+ die ("delete line missing <ref>" );
179+
180+ if ((next = parse_next_arg (next , & oldvalue )) != NULL )
181+ update_store_old_sha1 (update , oldvalue .buf );
182+ else if (!line_termination )
183+ die ("delete %s missing [<oldvalue>] NUL" , ref .buf );
184+ if (update -> have_old && is_null_sha1 (update -> old_sha1 ))
185+ die ("delete %s given zero old value" , ref .buf );
186+
187+ if (next && * next )
188+ die ("delete %s has extra input: %s" , ref .buf , next );
189+ }
190+
191+ static void parse_cmd_verify (const char * next )
192+ {
193+ struct strbuf ref = STRBUF_INIT ;
194+ struct strbuf value = STRBUF_INIT ;
195+ struct ref_update * update ;
196+
197+ update = update_alloc ();
198+
199+ if ((next = parse_first_arg (next , & ref )) != NULL && ref .buf [0 ])
200+ update_store_ref_name (update , ref .buf );
201+ else
202+ die ("verify line missing <ref>" );
203+
204+ if ((next = parse_next_arg (next , & value )) != NULL ) {
205+ update_store_old_sha1 (update , value .buf );
206+ update_store_new_sha1 (update , value .buf );
207+ } else if (!line_termination )
208+ die ("verify %s missing [<oldvalue>] NUL" , ref .buf );
209+
210+ if (next && * next )
211+ die ("verify %s has extra input: %s" , ref .buf , next );
212+ }
213+
214+ static void parse_cmd_option (const char * next )
215+ {
216+ if (!strcmp (next , "no-deref" ))
217+ update_flags |= REF_NODEREF ;
218+ else
219+ die ("option unknown: %s" , next );
220+ }
221+
222+ static void update_refs_stdin (void )
223+ {
224+ struct strbuf cmd = STRBUF_INIT ;
225+
226+ /* Read each line dispatch its command */
227+ while (strbuf_getline (& cmd , stdin , line_termination ) != EOF )
228+ if (!cmd .buf [0 ])
229+ die ("empty command in input" );
230+ else if (isspace (* cmd .buf ))
231+ die ("whitespace before command: %s" , cmd .buf );
232+ else if (!prefixcmp (cmd .buf , "update " ))
233+ parse_cmd_update (cmd .buf + 7 );
234+ else if (!prefixcmp (cmd .buf , "create " ))
235+ parse_cmd_create (cmd .buf + 7 );
236+ else if (!prefixcmp (cmd .buf , "delete " ))
237+ parse_cmd_delete (cmd .buf + 7 );
238+ else if (!prefixcmp (cmd .buf , "verify " ))
239+ parse_cmd_verify (cmd .buf + 7 );
240+ else if (!prefixcmp (cmd .buf , "option " ))
241+ parse_cmd_option (cmd .buf + 7 );
242+ else
243+ die ("unknown command: %s" , cmd .buf );
244+
245+ strbuf_release (& cmd );
246+ }
247+
12248int cmd_update_ref (int argc , const char * * argv , const char * prefix )
13249{
14250 const char * refname , * oldval , * msg = NULL ;
15251 unsigned char sha1 [20 ], oldsha1 [20 ];
16- int delete = 0 , no_deref = 0 , flags = 0 ;
252+ int delete = 0 , no_deref = 0 , read_stdin = 0 , end_null = 0 , flags = 0 ;
17253 struct option options [] = {
18254 OPT_STRING ( 'm' , NULL , & msg , N_ ("reason" ), N_ ("reason of the update" )),
19255 OPT_BOOLEAN ('d' , NULL , & delete , N_ ("delete the reference" )),
256+ OPT_BOOLEAN ('z' , NULL , & end_null , N_ ("stdin has NUL-terminated arguments" )),
20257 OPT_BOOLEAN ( 0 , "no-deref" , & no_deref ,
21258 N_ ("update <refname> not the one it points to" )),
259+ OPT_BOOLEAN ( 0 , "stdin" , & read_stdin , N_ ("read updates from stdin" )),
22260 OPT_END (),
23261 };
24262
@@ -28,6 +266,18 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
28266 if (msg && !* msg )
29267 die ("Refusing to perform update with empty message." );
30268
269+ if (read_stdin ) {
270+ if (delete || no_deref || argc > 0 )
271+ usage_with_options (git_update_ref_usage , options );
272+ if (end_null )
273+ line_termination = '\0' ;
274+ update_refs_stdin ();
275+ return update_refs (msg , updates , updates_count , DIE_ON_ERR );
276+ }
277+
278+ if (end_null )
279+ usage_with_options (git_update_ref_usage , options );
280+
31281 if (delete ) {
32282 if (argc < 1 || argc > 2 )
33283 usage_with_options (git_update_ref_usage , options );
0 commit comments