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