Subject: Re: [PATCH] prune: keep files created after process start

From: Eric Wong <[email-masked]>
Date: Sun, 19 Jun 2016 08:48:37 +0000

Andreas Schwab <[email-masked]> wrote:
> Eric Wong <[email-masked]> writes:
> 
> > @@ -21,7 +22,7 @@ static int prune_tmp_file(const char *fullpath)
> >  	struct stat st;
> >  	if (lstat(fullpath, &st))
> >  		return error("Could not stat '%s'", fullpath);
> > -	if (st.st_mtime > expire)
> > +	if (st.st_mtime > expire || st.st_ctime >= start)
> 
> That will also mean objects created (or their inode changed) up to a
> second before the start of prune will not be removed.  For example,
> objects ejected out of a pack by a previous repack may be affected.

True, but I prefer to err on the side of keeping data rather than
removing it.   But keeping it can also be a liability (as it was
in my case :)  So, perhaps warn users instead:

diff --git a/builtin/prune.c b/builtin/prune.c
index d4cd054..c1642d1 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -16,14 +16,22 @@ static int verbose;
 static unsigned long expire;
 static time_t start;
 static int show_progress = -1;
+static unsigned long ctime_matches;
 
 static int prune_tmp_file(const char *fullpath)
 {
 	struct stat st;
 	if (lstat(fullpath, &st))
 		return error("Could not stat '%s'", fullpath);
-	if (st.st_mtime > expire || st.st_ctime >= start)
+	if (st.st_mtime > expire || st.st_ctime > start)
 		return 0;
+
+	if (st.st_ctime == start) {
+		ctime_matches++;
+		warning("Keeping %s since it changed as we started", fullpath);
+		return 0;
+	}
+
 	if (show_only || verbose)
 		printf("Removing stale temporary file %s\n", fullpath);
 	if (!show_only)
@@ -48,8 +56,13 @@ static int prune_object(const unsigned char *sha1, const char *fullpath,
 		error("Could not stat '%s'", fullpath);
 		return 0;
 	}
-	if (st.st_mtime > expire || st.st_ctime >= start)
+	if (st.st_mtime > expire || st.st_ctime > start)
 		return 0;
+	if (st.st_ctime == start) {
+		ctime_matches++;
+		warning("Keeping %s since it changed as we started", fullpath);
+		return 0;
+	}
 	if (show_only || verbose) {
 		enum object_type type = sha1_object_info(sha1, NULL);
 		printf("%s %s\n", sha1_to_hex(sha1),
@@ -155,5 +168,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 	if (is_repository_shallow())
 		prune_shallow(show_only);
 
+	if (ctime_matches) {
+		warning("%lu files kept since they changed as prune started",
+			ctime_matches);
+		warning("rerun prune after %s",
+			show_date(start, 0, DATE_MODE(NORMAL)));
+	}
+
 	return 0;
 }