summaryrefslogtreecommitdiff
path: root/builtin-reflog.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-12-22 08:46:33 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-12-22 08:46:33 (GMT)
commit8d8b9f6252271899708b32fbce4cd2541af9545a (patch)
tree003a47bd55cc900624402cee450d0922a446aec4 /builtin-reflog.c
parent71b03b42c637d884295b48d4f5d830a5f5f3578b (diff)
downloadgit-8d8b9f6252271899708b32fbce4cd2541af9545a.zip
git-8d8b9f6252271899708b32fbce4cd2541af9545a.tar.gz
git-8d8b9f6252271899708b32fbce4cd2541af9545a.tar.bz2
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 <junkio@cox.net>
Diffstat (limited to 'builtin-reflog.c')
-rw-r--r--builtin-reflog.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/builtin-reflog.c b/builtin-reflog.c
index d4f7353..4097c32 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -3,7 +3,7 @@
#include "commit.h"
#include "refs.h"
#include "dir.h"
-#include <time.h>
+#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,