#include "commit.h"
#include "refs.h"
#include "dir.h"
-#include <time.h>
+#include "tree-walk.h"
+
+static unsigned long default_reflog_expire;
+static unsigned long default_reflog_expire_unreachable;
struct expire_reflog_cb {
FILE *newlog;
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,
goto prune;
if ((timestamp < cb->expire_unreachable) &&
- ((old && !in_merge_bases(old, cb->ref_commit)) ||
+ (!cb->ref_commit ||
+ (old && !in_merge_bases(old, cb->ref_commit)) ||
(new && !in_merge_bases(new, cb->ref_commit))))
goto prune;
}
cb.ref_commit = lookup_commit_reference_gently(sha1, 1);
- if (!cb.ref_commit) {
- status = error("ref '%s' does not point at a commit", ref);
- goto finish;
- }
+ if (!cb.ref_commit)
+ fprintf(stderr,
+ "warning: ref '%s' does not point at a commit\n", ref);
cb.ref = ref;
cb.expire_total = cmd->expire_total;
cb.expire_unreachable = cmd->expire_unreachable;
return status;
}
+static int reflog_expire_config(const char *var, const char *value)
+{
+ if (!strcmp(var, "gc.reflogexpire"))
+ default_reflog_expire = approxidate(value);
+ else if (!strcmp(var, "gc.reflogexpireunreachable"))
+ default_reflog_expire_unreachable = approxidate(value);
+ else
+ return git_default_config(var, value);
+ return 0;
+}
+
static const char reflog_expire_usage[] =
"git-reflog expire [--dry-run] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
unsigned long now = time(NULL);
int i, status, do_all;
+ git_config(reflog_expire_config);
+
save_commit_buffer = 0;
do_all = status = 0;
memset(&cb, 0, sizeof(cb));
- cb.expire_total = now - 90 * 24 * 3600;
- cb.expire_unreachable = now - 30 * 24 * 3600;
+
+ if (!default_reflog_expire_unreachable)
+ default_reflog_expire_unreachable = now - 30 * 24 * 3600;
+ if (!default_reflog_expire)
+ default_reflog_expire = now - 90 * 24 * 3600;
+ cb.expire_total = default_reflog_expire;
+ cb.expire_unreachable = default_reflog_expire_unreachable;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];