Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 1 | #include "cache.h" |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 2 | #include "commit.h" |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 3 | #include "diff.h" |
| 4 | #include "revision.h" |
| 5 | #include "builtin.h" |
Junio C Hamano | 9442147 | 2007-01-06 02:16:17 -0800 | [diff] [blame] | 6 | #include "reachable.h" |
Michele Ballabio | 629de47 | 2008-03-23 21:50:29 +0100 | [diff] [blame] | 7 | #include "parse-options.h" |
Nguyễn Thái Ngọc Duy | dc34719 | 2011-11-05 19:00:08 +0700 | [diff] [blame] | 8 | #include "progress.h" |
Denton Liu | 9460fd4 | 2020-03-23 21:07:52 -0400 | [diff] [blame] | 9 | #include "prune-packed.h" |
Stefan Beller | cbd53a2 | 2018-05-15 16:42:15 -0700 | [diff] [blame] | 10 | #include "object-store.h" |
Taylor Blau | 120ad2b | 2020-04-30 13:48:50 -0600 | [diff] [blame] | 11 | #include "shallow.h" |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 12 | |
Michele Ballabio | 629de47 | 2008-03-23 21:50:29 +0100 | [diff] [blame] | 13 | static const char * const prune_usage[] = { |
Robert P. J. Day | 1a1fc2d | 2017-11-21 10:51:52 -0500 | [diff] [blame] | 14 | N_("git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"), |
Michele Ballabio | 629de47 | 2008-03-23 21:50:29 +0100 | [diff] [blame] | 15 | NULL |
| 16 | }; |
David Rientjes | 96f1e58 | 2006-08-15 10:23:48 -0700 | [diff] [blame] | 17 | static int show_only; |
Michael J Gruber | b35ddf4 | 2008-09-29 18:49:52 +0200 | [diff] [blame] | 18 | static int verbose; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 19 | static timestamp_t expire; |
Jeff King | bf0a59b | 2011-11-08 00:34:08 -0500 | [diff] [blame] | 20 | static int show_progress = -1; |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 21 | |
Jeff King | 4454e9c | 2013-12-17 18:22:31 -0500 | [diff] [blame] | 22 | static int prune_tmp_file(const char *fullpath) |
Brandon Casey | 0e8316c | 2008-07-24 17:41:12 -0500 | [diff] [blame] | 23 | { |
Adam Simpkins | cbf731e | 2010-02-26 19:50:02 -0800 | [diff] [blame] | 24 | struct stat st; |
| 25 | if (lstat(fullpath, &st)) |
| 26 | return error("Could not stat '%s'", fullpath); |
| 27 | if (st.st_mtime > expire) |
| 28 | return 0; |
Brandon Casey | 90b29cb | 2012-08-06 22:01:49 -0700 | [diff] [blame] | 29 | if (show_only || verbose) |
| 30 | printf("Removing stale temporary file %s\n", fullpath); |
Brandon Casey | 0e8316c | 2008-07-24 17:41:12 -0500 | [diff] [blame] | 31 | if (!show_only) |
Alex Riesen | 691f1a2 | 2009-04-29 23:22:56 +0200 | [diff] [blame] | 32 | unlink_or_warn(fullpath); |
Brandon Casey | 0e8316c | 2008-07-24 17:41:12 -0500 | [diff] [blame] | 33 | return 0; |
| 34 | } |
| 35 | |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 36 | static void perform_reachability_traversal(struct rev_info *revs) |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 37 | { |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 38 | static int initialized; |
| 39 | struct progress *progress = NULL; |
| 40 | |
| 41 | if (initialized) |
| 42 | return; |
| 43 | |
| 44 | if (show_progress) |
| 45 | progress = start_delayed_progress(_("Checking connectivity"), 0); |
| 46 | mark_reachable_objects(revs, 1, expire, progress); |
| 47 | stop_progress(&progress); |
| 48 | initialized = 1; |
| 49 | } |
| 50 | |
| 51 | static int is_object_reachable(const struct object_id *oid, |
| 52 | struct rev_info *revs) |
| 53 | { |
Jeff King | c2bf473 | 2019-02-13 23:38:21 -0500 | [diff] [blame] | 54 | struct object *obj; |
| 55 | |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 56 | perform_reachability_traversal(revs); |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 57 | |
Jeff King | d0229ab | 2019-06-20 03:41:14 -0400 | [diff] [blame] | 58 | obj = lookup_object(the_repository, oid); |
Jeff King | c2bf473 | 2019-02-13 23:38:21 -0500 | [diff] [blame] | 59 | return obj && (obj->flags & SEEN); |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | static int prune_object(const struct object_id *oid, const char *fullpath, |
| 63 | void *data) |
| 64 | { |
| 65 | struct rev_info *revs = data; |
| 66 | struct stat st; |
| 67 | |
| 68 | if (is_object_reachable(oid, revs)) |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 69 | return 0; |
| 70 | |
| 71 | if (lstat(fullpath, &st)) { |
| 72 | /* report errors, but do not stop pruning */ |
| 73 | error("Could not stat '%s'", fullpath); |
| 74 | return 0; |
| 75 | } |
Adam Simpkins | cbf731e | 2010-02-26 19:50:02 -0800 | [diff] [blame] | 76 | if (st.st_mtime > expire) |
| 77 | return 0; |
Michael J Gruber | b35ddf4 | 2008-09-29 18:49:52 +0200 | [diff] [blame] | 78 | if (show_only || verbose) { |
Stefan Beller | 0df8e96 | 2018-04-25 11:20:59 -0700 | [diff] [blame] | 79 | enum object_type type = oid_object_info(the_repository, oid, |
| 80 | NULL); |
brian m. carlson | 76c1d9a | 2017-02-21 23:47:35 +0000 | [diff] [blame] | 81 | printf("%s %s\n", oid_to_hex(oid), |
Brandon Williams | debca9d | 2018-02-14 10:59:24 -0800 | [diff] [blame] | 82 | (type > 0) ? type_name(type) : "unknown"); |
Michael J Gruber | b35ddf4 | 2008-09-29 18:49:52 +0200 | [diff] [blame] | 83 | } |
| 84 | if (!show_only) |
Alex Riesen | 691f1a2 | 2009-04-29 23:22:56 +0200 | [diff] [blame] | 85 | unlink_or_warn(fullpath); |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 86 | return 0; |
| 87 | } |
| 88 | |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 89 | static int prune_cruft(const char *basename, const char *path, void *data) |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 90 | { |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 91 | if (starts_with(basename, "tmp_obj_")) |
| 92 | prune_tmp_file(path); |
| 93 | else |
| 94 | fprintf(stderr, "bad sha1 file: %s\n", path); |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 95 | return 0; |
| 96 | } |
| 97 | |
René Scharfe | 70c4905 | 2017-06-24 16:09:39 +0200 | [diff] [blame] | 98 | static int prune_subdir(unsigned int nr, const char *path, void *data) |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 99 | { |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 100 | if (!show_only) |
| 101 | rmdir(path); |
| 102 | return 0; |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 103 | } |
| 104 | |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 105 | /* |
| 106 | * Write errors (particularly out of space) can result in |
| 107 | * failed temporary packs (and more rarely indexes and other |
Junio C Hamano | 9517e6b | 2010-02-03 21:23:18 -0800 | [diff] [blame] | 108 | * files beginning with "tmp_") accumulating in the object |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 109 | * and the pack directories. |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 110 | */ |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 111 | static void remove_temporary_files(const char *path) |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 112 | { |
| 113 | DIR *dir; |
| 114 | struct dirent *de; |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 115 | |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 116 | dir = opendir(path); |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 117 | if (!dir) { |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 118 | fprintf(stderr, "Unable to open directory %s\n", path); |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 119 | return; |
| 120 | } |
Brandon Casey | 0e8316c | 2008-07-24 17:41:12 -0500 | [diff] [blame] | 121 | while ((de = readdir(dir)) != NULL) |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 122 | if (starts_with(de->d_name, "tmp_")) |
Jeff King | 4454e9c | 2013-12-17 18:22:31 -0500 | [diff] [blame] | 123 | prune_tmp_file(mkpath("%s/%s", path, de->d_name)); |
David Steven Tweed | 8464010 | 2008-02-07 02:55:14 +0000 | [diff] [blame] | 124 | closedir(dir); |
| 125 | } |
| 126 | |
Linus Torvalds | a633fca | 2006-07-28 22:44:25 -0700 | [diff] [blame] | 127 | int cmd_prune(int argc, const char **argv, const char *prefix) |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 128 | { |
Junio C Hamano | 2430481 | 2007-01-06 02:16:10 -0800 | [diff] [blame] | 129 | struct rev_info revs; |
Jonathan Tan | 0c16cd4 | 2017-12-08 15:27:16 +0000 | [diff] [blame] | 130 | int exclude_promisor_objects = 0; |
Michele Ballabio | 629de47 | 2008-03-23 21:50:29 +0100 | [diff] [blame] | 131 | const struct option options[] = { |
Nguyễn Thái Ngọc Duy | 8f5b728 | 2012-08-20 19:32:32 +0700 | [diff] [blame] | 132 | OPT__DRY_RUN(&show_only, N_("do not remove, show only")), |
| 133 | OPT__VERBOSE(&verbose, N_("report pruned objects")), |
| 134 | OPT_BOOL(0, "progress", &show_progress, N_("show progress")), |
Junio C Hamano | 27ec394 | 2013-04-25 11:13:49 -0700 | [diff] [blame] | 135 | OPT_EXPIRY_DATE(0, "expire", &expire, |
| 136 | N_("expire objects older than <time>")), |
Jonathan Tan | 0c16cd4 | 2017-12-08 15:27:16 +0000 | [diff] [blame] | 137 | OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects, |
| 138 | N_("limit traversal to objects outside promisor packfiles")), |
Michele Ballabio | 629de47 | 2008-03-23 21:50:29 +0100 | [diff] [blame] | 139 | OPT_END() |
| 140 | }; |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 141 | char *s; |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 142 | |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 143 | expire = TIME_MAX; |
Junio C Hamano | 16157b8 | 2007-01-05 13:31:43 -0800 | [diff] [blame] | 144 | save_commit_buffer = 0; |
Jeff King | 6ebd1ca | 2018-07-18 16:45:20 -0400 | [diff] [blame] | 145 | read_replace_refs = 0; |
Jeff King | ff4056b | 2015-03-20 14:43:09 -0400 | [diff] [blame] | 146 | ref_paranoia = 1; |
Nguyễn Thái Ngọc Duy | 2abf350 | 2018-09-21 17:57:38 +0200 | [diff] [blame] | 147 | repo_init_revisions(the_repository, &revs, prefix); |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 148 | |
Stephen Boyd | 3778292 | 2009-05-23 11:53:12 -0700 | [diff] [blame] | 149 | argc = parse_options(argc, argv, prefix, options, prune_usage, 0); |
Nguyễn Thái Ngọc Duy | 23af91d | 2014-11-30 15:24:48 +0700 | [diff] [blame] | 150 | |
Jeff King | 067fbd4 | 2015-06-23 06:54:11 -0400 | [diff] [blame] | 151 | if (repository_format_precious_objects) |
| 152 | die(_("cannot prune in a precious-objects repo")); |
| 153 | |
Junio C Hamano | fe308f5 | 2008-03-24 23:20:51 -0700 | [diff] [blame] | 154 | while (argc--) { |
brian m. carlson | af6730e | 2017-05-01 02:28:58 +0000 | [diff] [blame] | 155 | struct object_id oid; |
Junio C Hamano | fe308f5 | 2008-03-24 23:20:51 -0700 | [diff] [blame] | 156 | const char *name = *argv++; |
| 157 | |
brian m. carlson | af6730e | 2017-05-01 02:28:58 +0000 | [diff] [blame] | 158 | if (!get_oid(name, &oid)) { |
brian m. carlson | c251c83 | 2017-05-06 22:10:38 +0000 | [diff] [blame] | 159 | struct object *object = parse_object_or_die(&oid, |
| 160 | name); |
Junio C Hamano | fe308f5 | 2008-03-24 23:20:51 -0700 | [diff] [blame] | 161 | add_pending_object(&revs, object, ""); |
| 162 | } |
| 163 | else |
| 164 | die("unrecognized argument: %s", name); |
| 165 | } |
Jeff King | bf0a59b | 2011-11-08 00:34:08 -0500 | [diff] [blame] | 166 | |
| 167 | if (show_progress == -1) |
| 168 | show_progress = isatty(2); |
Jonathan Tan | 0c16cd4 | 2017-12-08 15:27:16 +0000 | [diff] [blame] | 169 | if (exclude_promisor_objects) { |
| 170 | fetch_if_missing = 0; |
| 171 | revs.exclude_promisor_objects = 1; |
| 172 | } |
Jeff King | bf0a59b | 2011-11-08 00:34:08 -0500 | [diff] [blame] | 173 | |
Jeff King | 27e1e22 | 2014-10-15 18:38:55 -0400 | [diff] [blame] | 174 | for_each_loose_file_in_objdir(get_object_directory(), prune_object, |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 175 | prune_cruft, prune_subdir, &revs); |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 176 | |
Nguyễn Thái Ngọc Duy | af0b4a3 | 2013-05-27 18:18:47 +0700 | [diff] [blame] | 177 | prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0); |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 178 | remove_temporary_files(get_object_directory()); |
Ramsay Jones | 4e2d094 | 2012-09-04 18:31:14 +0100 | [diff] [blame] | 179 | s = mkpathdup("%s/pack", get_object_directory()); |
Brandon Casey | db87e39 | 2008-09-22 18:34:26 -0500 | [diff] [blame] | 180 | remove_temporary_files(s); |
| 181 | free(s); |
Nguyễn Thái Ngọc Duy | eab3296 | 2013-12-05 20:02:54 +0700 | [diff] [blame] | 182 | |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 183 | if (is_repository_shallow(the_repository)) { |
| 184 | perform_reachability_traversal(&revs); |
Johannes Schindelin | 2588f6e | 2018-10-24 08:56:12 -0700 | [diff] [blame] | 185 | prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0); |
Jeff King | d55a30b | 2019-02-13 23:35:22 -0500 | [diff] [blame] | 186 | } |
Nguyễn Thái Ngọc Duy | eab3296 | 2013-12-05 20:02:54 +0700 | [diff] [blame] | 187 | |
Linus Torvalds | ba84a79 | 2006-07-06 10:16:22 -0700 | [diff] [blame] | 188 | return 0; |
| 189 | } |