aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTharre <tharre3@gmail.com>2015-02-15 01:50:48 +0100
committerTharre <tharre3@gmail.com>2015-02-15 01:53:16 +0100
commit575dcfc9e15cfbd45339fe0e5cb4be6c637248d1 (patch)
tree3c16e5d3c38ded476323dcd596293aad68187c51 /src
parent6fe2d9cb44515c4db53686327086f2ae894cad60 (diff)
downloadredo-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.c4
-rw-r--r--src/filepath.c38
-rw-r--r--src/filepath.h2
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);