Skip to content

Commit 0ea68e4

Browse files
peffgitster
authored andcommitted
get_repo_path: refactor path-allocation
The get_repo_path function calls mkpath() and then does some non-trivial operations on it, like calling is_git_directory() and read_gitfile(). These are actually OK (they do not use more pathname static buffers themselves), but it takes a fair bit of work to verify. Let's use our own strbuf to store the path, and we can simply reuse it for each iteration of the loop (we can even avoid rewriting the beginning part, since we are trying a series of suffixes). To make the strbuf cleanup easier, we split out a thin wrapper. As a bonus, this wrapper can factor out the canonicalization that happens in all of the early-return code paths. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 03f2c77 commit 0ea68e4

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

builtin/clone.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,51 +99,66 @@ static const char *argv_submodule[] = {
9999
"submodule", "update", "--init", "--recursive", NULL
100100
};
101101

102-
static char *get_repo_path(const char *repo, int *is_bundle)
102+
static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
103103
{
104104
static char *suffix[] = { "/.git", "", ".git/.git", ".git" };
105105
static char *bundle_suffix[] = { ".bundle", "" };
106+
size_t baselen = path->len;
106107
struct stat st;
107108
int i;
108109

109110
for (i = 0; i < ARRAY_SIZE(suffix); i++) {
110-
const char *path;
111-
path = mkpath("%s%s", repo, suffix[i]);
112-
if (stat(path, &st))
111+
strbuf_setlen(path, baselen);
112+
strbuf_addstr(path, suffix[i]);
113+
if (stat(path->buf, &st))
113114
continue;
114-
if (S_ISDIR(st.st_mode) && is_git_directory(path)) {
115+
if (S_ISDIR(st.st_mode) && is_git_directory(path->buf)) {
115116
*is_bundle = 0;
116-
return xstrdup(absolute_path(path));
117+
return path->buf;
117118
} else if (S_ISREG(st.st_mode) && st.st_size > 8) {
118119
/* Is it a "gitfile"? */
119120
char signature[8];
120-
int len, fd = open(path, O_RDONLY);
121+
const char *dst;
122+
int len, fd = open(path->buf, O_RDONLY);
121123
if (fd < 0)
122124
continue;
123125
len = read_in_full(fd, signature, 8);
124126
close(fd);
125127
if (len != 8 || strncmp(signature, "gitdir: ", 8))
126128
continue;
127-
path = read_gitfile(path);
128-
if (path) {
129+
dst = read_gitfile(path->buf);
130+
if (dst) {
129131
*is_bundle = 0;
130-
return xstrdup(absolute_path(path));
132+
return dst;
131133
}
132134
}
133135
}
134136

135137
for (i = 0; i < ARRAY_SIZE(bundle_suffix); i++) {
136-
const char *path;
137-
path = mkpath("%s%s", repo, bundle_suffix[i]);
138-
if (!stat(path, &st) && S_ISREG(st.st_mode)) {
138+
strbuf_setlen(path, baselen);
139+
strbuf_addstr(path, bundle_suffix[i]);
140+
if (!stat(path->buf, &st) && S_ISREG(st.st_mode)) {
139141
*is_bundle = 1;
140-
return xstrdup(absolute_path(path));
142+
return path->buf;
141143
}
142144
}
143145

144146
return NULL;
145147
}
146148

149+
static char *get_repo_path(const char *repo, int *is_bundle)
150+
{
151+
struct strbuf path = STRBUF_INIT;
152+
const char *raw;
153+
char *canon;
154+
155+
strbuf_addstr(&path, repo);
156+
raw = get_repo_path_1(&path, is_bundle);
157+
canon = raw ? xstrdup(absolute_path(raw)) : NULL;
158+
strbuf_release(&path);
159+
return canon;
160+
}
161+
147162
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
148163
{
149164
const char *end = repo + strlen(repo), *start;

0 commit comments

Comments
 (0)