refspec: move refspec parsing logic into its own file
In preparation for performing a refactor on refspec related code, move the refspec parsing logic into its own file. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Brandon Williams committed
May 16, 2018 at 15:57 UTC
ec0cb496553ac82f97205a415ca77618406b30e3
17 files changed
+204
-184
Makefile
+1
@@ -928,6 +928,7 @@ LIB_OBJS += refs/files-backend.o
928
LIB_OBJS += refs/iterator.o
929
LIB_OBJS += refs/packed-backend.o
930
LIB_OBJS += refs/ref-cache.o
931
+LIB_OBJS += refspec.o
932
LIB_OBJS += ref-filter.o
933
LIB_OBJS += remote.o
934
LIB_OBJS += replace-object.o
branch.c
+1
@@ -3,6 +3,7 @@
3
#include "config.h"
4
#include "branch.h"
5
#include "refs.h"
6
+#include "refspec.h"
7
#include "remote.h"
8
#include "commit.h"
9
#include "worktree.h"
builtin/clone.c
+1
@@ -14,6 +14,7 @@
14
#include "parse-options.h"
15
#include "fetch-pack.h"
16
#include "refs.h"
17
+#include "refspec.h"
18
#include "tree.h"
19
#include "tree-walk.h"
20
#include "unpack-trees.h"
builtin/fast-export.c
+1
@@ -7,6 +7,7 @@
7
#include "cache.h"
8
#include "config.h"
9
#include "refs.h"
10
+#include "refspec.h"
11
#include "commit.h"
12
#include "object.h"
13
#include "tag.h"
builtin/fetch.c
+1
@@ -5,6 +5,7 @@
5
#include "config.h"
6
#include "repository.h"
7
#include "refs.h"
8
+#include "refspec.h"
9
#include "commit.h"
10
#include "builtin.h"
11
#include "string-list.h"
builtin/merge.c
+1
@@ -14,6 +14,7 @@
14
#include "run-command.h"
15
#include "diff.h"
16
#include "refs.h"
17
+#include "refspec.h"
18
#include "commit.h"
19
#include "diffcore.h"
20
#include "revision.h"
builtin/pull.c
+1
@@ -15,6 +15,7 @@
15
#include "remote.h"
16
#include "dir.h"
17
#include "refs.h"
18
+#include "refspec.h"
19
#include "revision.h"
20
#include "submodule.h"
21
#include "submodule-config.h"
builtin/push.c
+1
@@ -4,6 +4,7 @@
4
#include "cache.h"
5
#include "config.h"
6
#include "refs.h"
7
+#include "refspec.h"
8
#include "run-command.h"
9
#include "builtin.h"
10
#include "remote.h"
builtin/remote.c
+1
@@ -7,6 +7,7 @@
7
#include "strbuf.h"
8
#include "run-command.h"
9
#include "refs.h"
10
+#include "refspec.h"
11
#include "argv-array.h"
12
13
static const char * const builtin_remote_usage[] = {
builtin/submodule--helper.c
+1
@@ -12,6 +12,7 @@
12
#include "run-command.h"
13
#include "remote.h"
14
#include "refs.h"
15
+#include "refspec.h"
16
#include "connect.h"
17
#include "revision.h"
18
#include "diffcore.h"
checkout.c
+1
@@ -1,5 +1,6 @@
1
#include "cache.h"
2
#include "remote.h"
3
+#include "refspec.h"
4
#include "checkout.h"
5
6
struct tracking_name_data {
refspec.c
new
+167
@@ -0,0 +1,167 @@
1
+#include "cache.h"
2
+#include "refs.h"
3
+#include "refspec.h"
4
+
5
+static struct refspec s_tag_refspec = {
6
+ 0,
7
+ 1,
8
+ 0,
9
+ 0,
10
+ "refs/tags/*",
11
+ "refs/tags/*"
12
+};
13
+
14
+/* See TAG_REFSPEC for the string version */
15
+const struct refspec *tag_refspec = &s_tag_refspec;
16
+
17
+static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
18
+{
19
+ int i;
20
+ struct refspec *rs = xcalloc(nr_refspec, sizeof(*rs));
21
+
22
+ for (i = 0; i < nr_refspec; i++) {
23
+ size_t llen;
24
+ int is_glob;
25
+ const char *lhs, *rhs;
26
+ int flags;
27
+
28
+ is_glob = 0;
29
+
30
+ lhs = refspec[i];
31
+ if (*lhs == '+') {
32
+ rs[i].force = 1;
33
+ lhs++;
34
+ }
35
+
36
+ rhs = strrchr(lhs, ':');
37
+
38
+ /*
39
+ * Before going on, special case ":" (or "+:") as a refspec
40
+ * for pushing matching refs.
41
+ */
42
+ if (!fetch && rhs == lhs && rhs[1] == '\0') {
43
+ rs[i].matching = 1;
44
+ continue;
45
+ }
46
+
47
+ if (rhs) {
48
+ size_t rlen = strlen(++rhs);
49
+ is_glob = (1 <= rlen && strchr(rhs, '*'));
50
+ rs[i].dst = xstrndup(rhs, rlen);
51
+ }
52
+
53
+ llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
54
+ if (1 <= llen && memchr(lhs, '*', llen)) {
55
+ if ((rhs && !is_glob) || (!rhs && fetch))
56
+ goto invalid;
57
+ is_glob = 1;
58
+ } else if (rhs && is_glob) {
59
+ goto invalid;
60
+ }
61
+
62
+ rs[i].pattern = is_glob;
63
+ rs[i].src = xstrndup(lhs, llen);
64
+ flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
65
+
66
+ if (fetch) {
67
+ struct object_id unused;
68
+
69
+ /* LHS */
70
+ if (!*rs[i].src)
71
+ ; /* empty is ok; it means "HEAD" */
72
+ else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(rs[i].src, &unused))
73
+ rs[i].exact_sha1 = 1; /* ok */
74
+ else if (!check_refname_format(rs[i].src, flags))
75
+ ; /* valid looking ref is ok */
76
+ else
77
+ goto invalid;
78
+ /* RHS */
79
+ if (!rs[i].dst)
80
+ ; /* missing is ok; it is the same as empty */
81
+ else if (!*rs[i].dst)
82
+ ; /* empty is ok; it means "do not store" */
83
+ else if (!check_refname_format(rs[i].dst, flags))
84
+ ; /* valid looking ref is ok */
85
+ else
86
+ goto invalid;
87
+ } else {
88
+ /*
89
+ * LHS
90
+ * - empty is allowed; it means delete.
91
+ * - when wildcarded, it must be a valid looking ref.
92
+ * - otherwise, it must be an extended SHA-1, but
93
+ * there is no existing way to validate this.
94
+ */
95
+ if (!*rs[i].src)
96
+ ; /* empty is ok */
97
+ else if (is_glob) {
98
+ if (check_refname_format(rs[i].src, flags))
99
+ goto invalid;
100
+ }
101
+ else
102
+ ; /* anything goes, for now */
103
+ /*
104
+ * RHS
105
+ * - missing is allowed, but LHS then must be a
106
+ * valid looking ref.
107
+ * - empty is not allowed.
108
+ * - otherwise it must be a valid looking ref.
109
+ */
110
+ if (!rs[i].dst) {
111
+ if (check_refname_format(rs[i].src, flags))
112
+ goto invalid;
113
+ } else if (!*rs[i].dst) {
114
+ goto invalid;
115
+ } else {
116
+ if (check_refname_format(rs[i].dst, flags))
117
+ goto invalid;
118
+ }
119
+ }
120
+ }
121
+ return rs;
122
+
123
+ invalid:
124
+ if (verify) {
125
+ /*
126
+ * nr_refspec must be greater than zero and i must be valid
127
+ * since it is only possible to reach this point from within
128
+ * the for loop above.
129
+ */
130
+ free_refspec(i+1, rs);
131
+ return NULL;
132
+ }
133
+ die("Invalid refspec '%s'", refspec[i]);
134
+}
135
+
136
+int valid_fetch_refspec(const char *fetch_refspec_str)
137
+{
138
+ struct refspec *refspec;
139
+
140
+ refspec = parse_refspec_internal(1, &fetch_refspec_str, 1, 1);
141
+ free_refspec(1, refspec);
142
+ return !!refspec;
143
+}
144
+
145
+struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec)
146
+{
147
+ return parse_refspec_internal(nr_refspec, refspec, 1, 0);
148
+}
149
+
150
+struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
151
+{
152
+ return parse_refspec_internal(nr_refspec, refspec, 0, 0);
153
+}
154
+
155
+void free_refspec(int nr_refspec, struct refspec *refspec)
156
+{
157
+ int i;
158
+
159
+ if (!refspec)
160
+ return;
161
+
162
+ for (i = 0; i < nr_refspec; i++) {
163
+ free(refspec[i].src);
164
+ free(refspec[i].dst);
165
+ }
166
+ free(refspec);
167
+}
refspec.h
new
+23
@@ -0,0 +1,23 @@
1
+#ifndef REFSPEC_H
2
+#define REFSPEC_H
3
+
4
+#define TAG_REFSPEC "refs/tags/*:refs/tags/*"
5
+extern const struct refspec *tag_refspec;
6
+
7
+struct refspec {
8
+ unsigned force : 1;
9
+ unsigned pattern : 1;
10
+ unsigned matching : 1;
11
+ unsigned exact_sha1 : 1;
12
+
13
+ char *src;
14
+ char *dst;
15
+};
16
+
17
+int valid_fetch_refspec(const char *refspec);
18
+struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
19
+struct refspec *parse_push_refspec(int nr_refspec, const char **refspec);
20
+
21
+void free_refspec(int nr_refspec, struct refspec *refspec);
22
+
23
+#endif /* REFSPEC_H */
remote.c
+1
-164
@@ -2,6 +2,7 @@
2
#include "config.h"
3
#include "remote.h"
4
#include "refs.h"
5
+#include "refspec.h"
6
#include "commit.h"
7
#include "diff.h"
8
#include "revision.h"
@@ -13,18 +14,6 @@
14
15
enum map_direction { FROM_SRC, FROM_DST };
16
16
-static struct refspec s_tag_refspec = {
17
- 0,
18
- 1,
19
- 0,
20
- 0,
21
- "refs/tags/*",
22
- "refs/tags/*"
23
-};
24
-
25
-/* See TAG_REFSPEC for the string version */
26
-const struct refspec *tag_refspec = &s_tag_refspec;
27
-
17
struct counted_string {
18
size_t len;
19
const char *s;
@@ -499,158 +488,6 @@ static void read_config(void)
488
alias_all_urls();
489
}
490
502
-static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
503
-{
504
- int i;
505
- struct refspec *rs = xcalloc(nr_refspec, sizeof(*rs));
506
-
507
- for (i = 0; i < nr_refspec; i++) {
508
- size_t llen;
509
- int is_glob;
510
- const char *lhs, *rhs;
511
- int flags;
512
-
513
- is_glob = 0;
514
-
515
- lhs = refspec[i];
516
- if (*lhs == '+') {
517
- rs[i].force = 1;
518
- lhs++;
519
- }
520
-
521
- rhs = strrchr(lhs, ':');
522
-
523
- /*
524
- * Before going on, special case ":" (or "+:") as a refspec
525
- * for pushing matching refs.
526
- */
527
- if (!fetch && rhs == lhs && rhs[1] == '\0') {
528
- rs[i].matching = 1;
529
- continue;
530
- }
531
-
532
- if (rhs) {
533
- size_t rlen = strlen(++rhs);
534
- is_glob = (1 <= rlen && strchr(rhs, '*'));
535
- rs[i].dst = xstrndup(rhs, rlen);
536
- }
537
-
538
- llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
539
- if (1 <= llen && memchr(lhs, '*', llen)) {
540
- if ((rhs && !is_glob) || (!rhs && fetch))
541
- goto invalid;
542
- is_glob = 1;
543
- } else if (rhs && is_glob) {
544
- goto invalid;
545
- }
546
-
547
- rs[i].pattern = is_glob;
548
- rs[i].src = xstrndup(lhs, llen);
549
- flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
550
-
551
- if (fetch) {
552
- struct object_id unused;
553
-
554
- /* LHS */
555
- if (!*rs[i].src)
556
- ; /* empty is ok; it means "HEAD" */
557
- else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(rs[i].src, &unused))
558
- rs[i].exact_sha1 = 1; /* ok */
559
- else if (!check_refname_format(rs[i].src, flags))
560
- ; /* valid looking ref is ok */
561
- else
562
- goto invalid;
563
- /* RHS */
564
- if (!rs[i].dst)
565
- ; /* missing is ok; it is the same as empty */
566
- else if (!*rs[i].dst)
567
- ; /* empty is ok; it means "do not store" */
568
- else if (!check_refname_format(rs[i].dst, flags))
569
- ; /* valid looking ref is ok */
570
- else
571
- goto invalid;
572
- } else {
573
- /*
574
- * LHS
575
- * - empty is allowed; it means delete.
576
- * - when wildcarded, it must be a valid looking ref.
577
- * - otherwise, it must be an extended SHA-1, but
578
- * there is no existing way to validate this.
579
- */
580
- if (!*rs[i].src)
581
- ; /* empty is ok */
582
- else if (is_glob) {
583
- if (check_refname_format(rs[i].src, flags))
584
- goto invalid;
585
- }
586
- else
587
- ; /* anything goes, for now */
588
- /*
589
- * RHS
590
- * - missing is allowed, but LHS then must be a
591
- * valid looking ref.
592
- * - empty is not allowed.
593
- * - otherwise it must be a valid looking ref.
594
- */
595
- if (!rs[i].dst) {
596
- if (check_refname_format(rs[i].src, flags))
597
- goto invalid;
598
- } else if (!*rs[i].dst) {
599
- goto invalid;
600
- } else {
601
- if (check_refname_format(rs[i].dst, flags))
602
- goto invalid;
603
- }
604
- }
605
- }
606
- return rs;
607
-
608
- invalid:
609
- if (verify) {
610
- /*
611
- * nr_refspec must be greater than zero and i must be valid
612
- * since it is only possible to reach this point from within
613
- * the for loop above.
614
- */
615
- free_refspec(i+1, rs);
616
- return NULL;
617
- }
618
- die("Invalid refspec '%s'", refspec[i]);
619
-}
620
-
621
-int valid_fetch_refspec(const char *fetch_refspec_str)
622
-{
623
- struct refspec *refspec;
624
-
625
- refspec = parse_refspec_internal(1, &fetch_refspec_str, 1, 1);
626
- free_refspec(1, refspec);
627
- return !!refspec;
628
-}
629
-
630
-struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec)
631
-{
632
- return parse_refspec_internal(nr_refspec, refspec, 1, 0);
633
-}
634
-
635
-struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
636
-{
637
- return parse_refspec_internal(nr_refspec, refspec, 0, 0);
638
-}
639
-
640
-void free_refspec(int nr_refspec, struct refspec *refspec)
641
-{
642
- int i;
643
-
644
- if (!refspec)
645
- return;
646
-
647
- for (i = 0; i < nr_refspec; i++) {
648
- free(refspec[i].src);
649
- free(refspec[i].dst);
650
- }
651
- free(refspec);
652
-}
653
-
491
static int valid_remote_nick(const char *name)
492
{
493
if (!name[0] || is_dot_or_dotdot(name))
remote.h
-20
@@ -68,18 +68,6 @@ int for_each_remote(each_remote_fn fn, void *priv);
68
69
int remote_has_url(struct remote *remote, const char *url);
70
71
-struct refspec {
72
- unsigned force : 1;
73
- unsigned pattern : 1;
74
- unsigned matching : 1;
75
- unsigned exact_sha1 : 1;
76
-
77
- char *src;
78
- char *dst;
79
-};
80
-
81
-extern const struct refspec *tag_refspec;
82
-
71
struct ref {
72
struct ref *next;
73
struct object_id old_oid;
@@ -175,12 +163,6 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid);
163
*/
164
struct ref *ref_remove_duplicates(struct ref *ref_map);
165
178
-int valid_fetch_refspec(const char *refspec);
179
-struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
180
-extern struct refspec *parse_push_refspec(int nr_refspec, const char **refspec);
181
-
182
-void free_refspec(int nr_refspec, struct refspec *refspec);
183
-
166
extern int query_refspecs(struct refspec *specs, int nr, struct refspec *query);
167
char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
168
const char *name);
@@ -313,8 +295,6 @@ extern int parseopt_push_cas_option(const struct option *, const char *arg, int
295
extern int is_empty_cas(const struct push_cas_option *);
296
void apply_push_cas(struct push_cas_option *, struct remote *, struct ref *);
297
316
-#define TAG_REFSPEC "refs/tags/*:refs/tags/*"
317
-
298
void add_prune_tags_to_fetch_refspec(struct remote *remote);
299
300
#endif
transport-helper.c
+1
@@ -11,6 +11,7 @@
11
#include "sigchain.h"
12
#include "argv-array.h"
13
#include "refs.h"
14
+#include "refspec.h"
15
#include "transport-internal.h"
16
#include "protocol.h"
17
transport.c
+1
@@ -11,6 +11,7 @@
11
#include "bundle.h"
12
#include "dir.h"
13
#include "refs.h"
14
+#include "refspec.h"
15
#include "branch.h"
16
#include "url.h"
17
#include "submodule.h"