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