@@ -76,6 +76,65 @@ static char *parse_refname(const char **next)
76
76
return strbuf_detach (& ref , NULL );
77
77
}
78
78
79
+ /*
80
+ * Wrapper around parse_refname which skips the next delimiter.
81
+ */
82
+ static char * parse_next_refname (const char * * next )
83
+ {
84
+ if (line_termination ) {
85
+ /* Without -z, consume SP and use next argument */
86
+ if (!* * next || * * next == line_termination )
87
+ return NULL ;
88
+ if (* * next != ' ' )
89
+ die ("expected SP but got: %s" , * next );
90
+ } else {
91
+ /* With -z, read the next NUL-terminated line */
92
+ if (* * next )
93
+ return NULL ;
94
+ }
95
+ /* Skip the delimiter */
96
+ (* next )++ ;
97
+
98
+ return parse_refname (next );
99
+ }
100
+
101
+ /*
102
+ * Wrapper around parse_arg which skips the next delimiter.
103
+ */
104
+ static char * parse_next_arg (const char * * next )
105
+ {
106
+ struct strbuf arg = STRBUF_INIT ;
107
+
108
+ if (line_termination ) {
109
+ /* Without -z, consume SP and use next argument */
110
+ if (!* * next || * * next == line_termination )
111
+ return NULL ;
112
+ if (* * next != ' ' )
113
+ die ("expected SP but got: %s" , * next );
114
+ } else {
115
+ /* With -z, read the next NUL-terminated line */
116
+ if (* * next )
117
+ return NULL ;
118
+ }
119
+ /* Skip the delimiter */
120
+ (* next )++ ;
121
+
122
+ if (line_termination ) {
123
+ /* Without -z, use the next argument */
124
+ * next = parse_arg (* next , & arg );
125
+ } else {
126
+ /* With -z, use everything up to the next NUL */
127
+ strbuf_addstr (& arg , * next );
128
+ * next += arg .len ;
129
+ }
130
+
131
+ if (arg .len )
132
+ return strbuf_detach (& arg , NULL );
133
+
134
+ strbuf_release (& arg );
135
+ return NULL ;
136
+ }
137
+
79
138
/*
80
139
* The value being parsed is <old-oid> (as opposed to <new-oid>; the
81
140
* difference affects which error messages are generated):
@@ -214,6 +273,61 @@ static void parse_cmd_update(struct ref_transaction *transaction,
214
273
strbuf_release (& err );
215
274
}
216
275
276
+ static void parse_cmd_symref_update (struct ref_transaction * transaction ,
277
+ const char * next , const char * end )
278
+ {
279
+ char * refname , * new_target , * old_arg ;
280
+ char * old_target = NULL ;
281
+ struct strbuf err = STRBUF_INIT ;
282
+ struct object_id old_oid ;
283
+ int have_old_oid = 0 ;
284
+
285
+ refname = parse_refname (& next );
286
+ if (!refname )
287
+ die ("symref-update: missing <ref>" );
288
+
289
+ new_target = parse_next_refname (& next );
290
+ if (!new_target )
291
+ die ("symref-update %s: missing <new-target>" , refname );
292
+
293
+ old_arg = parse_next_arg (& next );
294
+ if (old_arg ) {
295
+ old_target = parse_next_arg (& next );
296
+ if (!old_target )
297
+ die ("symref-update %s: expected old value" , refname );
298
+
299
+ if (!strcmp (old_arg , "oid" )) {
300
+ if (repo_get_oid (the_repository , old_target , & old_oid ))
301
+ die ("symref-update %s: invalid oid: %s" , refname , old_target );
302
+
303
+ have_old_oid = 1 ;
304
+ } else if (!strcmp (old_arg , "ref" )) {
305
+ if (check_refname_format (old_target , REFNAME_ALLOW_ONELEVEL ))
306
+ die ("symref-update %s: invalid ref: %s" , refname , old_target );
307
+ } else {
308
+ die ("symref-update %s: invalid arg '%s' for old value" , refname , old_arg );
309
+ }
310
+ }
311
+
312
+ if (* next != line_termination )
313
+ die ("symref-update %s: extra input: %s" , refname , next );
314
+
315
+ if (ref_transaction_update (transaction , refname , NULL ,
316
+ have_old_oid ? & old_oid : NULL ,
317
+ new_target ,
318
+ have_old_oid ? NULL : old_target ,
319
+ update_flags | create_reflog_flag ,
320
+ msg , & err ))
321
+ die ("%s" , err .buf );
322
+
323
+ update_flags = default_flags ;
324
+ free (refname );
325
+ free (old_arg );
326
+ free (old_target );
327
+ free (new_target );
328
+ strbuf_release (& err );
329
+ }
330
+
217
331
static void parse_cmd_create (struct ref_transaction * transaction ,
218
332
const char * next , const char * end )
219
333
{
@@ -234,13 +348,42 @@ static void parse_cmd_create(struct ref_transaction *transaction,
234
348
if (* next != line_termination )
235
349
die ("create %s: extra input: %s" , refname , next );
236
350
237
- if (ref_transaction_create (transaction , refname , & new_oid ,
351
+ if (ref_transaction_create (transaction , refname , & new_oid , NULL ,
352
+ update_flags | create_reflog_flag ,
353
+ msg , & err ))
354
+ die ("%s" , err .buf );
355
+
356
+ update_flags = default_flags ;
357
+ free (refname );
358
+ strbuf_release (& err );
359
+ }
360
+
361
+
362
+ static void parse_cmd_symref_create (struct ref_transaction * transaction ,
363
+ const char * next , const char * end )
364
+ {
365
+ struct strbuf err = STRBUF_INIT ;
366
+ char * refname , * new_target ;
367
+
368
+ refname = parse_refname (& next );
369
+ if (!refname )
370
+ die ("symref-create: missing <ref>" );
371
+
372
+ new_target = parse_next_refname (& next );
373
+ if (!new_target )
374
+ die ("symref-create %s: missing <new-target>" , refname );
375
+
376
+ if (* next != line_termination )
377
+ die ("symref-create %s: extra input: %s" , refname , next );
378
+
379
+ if (ref_transaction_create (transaction , refname , NULL , new_target ,
238
380
update_flags | create_reflog_flag ,
239
381
msg , & err ))
240
382
die ("%s" , err .buf );
241
383
242
384
update_flags = default_flags ;
243
385
free (refname );
386
+ free (new_target );
244
387
strbuf_release (& err );
245
388
}
246
389
@@ -270,14 +413,44 @@ static void parse_cmd_delete(struct ref_transaction *transaction,
270
413
271
414
if (ref_transaction_delete (transaction , refname ,
272
415
have_old ? & old_oid : NULL ,
273
- update_flags , msg , & err ))
416
+ NULL , update_flags , msg , & err ))
274
417
die ("%s" , err .buf );
275
418
276
419
update_flags = default_flags ;
277
420
free (refname );
278
421
strbuf_release (& err );
279
422
}
280
423
424
+
425
+ static void parse_cmd_symref_delete (struct ref_transaction * transaction ,
426
+ const char * next , const char * end )
427
+ {
428
+ struct strbuf err = STRBUF_INIT ;
429
+ char * refname , * old_target ;
430
+
431
+ if (!(update_flags & REF_NO_DEREF ))
432
+ die ("symref-delete: cannot operate with deref mode" );
433
+
434
+ refname = parse_refname (& next );
435
+ if (!refname )
436
+ die ("symref-delete: missing <ref>" );
437
+
438
+ old_target = parse_next_refname (& next );
439
+
440
+ if (* next != line_termination )
441
+ die ("symref-delete %s: extra input: %s" , refname , next );
442
+
443
+ if (ref_transaction_delete (transaction , refname , NULL ,
444
+ old_target , update_flags , msg , & err ))
445
+ die ("%s" , err .buf );
446
+
447
+ update_flags = default_flags ;
448
+ free (refname );
449
+ free (old_target );
450
+ strbuf_release (& err );
451
+ }
452
+
453
+
281
454
static void parse_cmd_verify (struct ref_transaction * transaction ,
282
455
const char * next , const char * end )
283
456
{
@@ -297,11 +470,47 @@ static void parse_cmd_verify(struct ref_transaction *transaction,
297
470
die ("verify %s: extra input: %s" , refname , next );
298
471
299
472
if (ref_transaction_verify (transaction , refname , & old_oid ,
300
- update_flags , & err ))
473
+ NULL , update_flags , & err ))
474
+ die ("%s" , err .buf );
475
+
476
+ update_flags = default_flags ;
477
+ free (refname );
478
+ strbuf_release (& err );
479
+ }
480
+
481
+ static void parse_cmd_symref_verify (struct ref_transaction * transaction ,
482
+ const char * next , const char * end )
483
+ {
484
+ struct strbuf err = STRBUF_INIT ;
485
+ struct object_id old_oid ;
486
+ char * refname , * old_target ;
487
+
488
+ if (!(update_flags & REF_NO_DEREF ))
489
+ die ("symref-verify: cannot operate with deref mode" );
490
+
491
+ refname = parse_refname (& next );
492
+ if (!refname )
493
+ die ("symref-verify: missing <ref>" );
494
+
495
+ /*
496
+ * old_ref is optional, if not provided, we need to ensure that the
497
+ * ref doesn't exist.
498
+ */
499
+ old_target = parse_next_refname (& next );
500
+ if (!old_target )
501
+ oidcpy (& old_oid , null_oid ());
502
+
503
+ if (* next != line_termination )
504
+ die ("symref-verify %s: extra input: %s" , refname , next );
505
+
506
+ if (ref_transaction_verify (transaction , refname ,
507
+ old_target ? NULL : & old_oid ,
508
+ old_target , update_flags , & err ))
301
509
die ("%s" , err .buf );
302
510
303
511
update_flags = default_flags ;
304
512
free (refname );
513
+ free (old_target );
305
514
strbuf_release (& err );
306
515
}
307
516
@@ -380,15 +589,19 @@ static const struct parse_cmd {
380
589
unsigned args ;
381
590
enum update_refs_state state ;
382
591
} command [] = {
383
- { "update" , parse_cmd_update , 3 , UPDATE_REFS_OPEN },
384
- { "create" , parse_cmd_create , 2 , UPDATE_REFS_OPEN },
385
- { "delete" , parse_cmd_delete , 2 , UPDATE_REFS_OPEN },
386
- { "verify" , parse_cmd_verify , 2 , UPDATE_REFS_OPEN },
387
- { "option" , parse_cmd_option , 1 , UPDATE_REFS_OPEN },
388
- { "start" , parse_cmd_start , 0 , UPDATE_REFS_STARTED },
389
- { "prepare" , parse_cmd_prepare , 0 , UPDATE_REFS_PREPARED },
390
- { "abort" , parse_cmd_abort , 0 , UPDATE_REFS_CLOSED },
391
- { "commit" , parse_cmd_commit , 0 , UPDATE_REFS_CLOSED },
592
+ { "update" , parse_cmd_update , 3 , UPDATE_REFS_OPEN },
593
+ { "create" , parse_cmd_create , 2 , UPDATE_REFS_OPEN },
594
+ { "delete" , parse_cmd_delete , 2 , UPDATE_REFS_OPEN },
595
+ { "verify" , parse_cmd_verify , 2 , UPDATE_REFS_OPEN },
596
+ { "symref-update" , parse_cmd_symref_update , 4 , UPDATE_REFS_OPEN },
597
+ { "symref-create" , parse_cmd_symref_create , 2 , UPDATE_REFS_OPEN },
598
+ { "symref-delete" , parse_cmd_symref_delete , 2 , UPDATE_REFS_OPEN },
599
+ { "symref-verify" , parse_cmd_symref_verify , 2 , UPDATE_REFS_OPEN },
600
+ { "option" , parse_cmd_option , 1 , UPDATE_REFS_OPEN },
601
+ { "start" , parse_cmd_start , 0 , UPDATE_REFS_STARTED },
602
+ { "prepare" , parse_cmd_prepare , 0 , UPDATE_REFS_PREPARED },
603
+ { "abort" , parse_cmd_abort , 0 , UPDATE_REFS_CLOSED },
604
+ { "commit" , parse_cmd_commit , 0 , UPDATE_REFS_CLOSED },
392
605
};
393
606
394
607
static void update_refs_stdin (void )
0 commit comments