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 <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Aug 10, 2015 at 05:37 UTC
0ea68e429647cc5400fe8fa257056083b0a6459d
1 file changed
+29
-14
builtin/clone.c
+29
-14
@@ -99,51 +99,66 @@ static const char *argv_submodule[] = {
99
"submodule", "update", "--init", "--recursive", NULL
100
};
101
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)
103
{
104
static char *suffix[] = { "/.git", "", ".git/.git", ".git" };
105
static char *bundle_suffix[] = { ".bundle", "" };
106
+ size_t baselen = path->len;
107
struct stat st;
108
int i;
109
110
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))
114
continue;
114
- if (S_ISDIR(st.st_mode) && is_git_directory(path)) {
115
+ if (S_ISDIR(st.st_mode) && is_git_directory(path->buf)) {
116
*is_bundle = 0;
116
- return xstrdup(absolute_path(path));
117
+ return path->buf;
118
} else if (S_ISREG(st.st_mode) && st.st_size > 8) {
119
/* Is it a "gitfile"? */
120
char signature[8];
120
- int len, fd = open(path, O_RDONLY);
121
+ const char *dst;
122
+ int len, fd = open(path->buf, O_RDONLY);
123
if (fd < 0)
124
continue;
125
len = read_in_full(fd, signature, 8);
126
close(fd);
127
if (len != 8 || strncmp(signature, "gitdir: ", 8))
128
continue;
127
- path = read_gitfile(path);
128
- if (path) {
129
+ dst = read_gitfile(path->buf);
130
+ if (dst) {
131
*is_bundle = 0;
130
- return xstrdup(absolute_path(path));
132
+ return dst;
133
}
134
}
135
}
136
137
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)) {
141
*is_bundle = 1;
140
- return xstrdup(absolute_path(path));
142
+ return path->buf;
143
}
144
}
145
146
return NULL;
147
}
148
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
+
162
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
163
{
164
const char *end = repo + strlen(repo), *start;