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