diff options
author | Tharre <tharre3@gmail.com> | 2015-02-15 01:50:48 +0100 |
---|---|---|
committer | Tharre <tharre3@gmail.com> | 2015-02-15 01:53:16 +0100 |
commit | 575dcfc9e15cfbd45339fe0e5cb4be6c637248d1 (patch) | |
tree | 3c16e5d3c38ded476323dcd596293aad68187c51 /src | |
parent | 6fe2d9cb44515c4db53686327086f2ae894cad60 (diff) | |
download | redo-575dcfc9e15cfbd45339fe0e5cb4be6c637248d1.tar.gz redo-575dcfc9e15cfbd45339fe0e5cb4be6c637248d1.tar.xz redo-575dcfc9e15cfbd45339fe0e5cb4be6c637248d1.zip |
Replace make_relative() with relpath()
Also improve the documentation for this function, and add a few
examples to clarify what it does (and what not).
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 4 | ||||
-rw-r--r-- | src/filepath.c | 38 | ||||
-rw-r--r-- | src/filepath.h | 2 |
3 files changed, 25 insertions, 19 deletions
diff --git a/src/build.c b/src/build.c index c1dd602..71f10f9 100644 --- a/src/build.c +++ b/src/build.c @@ -322,9 +322,9 @@ static char *get_relpath(const char *target) { if (!abstarget) fatal("redo: failed to get realpath() of %s", target); - char *relpath = xstrdup(make_relative(root, abstarget)); + char *path = xstrdup(relpath(abstarget, root)); free(abstarget); - return relpath; + return path; } /* Return the dependency file path of target. */ diff --git a/src/filepath.c b/src/filepath.c index d0b68de..e4d8e62 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -53,27 +53,33 @@ char *take_extension(const char *target) { return ""; } -/* Make one path relative to another i.e. some/path to some/path/a/b/c would - yield a/b/c as result. Prints '.' if the 2 paths match. */ -// TODO: nameing, requires absolute paths, doesn't MALLOC -const char *make_relative(const char *target, const char *to) { +/* Returns a pointer to a relative path to `path` from `start`. This pointer may + be pointing to either of it's arguments, or to the statically allocated + string "." should both paths match. Both paths must be canonicalized. + A few examples: + relpath("/abc/de", "/abc/de") => "." + relpath("some/path/a/b/c", "some/path") => "a/b/c" + relpath("some/path", "some/path/a/b/c") => "some/path/a/b/c" + relpath("/", "/") => "." + relpath("/abc", "/") => "abc" + */ +char *relpath(char *path, char *start) { int i; - for (i = 0; target[i] && to[i]; ++i) - if (target[i] != to[i]) { - /* the paths do not match */ - return to; - } - - if (!target[i] && !to[i]) { - /* both paths match completely */ - return "."; + for (i = 0; path[i] && start[i]; ++i) { + if (path[i] != start[i]) + return path; /* paths share nothing */ } - /* skip any leading seperators */ - while (to[i] == '/') + if (!path[i] && start[i]) + return start; /* path is above start */ + + if (!path[i] && !start[i]) + return "."; /* paths match completely */ + + if (path[i] == '/') ++i; - return &to[i]; + return &path[i]; } /* Transforms target into a safe filename, replacing all '/' with '!'. */ diff --git a/src/filepath.h b/src/filepath.h index 3eb68ba..68a4ecf 100644 --- a/src/filepath.h +++ b/src/filepath.h @@ -14,7 +14,7 @@ extern bool is_absolute(const char* path); extern char *remove_ext(const char *str); extern char *take_extension(const char *target); -extern const char *make_relative(const char *target, const char *to); +extern char *relpath(char *path, char *start); extern char *transform_path(const char *target); extern char *xbasename(const char *path); extern bool fexists(const char *target); |