Raw
1 /*
2 * GIT - The information manager from hell
3 */
4
5 #define USE_THE_REPOSITORY_VARIABLE
6
7 #include "builtin.h"
8 #include "refs.h"
9 #include "setup.h"
10 #include "strbuf.h"
11
12 static const char builtin_check_ref_format_usage[] =
13 "git check-ref-format [--normalize] [<options>] <refname>\n"
14 " or: git check-ref-format --branch <branchname-shorthand>";
15
16 /*
17 * Return a copy of refname but with leading slashes removed and runs
18 * of adjacent slashes replaced with single slashes.
19 *
20 * This function is similar to normalize_path_copy(), but stripped down
21 * to meet check_ref_format's simpler needs.
22 */
23 static char *collapse_slashes(const char *refname)
24 {
25 char *ret = xmallocz(strlen(refname));
26 char ch;
27 char prev = '/';
28 char *cp = ret;
29
30 while ((ch = *refname++) != '\0') {
31 if (prev == '/' && ch == prev)
32 continue;
33
34 *cp++ = ch;
35 prev = ch;
36 }
37 *cp = '\0';
38 return ret;
39 }
40
41 static int check_ref_format_branch(const char *arg)
42 {
43 struct strbuf sb = STRBUF_INIT;
44 const char *name;
45 int nongit;
46
47 setup_git_directory_gently(the_repository, &nongit);
48 if (check_branch_ref(the_repository, &sb, arg) ||
49 !skip_prefix(sb.buf, "refs/heads/", &name))
50 die("'%s' is not a valid branch name", arg);
51 printf("%s\n", name);
52 strbuf_release(&sb);
53 return 0;
54 }
55
56 int cmd_check_ref_format(int argc,
57 const char **argv,
58 const char *prefix,
59 struct repository *repo UNUSED)
60 {
61 int i;
62 int normalize = 0;
63 int flags = 0;
64 const char *refname;
65 char *to_free = NULL;
66 int ret = 1;
67
68 BUG_ON_NON_EMPTY_PREFIX(prefix);
69
70 show_usage_if_asked(argc, argv,
71 builtin_check_ref_format_usage);
72
73 if (argc == 3 && !strcmp(argv[1], "--branch"))
74 return check_ref_format_branch(argv[2]);
75
76 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
77 if (!strcmp(argv[i], "--normalize") || !strcmp(argv[i], "--print"))
78 normalize = 1;
79 else if (!strcmp(argv[i], "--allow-onelevel"))
80 flags |= REFNAME_ALLOW_ONELEVEL;
81 else if (!strcmp(argv[i], "--no-allow-onelevel"))
82 flags &= ~REFNAME_ALLOW_ONELEVEL;
83 else if (!strcmp(argv[i], "--refspec-pattern"))
84 flags |= REFNAME_REFSPEC_PATTERN;
85 else
86 usage(builtin_check_ref_format_usage);
87 }
88 if (! (i == argc - 1))
89 usage(builtin_check_ref_format_usage);
90
91 refname = argv[i];
92 if (normalize)
93 refname = to_free = collapse_slashes(refname);
94 if (check_refname_format(refname, flags))
95 goto cleanup;
96 if (normalize)
97 printf("%s\n", refname);
98
99 ret = 0;
100 cleanup:
101 free(to_free);
102 return ret;
103 }