393
alias_all_urls();
394
}
395
396
-struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
396
+static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch)
397
{
398
int i;
399
int st;
400
struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);
401
+
402
for (i = 0; i < nr_refspec; i++) {
402
- const char *sp, *ep, *gp;
403
- sp = refspec[i];
404
- if (*sp == '+') {
403
+ size_t llen, rlen;
404
+ int is_glob;
405
+ const char *lhs, *rhs;
406
+
407
+ llen = rlen = is_glob = 0;
408
+
409
+ lhs = refspec[i];
410
+ if (*lhs == '+') {
411
rs[i].force = 1;
406
- sp++;
407
- }
408
- gp = strstr(sp, "/*");
409
- ep = strchr(sp, ':');
410
- if (gp && ep && gp > ep)
411
- gp = NULL;
412
- if (ep) {
413
- if (ep[1]) {
414
- const char *glob = strstr(ep + 1, "/*");
415
- if (glob && glob[2])
416
- glob = NULL;
417
- if (!glob)
418
- gp = NULL;
419
- if (gp)
420
- rs[i].dst = xstrndup(ep + 1,
421
- glob - ep - 1);
422
- else
423
- rs[i].dst = xstrdup(ep + 1);
424
- }
425
- } else {
426
- ep = sp + strlen(sp);
412
+ lhs++;
413
}
428
- if (gp && gp + 2 != ep)
429
- gp = NULL;
430
- if (gp) {
431
- rs[i].pattern = 1;
432
- ep = gp;
414
+
415
+ rhs = strrchr(lhs, ':');
416
+ if (rhs) {
417
+ rhs++;
418
+ rlen = strlen(rhs);
419
+ is_glob = (2 <= rlen && !strcmp(rhs + rlen - 2, "/*"));
420
+ rs[i].dst = xstrndup(rhs, rlen - is_glob * 2);
421
}
434
- rs[i].src = xstrndup(sp, ep - sp);
422
436
- if (*rs[i].src) {
437
- st = check_ref_format(rs[i].src);
438
- if (st && st != CHECK_REF_FORMAT_ONELEVEL)
439
- die("Invalid refspec '%s'", refspec[i]);
423
+ llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
424
+ if (is_glob != (2 <= llen && !memcmp(lhs + llen - 2, "/*", 2)))
425
+ goto invalid;
426
+
427
+ if (is_glob) {
428
+ llen -= 2;
429
+ rlen -= 2;
430
}
441
- if (rs[i].dst && *rs[i].dst) {
442
- st = check_ref_format(rs[i].dst);
443
- if (st && st != CHECK_REF_FORMAT_ONELEVEL)
444
- die("Invalid refspec '%s'", refspec[i]);
431
+ rs[i].pattern = is_glob;
432
+ rs[i].src = xstrndup(lhs, llen);
433
+
434
+ if (fetch) {
435
+ /*
436
+ * LHS
437
+ * - empty is allowed; it means HEAD.
438
+ * - otherwise it must be a valid looking ref.
439
+ */
440
+ if (!*rs[i].src)
441
+ ; /* empty is ok */
442
+ else {
443
+ st = check_ref_format(rs[i].src);
444
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL)
445
+ goto invalid;
446
+ }
447
+ /*
448
+ * RHS
449
+ * - missing is allowed.
450
+ * - empty is ok; it means not to store.
451
+ * - otherwise it must be a valid looking ref.
452
+ */
453
+ if (!rs[i].dst) {
454
+ ; /* ok */
455
+ } else if (!*rs[i].dst) {
456
+ ; /* ok */
457
+ } else {
458
+ st = check_ref_format(rs[i].dst);
459
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL)
460
+ goto invalid;
461
+ }
462
+ } else {
463
+ /*
464
+ * LHS
465
+ * - empty is allowed; it means delete.
466
+ * - when wildcarded, it must be a valid looking ref.
467
+ * - otherwise, it must be an extended SHA-1, but
468
+ * there is no existing way to validate this.
469
+ */
470
+ if (!*rs[i].src)
471
+ ; /* empty is ok */
472
+ else if (is_glob) {
473
+ st = check_ref_format(rs[i].src);
474
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL)
475
+ goto invalid;
476
+ }
477
+ else
478
+ ; /* anything goes, for now */
479
+ /*
480
+ * RHS
481
+ * - missing is allowed, but LHS then must be a
482
+ * valid looking ref.
483
+ * - empty is not allowed.
484
+ * - otherwise it must be a valid looking ref.
485
+ */
486
+ if (!rs[i].dst) {
487
+ st = check_ref_format(rs[i].src);
488
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL)
489
+ goto invalid;
490
+ } else if (!*rs[i].dst) {
491
+ goto invalid;
492
+ } else {
493
+ st = check_ref_format(rs[i].dst);
494
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL)
495
+ goto invalid;
496
+ }
497
}
498
}
499
return rs;
500
+
501
+ invalid:
502
+ die("Invalid refspec '%s'", refspec[i]);
503
+}
504
+
505
+struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec)
506
+{
507
+ return parse_refspec_internal(nr_refspec, refspec, 1);
508
+}
509
+
510
+struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
511
+{
512
+ return parse_refspec_internal(nr_refspec, refspec, 0);
513
}
514
515
static int valid_remote_nick(const char *name)
540
add_url_alias(ret, name);
541
if (!ret->url)
542
return NULL;
478
- ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec);
479
- ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec);
543
+ ret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);
544
+ ret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);
545
return ret;
546
}
547
554
if (!r)
555
continue;
556
if (!r->fetch)
492
- r->fetch = parse_ref_spec(r->fetch_refspec_nr,
493
- r->fetch_refspec);
557
+ r->fetch = parse_fetch_refspec(r->fetch_refspec_nr,
558
+ r->fetch_refspec);
559
if (!r->push)
495
- r->push = parse_ref_spec(r->push_refspec_nr,
496
- r->push_refspec);
560
+ r->push = parse_push_refspec(r->push_refspec_nr,
561
+ r->push_refspec);
562
result = fn(r, priv);
563
}
564
return result;
889
int nr_refspec, const char **refspec, int flags)
890
{
891
struct refspec *rs =
827
- parse_ref_spec(nr_refspec, (const char **) refspec);
892
+ parse_push_refspec(nr_refspec, (const char **) refspec);
893
int send_all = flags & MATCH_REFS_ALL;
894
int send_mirror = flags & MATCH_REFS_MIRROR;
895