Coverage Report

Created: 2024-09-08 06:23

/src/git/chdir-notify.c
Line
Count
Source (jump to first uncovered line)
1
#include "git-compat-util.h"
2
#include "abspath.h"
3
#include "chdir-notify.h"
4
#include "list.h"
5
#include "path.h"
6
#include "strbuf.h"
7
#include "trace.h"
8
9
struct chdir_notify_entry {
10
  const char *name;
11
  chdir_notify_callback cb;
12
  void *data;
13
  struct list_head list;
14
};
15
static LIST_HEAD(chdir_notify_entries);
16
17
void chdir_notify_register(const char *name,
18
         chdir_notify_callback cb,
19
         void *data)
20
0
{
21
0
  struct chdir_notify_entry *e = xmalloc(sizeof(*e));
22
0
  e->name = name;
23
0
  e->cb = cb;
24
0
  e->data = data;
25
0
  list_add_tail(&e->list, &chdir_notify_entries);
26
0
}
27
28
static void reparent_cb(const char *name,
29
      const char *old_cwd,
30
      const char *new_cwd,
31
      void *data)
32
0
{
33
0
  char **path = data;
34
0
  char *tmp = *path;
35
36
0
  if (!tmp)
37
0
    return;
38
39
0
  *path = reparent_relative_path(old_cwd, new_cwd, tmp);
40
0
  free(tmp);
41
42
0
  if (name) {
43
0
    trace_printf_key(&trace_setup_key,
44
0
         "setup: reparent %s to '%s'",
45
0
         name, *path);
46
0
  }
47
0
}
48
49
void chdir_notify_reparent(const char *name, char **path)
50
0
{
51
0
  chdir_notify_register(name, reparent_cb, path);
52
0
}
53
54
int chdir_notify(const char *new_cwd)
55
0
{
56
0
  struct strbuf old_cwd = STRBUF_INIT;
57
0
  struct list_head *pos;
58
59
0
  if (strbuf_getcwd(&old_cwd) < 0)
60
0
    return -1;
61
0
  if (chdir(new_cwd) < 0) {
62
0
    int saved_errno = errno;
63
0
    strbuf_release(&old_cwd);
64
0
    errno = saved_errno;
65
0
    return -1;
66
0
  }
67
68
0
  trace_printf_key(&trace_setup_key,
69
0
       "setup: chdir from '%s' to '%s'",
70
0
       old_cwd.buf, new_cwd);
71
72
0
  list_for_each(pos, &chdir_notify_entries) {
73
0
    struct chdir_notify_entry *e =
74
0
      list_entry(pos, struct chdir_notify_entry, list);
75
0
    e->cb(e->name, old_cwd.buf, new_cwd, e->data);
76
0
  }
77
78
0
  strbuf_release(&old_cwd);
79
0
  return 0;
80
0
}
81
82
char *reparent_relative_path(const char *old_cwd,
83
           const char *new_cwd,
84
           const char *path)
85
0
{
86
0
  char *ret, *full;
87
88
0
  if (is_absolute_path(path))
89
0
    return xstrdup(path);
90
91
0
  full = xstrfmt("%s/%s", old_cwd, path);
92
0
  ret = xstrdup(remove_leading_path(full, new_cwd));
93
0
  free(full);
94
95
0
  return ret;
96
0
}