odb: Fix loading ODB alternates Fixed an issue with the `strtokz implementation and added support for comments and relative paths in the alternates file.
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
diff --git a/src/odb.c b/src/odb.c
index 1f3848f..8953ec6 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -321,8 +321,7 @@ static int add_default_backends(git_odb *db, const char *objects_dir, int as_alt
static int load_alternates(git_odb *odb, const char *objects_dir)
{
char alternates_path[GIT_PATH_MAX];
- char alternate[GIT_PATH_MAX];
- char *buffer;
+ char *buffer, *alternate;
gitfo_buf alternates_buf = GITFO_BUF_INIT;
int error;
@@ -339,8 +338,21 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
error = GIT_SUCCESS;
/* add each alternate as a new backend; one alternate per line */
- while ((error == GIT_SUCCESS) && (buffer = git__strtok(alternate, buffer, "\r\n")) != NULL)
- error = add_default_backends(odb, alternate, 1);
+ while ((alternate = git__strtok(&buffer, "\r\n")) != NULL) {
+ char full_path[GIT_PATH_MAX];
+
+ if (*alternate == '\0' || *alternate == '#')
+ continue;
+
+ /* relative path: build based on the current `objects` folder */
+ if (*alternate == '.') {
+ git__joinpath(full_path, objects_dir, alternate);
+ alternate = full_path;
+ }
+
+ if ((error = add_default_backends(odb, alternate, 1)) < GIT_SUCCESS)
+ break;
+ }
gitfo_free_buf(&alternates_buf);
if (error < GIT_SUCCESS)
diff --git a/src/util.c b/src/util.c
index ebc1f43..560c40d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -337,27 +337,29 @@ void git__joinpath_n(char *buffer_out, int count, ...)
*buffer_out = '\0';
}
-static char *strtok_raw(char *output, char *src, char *delimit, int keep)
+char *git__strtok(char **end, const char *sep)
{
- while (*src && strchr(delimit, *src) == NULL)
- *output++ = *src++;
+ char *ptr = *end;
- *output = 0;
+ while (*ptr && strchr(sep, *ptr))
+ ++ptr;
- if (keep)
- return src;
- else
- return *src ? src+1 : src;
-}
+ if (*ptr) {
+ char *start = ptr;
+ *end = start + 1;
-char *git__strtok(char *output, char *src, char *delimit)
-{
- return strtok_raw(output, src, delimit, 0);
-}
+ while (**end && !strchr(sep, **end))
+ ++*end;
-char *git__strtok_keep(char *output, char *src, char *delimit)
-{
- return strtok_raw(output, src, delimit, 1);
+ if (**end) {
+ **end = '\0';
+ ++*end;
+ }
+
+ return start;
+ }
+
+ return NULL;
}
void git__hexdump(const char *buffer, size_t len)
diff --git a/src/util.h b/src/util.h
index e5a2ebe..72e3a9c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -139,8 +139,7 @@ GIT_INLINE(int) git__is_sizet(git_off_t p)
# define git__rotl(v, s) (uint32_t)(((uint32_t)(v) << (s)) | ((uint32_t)(v) >> (32 - (s))))
#endif
-extern char *git__strtok(char *output, char *src, char *delimit);
-extern char *git__strtok_keep(char *output, char *src, char *delimit);
+extern char *git__strtok(char **end, const char *sep);
extern void git__strntolower(char *str, int len);
extern void git__strtolower(char *str);