Coverage Report

Created: 2024-09-16 06:10

/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
}