summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2014-07-29 20:50:26 +0700
committerJunio C Hamano <gitster@pobox.com>2014-07-29 13:42:13 -0700
commit38d2ab633180e183653d781e5787e2842000f09f (patch)
treebe9528f7fb093395271e833fc3be471f3acf2933
parent4f25b3169d44c9bc72cf173dc207d37649c16277 (diff)
downloadgit-38d2ab633180e183653d781e5787e2842000f09f.tar.gz
prune --repos: fix uninitialized access
There's a code path in prune_repo_dir() that does not initialize 'st' buffer, which is checked by the caller, prune_repos_dir(). Instead of leaking some prune logic out to prune_repos_dir(), move 'st' into prune_repo_dir(). Another bug that is fixed while at there is the "return 0" at the end of prune_repo_dir() instead of '1', meaning "keep the checkout" while we want "keep the checkout _unless_ its last update is older than expire limit". Set correct expire limit in the test as well. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/prune.c16
-rwxr-xr-xt/t2026-prune-linked-checkouts.sh2
2 files changed, 7 insertions, 11 deletions
diff --git a/builtin/prune.c b/builtin/prune.c
index 28b7adf911..e72c3917ef 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -112,8 +112,9 @@ static void prune_object_dir(const char *path)
}
}
-static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason)
+static int prune_repo_dir(const char *id, struct strbuf *reason)
{
+ struct stat st;
char *path;
int fd, len;
@@ -123,26 +124,23 @@ static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason
}
if (file_exists(git_path("repos/%s/locked", id)))
return 0;
- if (stat(git_path("repos/%s/gitdir", id), st)) {
- st->st_mtime = expire;
+ if (stat(git_path("repos/%s/gitdir", id), &st)) {
strbuf_addf(reason, _("Removing repos/%s: gitdir file does not exist"), id);
return 1;
}
fd = open(git_path("repos/%s/gitdir", id), O_RDONLY);
if (fd < 0) {
- st->st_mtime = expire;
strbuf_addf(reason, _("Removing repos/%s: unable to read gitdir file (%s)"),
id, strerror(errno));
return 1;
}
- len = st->st_size;
+ len = st.st_size;
path = xmalloc(len + 1);
read_in_full(fd, path, len);
close(fd);
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
len--;
if (!len) {
- st->st_mtime = expire;
strbuf_addf(reason, _("Removing repos/%s: invalid gitdir file"), id);
free(path);
return 1;
@@ -162,7 +160,7 @@ static int prune_repo_dir(const char *id, struct stat *st, struct strbuf *reason
return 1;
}
free(path);
- return 0;
+ return st.st_mtime <= expire;
}
static void prune_repos_dir(void)
@@ -172,15 +170,13 @@ static void prune_repos_dir(void)
DIR *dir = opendir(git_path("repos"));
struct dirent *d;
int ret;
- struct stat st;
if (!dir)
return;
while ((d = readdir(dir)) != NULL) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
strbuf_reset(&reason);
- if (!prune_repo_dir(d->d_name, &st, &reason) ||
- st.st_mtime > expire)
+ if (!prune_repo_dir(d->d_name, &reason))
continue;
if (show_only || verbose)
printf("%s\n", reason.buf);
diff --git a/t/t2026-prune-linked-checkouts.sh b/t/t2026-prune-linked-checkouts.sh
index 4ccfa4ee8a..79d84cba42 100755
--- a/t/t2026-prune-linked-checkouts.sh
+++ b/t/t2026-prune-linked-checkouts.sh
@@ -77,7 +77,7 @@ test_expect_success 'not prune recent checkouts' '
mkdir zz &&
mkdir -p .git/repos/jlm &&
echo "$TRASH_DIRECTORY"/zz >.git/repos/jlm/gitdir &&
- git prune --repos --verbose &&
+ git prune --repos --verbose --expire=2.days.ago &&
test -d .git/repos/jlm
'