/src/git/builtin/symbolic-ref.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "builtin.h" |
2 | | #include "config.h" |
3 | | #include "gettext.h" |
4 | | #include "refs.h" |
5 | | #include "parse-options.h" |
6 | | #include "strbuf.h" |
7 | | |
8 | | static const char * const git_symbolic_ref_usage[] = { |
9 | | N_("git symbolic-ref [-m <reason>] <name> <ref>"), |
10 | | N_("git symbolic-ref [-q] [--short] [--no-recurse] <name>"), |
11 | | N_("git symbolic-ref --delete [-q] <name>"), |
12 | | NULL |
13 | | }; |
14 | | |
15 | | static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, int print) |
16 | 0 | { |
17 | 0 | int resolve_flags, flag; |
18 | 0 | const char *refname; |
19 | |
|
20 | 0 | resolve_flags = (recurse ? 0 : RESOLVE_REF_NO_RECURSE); |
21 | 0 | refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), |
22 | 0 | HEAD, resolve_flags, NULL, &flag); |
23 | |
|
24 | 0 | if (!refname) |
25 | 0 | die("No such ref: %s", HEAD); |
26 | 0 | else if (!(flag & REF_ISSYMREF)) { |
27 | 0 | if (!quiet) |
28 | 0 | die("ref %s is not a symbolic ref", HEAD); |
29 | 0 | else |
30 | 0 | return 1; |
31 | 0 | } |
32 | 0 | if (print) { |
33 | 0 | char *to_free = NULL; |
34 | 0 | if (shorten) |
35 | 0 | refname = to_free = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), |
36 | 0 | refname, |
37 | 0 | 0); |
38 | 0 | puts(refname); |
39 | 0 | free(to_free); |
40 | 0 | } |
41 | 0 | return 0; |
42 | 0 | } |
43 | | |
44 | | int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) |
45 | 0 | { |
46 | 0 | int quiet = 0, delete = 0, shorten = 0, recurse = 1, ret = 0; |
47 | 0 | const char *msg = NULL; |
48 | 0 | struct option options[] = { |
49 | 0 | OPT__QUIET(&quiet, |
50 | 0 | N_("suppress error message for non-symbolic (detached) refs")), |
51 | 0 | OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")), |
52 | 0 | OPT_BOOL(0, "short", &shorten, N_("shorten ref output")), |
53 | 0 | OPT_BOOL(0, "recurse", &recurse, N_("recursively dereference (default)")), |
54 | 0 | OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")), |
55 | 0 | OPT_END(), |
56 | 0 | }; |
57 | |
|
58 | 0 | git_config(git_default_config, NULL); |
59 | 0 | argc = parse_options(argc, argv, prefix, options, |
60 | 0 | git_symbolic_ref_usage, 0); |
61 | 0 | if (msg && !*msg) |
62 | 0 | die("Refusing to perform update with empty message"); |
63 | | |
64 | 0 | if (delete) { |
65 | 0 | if (argc != 1) |
66 | 0 | usage_with_options(git_symbolic_ref_usage, options); |
67 | 0 | ret = check_symref(argv[0], 1, 0, 0, 0); |
68 | 0 | if (ret) |
69 | 0 | die("Cannot delete %s, not a symbolic ref", argv[0]); |
70 | 0 | if (!strcmp(argv[0], "HEAD")) |
71 | 0 | die("deleting '%s' is not allowed", argv[0]); |
72 | 0 | return refs_delete_ref(get_main_ref_store(the_repository), |
73 | 0 | NULL, argv[0], NULL, REF_NO_DEREF); |
74 | 0 | } |
75 | | |
76 | 0 | switch (argc) { |
77 | 0 | case 1: |
78 | 0 | ret = check_symref(argv[0], quiet, shorten, recurse, 1); |
79 | 0 | break; |
80 | 0 | case 2: |
81 | 0 | if (!strcmp(argv[0], "HEAD") && |
82 | 0 | !starts_with(argv[1], "refs/")) |
83 | 0 | die("Refusing to point HEAD outside of refs/"); |
84 | 0 | if (check_refname_format(argv[1], REFNAME_ALLOW_ONELEVEL) < 0) |
85 | 0 | die("Refusing to set '%s' to invalid ref '%s'", argv[0], argv[1]); |
86 | 0 | ret = !!refs_update_symref(get_main_ref_store(the_repository), |
87 | 0 | argv[0], argv[1], msg); |
88 | 0 | break; |
89 | 0 | default: |
90 | 0 | usage_with_options(git_symbolic_ref_usage, options); |
91 | 0 | } |
92 | 0 | return ret; |
93 | 0 | } |