Coverage Report

Created: 2024-09-16 06:12

/src/git/builtin/merge-index.c
Line
Count
Source (jump to first uncovered line)
1
#include "builtin.h"
2
#include "hex.h"
3
#include "read-cache-ll.h"
4
#include "repository.h"
5
#include "run-command.h"
6
#include "sparse-index.h"
7
8
static const char *pgm;
9
static int one_shot, quiet;
10
static int err;
11
12
static int merge_entry(int pos, const char *path)
13
0
{
14
0
  int found;
15
0
  const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
16
0
  char hexbuf[4][GIT_MAX_HEXSZ + 1];
17
0
  char ownbuf[4][60];
18
0
  struct child_process cmd = CHILD_PROCESS_INIT;
19
20
0
  if (pos >= the_repository->index->cache_nr)
21
0
    die("git merge-index: %s not in the cache", path);
22
0
  found = 0;
23
0
  do {
24
0
    const struct cache_entry *ce = the_repository->index->cache[pos];
25
0
    int stage = ce_stage(ce);
26
27
0
    if (strcmp(ce->name, path))
28
0
      break;
29
0
    found++;
30
0
    oid_to_hex_r(hexbuf[stage], &ce->oid);
31
0
    xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
32
0
    arguments[stage] = hexbuf[stage];
33
0
    arguments[stage + 4] = ownbuf[stage];
34
0
  } while (++pos < the_repository->index->cache_nr);
35
0
  if (!found)
36
0
    die("git merge-index: %s not in the cache", path);
37
38
0
  strvec_pushv(&cmd.args, arguments);
39
0
  if (run_command(&cmd)) {
40
0
    if (one_shot)
41
0
      err++;
42
0
    else {
43
0
      if (!quiet)
44
0
        die("merge program failed");
45
0
      exit(1);
46
0
    }
47
0
  }
48
0
  return found;
49
0
}
50
51
static void merge_one_path(const char *path)
52
0
{
53
0
  int pos = index_name_pos(the_repository->index, path, strlen(path));
54
55
  /*
56
   * If it already exists in the cache as stage0, it's
57
   * already merged and there is nothing to do.
58
   */
59
0
  if (pos < 0)
60
0
    merge_entry(-pos-1, path);
61
0
}
62
63
static void merge_all(void)
64
0
{
65
0
  int i;
66
  /* TODO: audit for interaction with sparse-index. */
67
0
  ensure_full_index(the_repository->index);
68
0
  for (i = 0; i < the_repository->index->cache_nr; i++) {
69
0
    const struct cache_entry *ce = the_repository->index->cache[i];
70
0
    if (!ce_stage(ce))
71
0
      continue;
72
0
    i += merge_entry(i, ce->name)-1;
73
0
  }
74
0
}
75
76
int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED)
77
0
{
78
0
  int i, force_file = 0;
79
80
  /* Without this we cannot rely on waitpid() to tell
81
   * what happened to our children.
82
   */
83
0
  signal(SIGCHLD, SIG_DFL);
84
85
0
  if (argc < 3)
86
0
    usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
87
88
0
  repo_read_index(the_repository);
89
90
  /* TODO: audit for interaction with sparse-index. */
91
0
  ensure_full_index(the_repository->index);
92
93
0
  i = 1;
94
0
  if (!strcmp(argv[i], "-o")) {
95
0
    one_shot = 1;
96
0
    i++;
97
0
  }
98
0
  if (!strcmp(argv[i], "-q")) {
99
0
    quiet = 1;
100
0
    i++;
101
0
  }
102
0
  pgm = argv[i++];
103
0
  for (; i < argc; i++) {
104
0
    const char *arg = argv[i];
105
0
    if (!force_file && *arg == '-') {
106
0
      if (!strcmp(arg, "--")) {
107
0
        force_file = 1;
108
0
        continue;
109
0
      }
110
0
      if (!strcmp(arg, "-a")) {
111
0
        merge_all();
112
0
        continue;
113
0
      }
114
0
      die("git merge-index: unknown option %s", arg);
115
0
    }
116
0
    merge_one_path(arg);
117
0
  }
118
0
  if (err && !quiet)
119
0
    die("merge program failed");
120
0
  return err;
121
0
}