generalize the pathset's path comparison function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
diff --git a/lib/got_lib_path.h b/lib/got_lib_path.h
index 46595f8..6f0f5dc 100644
--- a/lib/got_lib_path.h
+++ b/lib/got_lib_path.h
@@ -51,3 +51,9 @@ const struct got_error *got_path_skip_common_ancestor(char **, const char *,
/* Determine whether a path points to the root directory "/" . */
int got_path_is_root_dir(const char *);
+
+/*
+ * Like strcmp() but orders children in subdirectories directly after
+ * their parents.
+ */
+int got_compare_paths(const char *, const char *);
diff --git a/lib/path.c b/lib/path.c
index c78fdb2..a57cfde 100644
--- a/lib/path.c
+++ b/lib/path.c
@@ -25,6 +25,10 @@
#include "got_lib_path.h"
+#ifndef MIN
+#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
int
got_path_is_absolute(const char *path)
{
@@ -139,3 +143,33 @@ got_path_is_root_dir(const char *path)
{
return (path[0] == '/' && path[1] == '\0');
}
+
+int
+got_compare_paths(const char *path1, const char *path2)
+{
+ size_t len1 = strlen(path1);
+ size_t len2 = strlen(path2);
+ size_t min_len = MIN(len1, len2);
+ size_t i = 0;
+
+ /* Skip over common prefix. */
+ while (i < min_len && path1[i] == path2[i])
+ i++;
+
+ /* Are the paths exactly equal? */
+ if (len1 == len2 && i >= min_len)
+ return 0;
+
+ /* Order children in subdirectories directly after their parents. */
+ if (path1[i] == '/' && path2[i] == '\0')
+ return 1;
+ if (path2[i] == '/' && path1[i] == '\0')
+ return -1;
+ if (path1[i] == '/')
+ return -1;
+ if (path2[i] == '/')
+ return 1;
+
+ /* Next character following the common prefix determines order. */
+ return (unsigned char)path1[i] < (unsigned char)path2[i] ? -1 : 1;
+}
diff --git a/lib/pathset.c b/lib/pathset.c
index 9b12433..0332c19 100644
--- a/lib/pathset.c
+++ b/lib/pathset.c
@@ -22,12 +22,9 @@
#include <limits.h>
#include "got_error.h"
+#include "got_lib_path.h"
#include "got_lib_pathset.h"
-#ifndef MIN
-#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
-#endif
-
struct got_pathset_element {
RB_ENTRY(got_pathset_element) entry;
char *path;
@@ -40,31 +37,7 @@ static int
cmp_elements(const struct got_pathset_element *e1,
const struct got_pathset_element *e2)
{
- size_t len1 = strlen(e1->path);
- size_t len2 = strlen(e2->path);
- size_t min_len = MIN(len1, len2);
- size_t i = 0;
-
- /* Skip over common prefix. */
- while (i < min_len && e1->path[i] == e2->path[i])
- i++;
-
- /* Are the paths exactly equal? */
- if (len1 == len2 && i >= min_len)
- return 0;
-
- /* Order children in subdirectories directly after their parents. */
- if (e1->path[i] == '/' && e2->path[i] == '\0')
- return 1;
- if (e2->path[i] == '/' && e1->path[i] == '\0')
- return -1;
- if (e1->path[i] == '/')
- return -1;
- if (e2->path[i] == '/')
- return 1;
-
- /* Next character following the common prefix determines order. */
- return (unsigned char)e1->path[i] < (unsigned char)e2->path[i] ? -1 : 1;
+ return got_compare_paths(e1->path, e2->path);
}
RB_PROTOTYPE(got_pathset_tree, got_pathset_element, entry, cmp_elements);
diff --git a/regress/pathset/Makefile b/regress/pathset/Makefile
index 9727586..35b7f21 100644
--- a/regress/pathset/Makefile
+++ b/regress/pathset/Makefile
@@ -1,7 +1,7 @@
.PATH:${.CURDIR}/../../lib
PROG = pathset_test
-SRCS = error.c sha1.c pathset.c pathset_test.c
+SRCS = error.c sha1.c pathset.c path.c pathset_test.c
CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
LDADD =