Make git prune remove temporary packs that look like write failures Write errors when repacking (eg, due to out-of-space conditions) can leave temporary packs lying around which no existing codepath removes and which aren't obvious to the casual user. Unfortunately the only way to tell in builtin-prune that a tmp_pack file is of this sort is that it hasn't been modified recently. We assume a pack which hasn't been modified within 10 minutes is of this sort and delete it, printing a notification to help debugging. (Nicolas Pitre suggested this functionality should be activated only by --prune.) Signed-off-by: David Tweed (david.tweed@xxxxxxxxx) --- I KNOW this initial RFC is mailer whitespace damaged. Finally version won't be. In principle this is a really trivial patch, but I'm being cautious because I don't like the fact that I don't know (and AFAICS can't reliably check) that the files being deleting are definitely dead. An alternative would be to make prune just print out that the suspicious packs are there and let the user delete them manually. (My itch is that once a write-failure pack gets created, nothing in git operations tells the user that a generally multimegabyte file hidden in .git occupying space.) builtin-prune.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/builtin-prune.c b/builtin-prune.c index b5e7684..90111ab 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -83,6 +83,39 @@ static void prune_object_dir(const char *path) } } +/* + * Write errors (particularly out of space) can result in + * failed temporary packs accumulating in the object directory. + * This removes anything in the object directory beginning + * with tmp_ using the heuristic that anything + * that was last modified more than 10 minutes + * ago is the abandoned result of a write failure. + */ +static void remove_temporary_files(void) +{ + DIR *dir; + struct stat status; + time_t now; + struct dirent *de; + char* dirname=get_object_directory(); + + now = time(NULL); + dir = opendir(dirname); + while ((de = readdir(dir)) != NULL) { + if(strncmp(de->d_name, "tmp_", 4) == 0){ + char name[4096]; + int c=snprintf(name, 4095, "%s/%s", dirname, de->d_name); + if(c>0 && c<4096 && stat(name, &status) == 0 + && status.st_mtime < now - 600){ + printf("Removing apparently abandoned %s\n",name); + unlink(name); + } + } + } + closedir(dir); +} + + int cmd_prune(int argc, const char **argv, const char *prefix) { int i; @@ -115,5 +148,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix) sync(); prune_packed_objects(show_only); + remove_temporary_files(); return 0; } - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html