diff options
Diffstat (limited to 'sha1_file.c')
-rw-r--r-- | sha1_file.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/sha1_file.c b/sha1_file.c index 5457314e6a..1173071859 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -26,6 +26,7 @@ #include "mru.h" #include "list.h" #include "mergesort.h" +#include "quote.h" #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) @@ -296,7 +297,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, } strbuf_addstr(&pathbuf, entry); - if (strbuf_normalize_path(&pathbuf) < 0) { + if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) { error("unable to normalize alternate object path: %s", pathbuf.buf); strbuf_release(&pathbuf); @@ -329,13 +330,40 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base, return 0; } +static const char *parse_alt_odb_entry(const char *string, + int sep, + struct strbuf *out) +{ + const char *end; + + strbuf_reset(out); + + if (*string == '#') { + /* comment; consume up to next separator */ + end = strchrnul(string, sep); + } else if (*string == '"' && !unquote_c_style(out, string, &end)) { + /* + * quoted path; unquote_c_style has copied the + * data for us and set "end". Broken quoting (e.g., + * an entry that doesn't end with a quote) falls + * back to the unquoted case below. + */ + } else { + /* normal, unquoted path */ + end = strchrnul(string, sep); + strbuf_add(out, string, end - string); + } + + if (*end) + end++; + return end; +} + static void link_alt_odb_entries(const char *alt, int len, int sep, const char *relative_base, int depth) { - struct string_list entries = STRING_LIST_INIT_NODUP; - char *alt_copy; - int i; struct strbuf objdirbuf = STRBUF_INIT; + struct strbuf entry = STRBUF_INIT; if (depth > 5) { error("%s: ignoring alternate object stores, nesting too deep.", @@ -348,16 +376,13 @@ static void link_alt_odb_entries(const char *alt, int len, int sep, die("unable to normalize object directory: %s", objdirbuf.buf); - alt_copy = xmemdupz(alt, len); - string_list_split_in_place(&entries, alt_copy, sep, -1); - for (i = 0; i < entries.nr; i++) { - const char *entry = entries.items[i].string; - if (entry[0] == '\0' || entry[0] == '#') + while (*alt) { + alt = parse_alt_odb_entry(alt, sep, &entry); + if (!entry.len) continue; - link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf); + link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf); } - string_list_clear(&entries, 0); - free(alt_copy); + strbuf_release(&entry); strbuf_release(&objdirbuf); } |