From 8d8b9f6252271899708b32fbce4cd2541af9545a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 22 Dec 2006 00:46:33 -0800 Subject: reflog expire: prune commits that are not incomplete Older fsck-objects and prune did not protect commits in reflog entries, and it is quite possible that a commit still exists in the repository (because it was in a pack, or something) while some of its trees and blobs are long gone. Make sure the commit and its associated tree is complete and expire incomplete ones. Signed-off-by: Junio C Hamano --- builtin-reflog.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'builtin-reflog.c') diff --git a/builtin-reflog.c b/builtin-reflog.c index d4f73535c4..4097c328cc 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -3,7 +3,7 @@ #include "commit.h" #include "refs.h" #include "dir.h" -#include +#include "tree-walk.h" struct expire_reflog_cb { FILE *newlog; @@ -13,13 +13,50 @@ struct expire_reflog_cb { unsigned long expire_unreachable; }; +static int tree_is_complete(const unsigned char *sha1) +{ + struct tree_desc desc; + void *buf; + char type[20]; + + buf = read_sha1_file(sha1, type, &desc.size); + if (!buf) + return 0; + desc.buf = buf; + while (desc.size) { + const unsigned char *elem; + const char *name; + unsigned mode; + + elem = tree_entry_extract(&desc, &name, &mode); + if (!has_sha1_file(elem) || + (S_ISDIR(mode) && !tree_is_complete(elem))) { + free(buf); + return 0; + } + update_tree_entry(&desc); + } + free(buf); + return 1; +} + static int keep_entry(struct commit **it, unsigned char *sha1) { + struct commit *commit; + *it = NULL; if (is_null_sha1(sha1)) return 1; - *it = lookup_commit_reference_gently(sha1, 1); - return (*it != NULL); + commit = lookup_commit_reference_gently(sha1, 1); + if (!commit) + return 0; + + /* Make sure everything in this commit exists. */ + parse_object(commit->object.sha1); + if (!tree_is_complete(commit->tree->object.sha1)) + return 0; + *it = commit; + return 1; } static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1, -- cgit v1.2.3