| 100 | } |
| 101 | |
| 102 | void parse_alternates(const char *string, |
| 103 | int sep, |
| 104 | const char *relative_base, |
| 105 | struct strvec *out) |
| 106 | { |
| 107 | struct strbuf pathbuf = STRBUF_INIT; |
| 108 | struct strbuf buf = STRBUF_INIT; |
| 109 | |
| 110 | if (!string || !*string) |
| 111 | return; |
| 112 | |
| 113 | while (*string) { |
| 114 | const char *end; |
| 115 | |
| 116 | strbuf_reset(&buf); |
| 117 | strbuf_reset(&pathbuf); |
| 118 | |
| 119 | if (*string == '#') { |
| 120 | /* comment; consume up to next separator */ |
| 121 | end = strchrnul(string, sep); |
| 122 | } else if (*string == '"' && !unquote_c_style(&buf, string, &end)) { |
| 123 | /* |
| 124 | * quoted path; unquote_c_style has copied the |
| 125 | * data for us and set "end". Broken quoting (e.g., |
| 126 | * an entry that doesn't end with a quote) falls |
| 127 | * back to the unquoted case below. |
| 128 | */ |
| 129 | } else { |
| 130 | /* normal, unquoted path */ |
| 131 | end = strchrnul(string, sep); |
| 132 | strbuf_add(&buf, string, end - string); |
| 133 | } |
| 134 | |
| 135 | if (*end) |
| 136 | end++; |
| 137 | string = end; |
| 138 | |
| 139 | if (!buf.len) |
| 140 | continue; |
| 141 | |
| 142 | if (!is_absolute_path(buf.buf) && relative_base) { |
| 143 | strbuf_realpath(&pathbuf, relative_base, 1); |
| 144 | strbuf_addch(&pathbuf, '/'); |
| 145 | } |
| 146 | strbuf_addbuf(&pathbuf, &buf); |
| 147 | |
| 148 | strbuf_reset(&buf); |
| 149 | if (!strbuf_realpath(&buf, pathbuf.buf, 0)) { |
| 150 | error(_("unable to normalize alternate object path: %s"), |
| 151 | pathbuf.buf); |
| 152 | continue; |
| 153 | } |
| 154 | |
| 155 | /* |
| 156 | * The trailing slash after the directory name is given by |
| 157 | * this function at the end. Remove duplicates. |
| 158 | */ |
| 159 | while (buf.len && buf.buf[buf.len - 1] == '/') |
no test coverage detected