You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
1.8 KiB
93 lines
1.8 KiB
#include "cache.h" |
|
#include "chdir-notify.h" |
|
#include "list.h" |
|
#include "strbuf.h" |
|
|
|
struct chdir_notify_entry { |
|
const char *name; |
|
chdir_notify_callback cb; |
|
void *data; |
|
struct list_head list; |
|
}; |
|
static LIST_HEAD(chdir_notify_entries); |
|
|
|
void chdir_notify_register(const char *name, |
|
chdir_notify_callback cb, |
|
void *data) |
|
{ |
|
struct chdir_notify_entry *e = xmalloc(sizeof(*e)); |
|
e->name = name; |
|
e->cb = cb; |
|
e->data = data; |
|
list_add_tail(&e->list, &chdir_notify_entries); |
|
} |
|
|
|
static void reparent_cb(const char *name, |
|
const char *old_cwd, |
|
const char *new_cwd, |
|
void *data) |
|
{ |
|
char **path = data; |
|
char *tmp = *path; |
|
|
|
if (!tmp) |
|
return; |
|
|
|
*path = reparent_relative_path(old_cwd, new_cwd, tmp); |
|
free(tmp); |
|
|
|
if (name) { |
|
trace_printf_key(&trace_setup_key, |
|
"setup: reparent %s to '%s'", |
|
name, *path); |
|
} |
|
} |
|
|
|
void chdir_notify_reparent(const char *name, char **path) |
|
{ |
|
chdir_notify_register(name, reparent_cb, path); |
|
} |
|
|
|
int chdir_notify(const char *new_cwd) |
|
{ |
|
struct strbuf old_cwd = STRBUF_INIT; |
|
struct list_head *pos; |
|
|
|
if (strbuf_getcwd(&old_cwd) < 0) |
|
return -1; |
|
if (chdir(new_cwd) < 0) { |
|
int saved_errno = errno; |
|
strbuf_release(&old_cwd); |
|
errno = saved_errno; |
|
return -1; |
|
} |
|
|
|
trace_printf_key(&trace_setup_key, |
|
"setup: chdir from '%s' to '%s'", |
|
old_cwd.buf, new_cwd); |
|
|
|
list_for_each(pos, &chdir_notify_entries) { |
|
struct chdir_notify_entry *e = |
|
list_entry(pos, struct chdir_notify_entry, list); |
|
e->cb(e->name, old_cwd.buf, new_cwd, e->data); |
|
} |
|
|
|
strbuf_release(&old_cwd); |
|
return 0; |
|
} |
|
|
|
char *reparent_relative_path(const char *old_cwd, |
|
const char *new_cwd, |
|
const char *path) |
|
{ |
|
char *ret, *full; |
|
|
|
if (is_absolute_path(path)) |
|
return xstrdup(path); |
|
|
|
full = xstrfmt("%s/%s", old_cwd, path); |
|
ret = xstrdup(remove_leading_path(full, new_cwd)); |
|
free(full); |
|
|
|
return ret; |
|
}
|
|
|