Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 1 | #include "builtin.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 2 | #include "config.h" |
Michael Haggerty | 697cc8e | 2014-10-01 12:28:42 +0200 | [diff] [blame] | 3 | #include "lockfile.h" |
Stefan Beller | cbd53a2 | 2018-05-15 16:42:15 -0700 | [diff] [blame] | 4 | #include "object-store.h" |
Stefan Beller | 109cd76 | 2018-06-28 18:21:51 -0700 | [diff] [blame] | 5 | #include "repository.h" |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 6 | #include "commit.h" |
| 7 | #include "refs.h" |
| 8 | #include "dir.h" |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 9 | #include "tree-walk.h" |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 10 | #include "diff.h" |
| 11 | #include "revision.h" |
| 12 | #include "reachable.h" |
| 13 | |
Michael Haggerty | fe2a181 | 2015-03-03 12:43:15 +0100 | [diff] [blame] | 14 | /* NEEDSWORK: switch to using parse_options */ |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 15 | static const char reflog_expire_usage[] = |
Michael Haggerty | fe2a181 | 2015-03-03 12:43:15 +0100 | [diff] [blame] | 16 | "git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>..."; |
Brandon Casey | 3c386aa | 2008-02-22 15:08:59 -0600 | [diff] [blame] | 17 | static const char reflog_delete_usage[] = |
Michael Haggerty | fe2a181 | 2015-03-03 12:43:15 +0100 | [diff] [blame] | 18 | "git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>..."; |
David Turner | afcb2e7 | 2015-07-21 17:04:53 -0400 | [diff] [blame] | 19 | static const char reflog_exists_usage[] = |
| 20 | "git reflog exists <ref>"; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 21 | |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 22 | static timestamp_t default_reflog_expire; |
| 23 | static timestamp_t default_reflog_expire_unreachable; |
Junio C Hamano | 4aec56d | 2006-12-27 01:47:57 -0800 | [diff] [blame] | 24 | |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 25 | struct cmd_reflog_expire_cb { |
| 26 | struct rev_info revs; |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 27 | int stalefix; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 28 | timestamp_t expire_total; |
| 29 | timestamp_t expire_unreachable; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 30 | int recno; |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 31 | }; |
| 32 | |
Michael Haggerty | ea7b4f6 | 2014-12-12 09:56:52 +0100 | [diff] [blame] | 33 | struct expire_reflog_policy_cb { |
Junio C Hamano | 03cb91b | 2010-04-09 13:20:02 -0700 | [diff] [blame] | 34 | enum { |
| 35 | UE_NORMAL, |
| 36 | UE_ALWAYS, |
| 37 | UE_HEAD |
| 38 | } unreachable_expire_kind; |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 39 | struct commit_list *mark_list; |
| 40 | unsigned long mark_limit; |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 41 | struct cmd_reflog_expire_cb cmd; |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 42 | struct commit *tip_commit; |
| 43 | struct commit_list *tips; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 44 | }; |
| 45 | |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 46 | struct collected_reflog { |
brian m. carlson | b8acac5 | 2017-10-15 22:06:58 +0000 | [diff] [blame] | 47 | struct object_id oid; |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 48 | char reflog[FLEX_ARRAY]; |
| 49 | }; |
Michael Haggerty | ddd64c5 | 2014-12-12 09:56:53 +0100 | [diff] [blame] | 50 | |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 51 | struct collect_reflog_cb { |
| 52 | struct collected_reflog **e; |
| 53 | int alloc; |
| 54 | int nr; |
| 55 | }; |
| 56 | |
Nguyễn Thái Ngọc Duy | 95308d6 | 2018-03-06 17:16:14 +0700 | [diff] [blame] | 57 | /* Remember to update object flag allocation in object.h */ |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 58 | #define INCOMPLETE (1u<<10) |
| 59 | #define STUDYING (1u<<11) |
Junio Hamano | 494fbfe | 2009-03-30 21:34:14 -0700 | [diff] [blame] | 60 | #define REACHABLE (1u<<12) |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 61 | |
brian m. carlson | 49a09e7 | 2017-05-06 22:10:16 +0000 | [diff] [blame] | 62 | static int tree_is_complete(const struct object_id *oid) |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 63 | { |
| 64 | struct tree_desc desc; |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 65 | struct name_entry entry; |
| 66 | int complete; |
| 67 | struct tree *tree; |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 68 | |
Stefan Beller | f86bcc7 | 2018-06-28 18:21:56 -0700 | [diff] [blame] | 69 | tree = lookup_tree(the_repository, oid); |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 70 | if (!tree) |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 71 | return 0; |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 72 | if (tree->object.flags & SEEN) |
| 73 | return 1; |
| 74 | if (tree->object.flags & INCOMPLETE) |
| 75 | return 0; |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 76 | |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 77 | if (!tree->buffer) { |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 78 | enum object_type type; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 79 | unsigned long size; |
brian m. carlson | b4f5aca | 2018-03-12 02:27:53 +0000 | [diff] [blame] | 80 | void *data = read_object_file(oid, &type, &size); |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 81 | if (!data) { |
| 82 | tree->object.flags |= INCOMPLETE; |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 83 | return 0; |
| 84 | } |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 85 | tree->buffer = data; |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 86 | tree->size = size; |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 87 | } |
Linus Torvalds | 6fda5e5 | 2007-03-21 10:08:25 -0700 | [diff] [blame] | 88 | init_tree_desc(&desc, tree->buffer, tree->size); |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 89 | complete = 1; |
| 90 | while (tree_entry(&desc, &entry)) { |
brian m. carlson | 7d924c9 | 2016-04-17 23:10:39 +0000 | [diff] [blame] | 91 | if (!has_sha1_file(entry.oid->hash) || |
brian m. carlson | 49a09e7 | 2017-05-06 22:10:16 +0000 | [diff] [blame] | 92 | (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid))) { |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 93 | tree->object.flags |= INCOMPLETE; |
| 94 | complete = 0; |
| 95 | } |
| 96 | } |
Jeff King | 6e454b9 | 2013-06-05 18:37:39 -0400 | [diff] [blame] | 97 | free_tree_buffer(tree); |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 98 | |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 99 | if (complete) |
| 100 | tree->object.flags |= SEEN; |
| 101 | return complete; |
| 102 | } |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 103 | |
| 104 | static int commit_is_complete(struct commit *commit) |
| 105 | { |
| 106 | struct object_array study; |
| 107 | struct object_array found; |
| 108 | int is_incomplete = 0; |
| 109 | int i; |
| 110 | |
| 111 | /* early return */ |
| 112 | if (commit->object.flags & SEEN) |
| 113 | return 1; |
| 114 | if (commit->object.flags & INCOMPLETE) |
| 115 | return 0; |
| 116 | /* |
| 117 | * Find all commits that are reachable and are not marked as |
| 118 | * SEEN. Then make sure the trees and blobs contained are |
| 119 | * complete. After that, mark these commits also as SEEN. |
| 120 | * If some of the objects that are needed to complete this |
| 121 | * commit are missing, mark this commit as INCOMPLETE. |
| 122 | */ |
| 123 | memset(&study, 0, sizeof(study)); |
| 124 | memset(&found, 0, sizeof(found)); |
| 125 | add_object_array(&commit->object, NULL, &study); |
| 126 | add_object_array(&commit->object, NULL, &found); |
| 127 | commit->object.flags |= STUDYING; |
| 128 | while (study.nr) { |
| 129 | struct commit *c; |
| 130 | struct commit_list *parent; |
| 131 | |
Martin Ågren | 7199203 | 2017-09-23 01:34:53 +0200 | [diff] [blame] | 132 | c = (struct commit *)object_array_pop(&study); |
Stefan Beller | 109cd76 | 2018-06-28 18:21:51 -0700 | [diff] [blame] | 133 | if (!c->object.parsed && !parse_object(the_repository, &c->object.oid)) |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 134 | c->object.flags |= INCOMPLETE; |
| 135 | |
| 136 | if (c->object.flags & INCOMPLETE) { |
| 137 | is_incomplete = 1; |
| 138 | break; |
| 139 | } |
| 140 | else if (c->object.flags & SEEN) |
| 141 | continue; |
| 142 | for (parent = c->parents; parent; parent = parent->next) { |
| 143 | struct commit *p = parent->item; |
| 144 | if (p->object.flags & STUDYING) |
| 145 | continue; |
| 146 | p->object.flags |= STUDYING; |
| 147 | add_object_array(&p->object, NULL, &study); |
| 148 | add_object_array(&p->object, NULL, &found); |
| 149 | } |
| 150 | } |
| 151 | if (!is_incomplete) { |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 152 | /* |
| 153 | * make sure all commits in "found" array have all the |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 154 | * necessary objects. |
| 155 | */ |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 156 | for (i = 0; i < found.nr; i++) { |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 157 | struct commit *c = |
| 158 | (struct commit *)found.objects[i].item; |
Derrick Stolee | 2e27bd7 | 2018-04-06 19:09:38 +0000 | [diff] [blame] | 159 | if (!tree_is_complete(get_commit_tree_oid(c))) { |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 160 | is_incomplete = 1; |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 161 | c->object.flags |= INCOMPLETE; |
| 162 | } |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 163 | } |
| 164 | if (!is_incomplete) { |
| 165 | /* mark all found commits as complete, iow SEEN */ |
| 166 | for (i = 0; i < found.nr; i++) |
| 167 | found.objects[i].item->flags |= SEEN; |
| 168 | } |
| 169 | } |
| 170 | /* clear flags from the objects we traversed */ |
| 171 | for (i = 0; i < found.nr; i++) |
| 172 | found.objects[i].item->flags &= ~STUDYING; |
| 173 | if (is_incomplete) |
| 174 | commit->object.flags |= INCOMPLETE; |
Junio C Hamano | cd1f9c3 | 2007-01-06 22:32:41 -0800 | [diff] [blame] | 175 | else { |
| 176 | /* |
| 177 | * If we come here, we have (1) traversed the ancestry chain |
| 178 | * from the "commit" until we reach SEEN commits (which are |
| 179 | * known to be complete), and (2) made sure that the commits |
| 180 | * encountered during the above traversal refer to trees that |
| 181 | * are complete. Which means that we know *all* the commits |
| 182 | * we have seen during this process are complete. |
| 183 | */ |
| 184 | for (i = 0; i < found.nr; i++) |
| 185 | found.objects[i].item->flags |= SEEN; |
| 186 | } |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 187 | /* free object arrays */ |
Martin Ågren | dcb572a | 2017-09-23 01:34:52 +0200 | [diff] [blame] | 188 | object_array_clear(&study); |
| 189 | object_array_clear(&found); |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 190 | return !is_incomplete; |
| 191 | } |
| 192 | |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 193 | static int keep_entry(struct commit **it, struct object_id *oid) |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 194 | { |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 195 | struct commit *commit; |
| 196 | |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 197 | if (is_null_oid(oid)) |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 198 | return 1; |
Stefan Beller | 21e1ee8 | 2018-06-28 18:21:57 -0700 | [diff] [blame] | 199 | commit = lookup_commit_reference_gently(the_repository, oid, 1); |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 200 | if (!commit) |
| 201 | return 0; |
| 202 | |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 203 | /* |
| 204 | * Make sure everything in this commit exists. |
| 205 | * |
| 206 | * We have walked all the objects reachable from the refs |
| 207 | * and cache earlier. The commits reachable by this commit |
| 208 | * must meet SEEN commits -- and then we should mark them as |
| 209 | * SEEN as well. |
| 210 | */ |
| 211 | if (!commit_is_complete(commit)) |
Junio C Hamano | 8d8b9f6 | 2006-12-22 00:46:33 -0800 | [diff] [blame] | 212 | return 0; |
| 213 | *it = commit; |
| 214 | return 1; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 215 | } |
| 216 | |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 217 | /* |
| 218 | * Starting from commits in the cb->mark_list, mark commits that are |
| 219 | * reachable from them. Stop the traversal at commits older than |
| 220 | * the expire_limit and queue them back, so that the caller can call |
| 221 | * us again to restart the traversal with longer expire_limit. |
| 222 | */ |
Michael Haggerty | ea7b4f6 | 2014-12-12 09:56:52 +0100 | [diff] [blame] | 223 | static void mark_reachable(struct expire_reflog_policy_cb *cb) |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 224 | { |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 225 | struct commit_list *pending; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 226 | timestamp_t expire_limit = cb->mark_limit; |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 227 | struct commit_list *leftover = NULL; |
| 228 | |
| 229 | for (pending = cb->mark_list; pending; pending = pending->next) |
| 230 | pending->item->object.flags &= ~REACHABLE; |
| 231 | |
| 232 | pending = cb->mark_list; |
| 233 | while (pending) { |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 234 | struct commit_list *parent; |
René Scharfe | e510ab8 | 2015-10-24 18:21:31 +0200 | [diff] [blame] | 235 | struct commit *commit = pop_commit(&pending); |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 236 | if (commit->object.flags & REACHABLE) |
| 237 | continue; |
| 238 | if (parse_commit(commit)) |
| 239 | continue; |
| 240 | commit->object.flags |= REACHABLE; |
| 241 | if (commit->date < expire_limit) { |
| 242 | commit_list_insert(commit, &leftover); |
| 243 | continue; |
| 244 | } |
| 245 | commit->object.flags |= REACHABLE; |
| 246 | parent = commit->parents; |
| 247 | while (parent) { |
| 248 | commit = parent->item; |
| 249 | parent = parent->next; |
| 250 | if (commit->object.flags & REACHABLE) |
| 251 | continue; |
| 252 | commit_list_insert(commit, &pending); |
| 253 | } |
| 254 | } |
| 255 | cb->mark_list = leftover; |
| 256 | } |
| 257 | |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 258 | static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid) |
Linus Torvalds | 666e07e | 2009-03-31 09:45:22 -0700 | [diff] [blame] | 259 | { |
| 260 | /* |
| 261 | * We may or may not have the commit yet - if not, look it |
| 262 | * up using the supplied sha1. |
| 263 | */ |
| 264 | if (!commit) { |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 265 | if (is_null_oid(oid)) |
Linus Torvalds | 666e07e | 2009-03-31 09:45:22 -0700 | [diff] [blame] | 266 | return 0; |
| 267 | |
Stefan Beller | 21e1ee8 | 2018-06-28 18:21:57 -0700 | [diff] [blame] | 268 | commit = lookup_commit_reference_gently(the_repository, oid, |
| 269 | 1); |
Linus Torvalds | 666e07e | 2009-03-31 09:45:22 -0700 | [diff] [blame] | 270 | |
| 271 | /* Not a commit -- keep it */ |
| 272 | if (!commit) |
| 273 | return 0; |
| 274 | } |
| 275 | |
| 276 | /* Reachable from the current ref? Don't prune. */ |
Junio Hamano | 494fbfe | 2009-03-30 21:34:14 -0700 | [diff] [blame] | 277 | if (commit->object.flags & REACHABLE) |
| 278 | return 0; |
Linus Torvalds | 666e07e | 2009-03-31 09:45:22 -0700 | [diff] [blame] | 279 | |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 280 | if (cb->mark_list && cb->mark_limit) { |
| 281 | cb->mark_limit = 0; /* dig down to the root */ |
| 282 | mark_reachable(cb); |
Junio Hamano | 494fbfe | 2009-03-30 21:34:14 -0700 | [diff] [blame] | 283 | } |
Junio C Hamano | b4ca1db | 2010-04-07 11:09:12 -0700 | [diff] [blame] | 284 | |
| 285 | return !(commit->object.flags & REACHABLE); |
Junio Hamano | 494fbfe | 2009-03-30 21:34:14 -0700 | [diff] [blame] | 286 | } |
| 287 | |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 288 | /* |
| 289 | * Return true iff the specified reflog entry should be expired. |
| 290 | */ |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 291 | static int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 292 | const char *email, timestamp_t timestamp, int tz, |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 293 | const char *message, void *cb_data) |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 294 | { |
Michael Haggerty | ea7b4f6 | 2014-12-12 09:56:52 +0100 | [diff] [blame] | 295 | struct expire_reflog_policy_cb *cb = cb_data; |
Brandon Williams | dfa5990 | 2018-02-14 10:59:34 -0800 | [diff] [blame] | 296 | struct commit *old_commit, *new_commit; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 297 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 298 | if (timestamp < cb->cmd.expire_total) |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 299 | return 1; |
Brandon Casey | 2b81fab | 2008-02-22 12:56:50 -0600 | [diff] [blame] | 300 | |
Brandon Williams | dfa5990 | 2018-02-14 10:59:34 -0800 | [diff] [blame] | 301 | old_commit = new_commit = NULL; |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 302 | if (cb->cmd.stalefix && |
Brandon Williams | dfa5990 | 2018-02-14 10:59:34 -0800 | [diff] [blame] | 303 | (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid))) |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 304 | return 1; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 305 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 306 | if (timestamp < cb->cmd.expire_unreachable) { |
Junio C Hamano | 03cb91b | 2010-04-09 13:20:02 -0700 | [diff] [blame] | 307 | if (cb->unreachable_expire_kind == UE_ALWAYS) |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 308 | return 1; |
Brandon Williams | dfa5990 | 2018-02-14 10:59:34 -0800 | [diff] [blame] | 309 | if (unreachable(cb, old_commit, ooid) || unreachable(cb, new_commit, noid)) |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 310 | return 1; |
Junio C Hamano | 9bbaa6c | 2007-01-11 19:56:43 -0800 | [diff] [blame] | 311 | } |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 312 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 313 | if (cb->cmd.recno && --(cb->cmd.recno) == 0) |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 314 | return 1; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 315 | |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 316 | return 0; |
Michael Haggerty | 60cc3c4 | 2014-12-12 09:56:47 +0100 | [diff] [blame] | 317 | } |
| 318 | |
Michael Haggerty | 5bcad1b | 2015-05-25 18:38:40 +0000 | [diff] [blame] | 319 | static int push_tip_to_list(const char *refname, const struct object_id *oid, |
Michael Haggerty | ea7b4f6 | 2014-12-12 09:56:52 +0100 | [diff] [blame] | 320 | int flags, void *cb_data) |
Junio C Hamano | 03cb91b | 2010-04-09 13:20:02 -0700 | [diff] [blame] | 321 | { |
| 322 | struct commit_list **list = cb_data; |
| 323 | struct commit *tip_commit; |
| 324 | if (flags & REF_ISSYMREF) |
| 325 | return 0; |
Stefan Beller | 21e1ee8 | 2018-06-28 18:21:57 -0700 | [diff] [blame] | 326 | tip_commit = lookup_commit_reference_gently(the_repository, oid, 1); |
Junio C Hamano | 03cb91b | 2010-04-09 13:20:02 -0700 | [diff] [blame] | 327 | if (!tip_commit) |
| 328 | return 0; |
| 329 | commit_list_insert(tip_commit, list); |
| 330 | return 0; |
| 331 | } |
| 332 | |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 333 | static void reflog_expiry_prepare(const char *refname, |
brian m. carlson | 4322478 | 2017-05-06 22:10:00 +0000 | [diff] [blame] | 334 | const struct object_id *oid, |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 335 | void *cb_data) |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 336 | { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 337 | struct expire_reflog_policy_cb *cb = cb_data; |
| 338 | |
| 339 | if (!cb->cmd.expire_unreachable || !strcmp(refname, "HEAD")) { |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 340 | cb->tip_commit = NULL; |
| 341 | cb->unreachable_expire_kind = UE_HEAD; |
| 342 | } else { |
Stefan Beller | 21e1ee8 | 2018-06-28 18:21:57 -0700 | [diff] [blame] | 343 | cb->tip_commit = lookup_commit_reference_gently(the_repository, |
| 344 | oid, 1); |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 345 | if (!cb->tip_commit) |
| 346 | cb->unreachable_expire_kind = UE_ALWAYS; |
| 347 | else |
| 348 | cb->unreachable_expire_kind = UE_NORMAL; |
| 349 | } |
| 350 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 351 | if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 352 | cb->unreachable_expire_kind = UE_ALWAYS; |
| 353 | |
| 354 | cb->mark_list = NULL; |
| 355 | cb->tips = NULL; |
| 356 | if (cb->unreachable_expire_kind != UE_ALWAYS) { |
| 357 | if (cb->unreachable_expire_kind == UE_HEAD) { |
| 358 | struct commit_list *elem; |
Michael Haggerty | 2b2a5be | 2015-05-25 18:38:28 +0000 | [diff] [blame] | 359 | |
Michael Haggerty | 5bcad1b | 2015-05-25 18:38:40 +0000 | [diff] [blame] | 360 | for_each_ref(push_tip_to_list, &cb->tips); |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 361 | for (elem = cb->tips; elem; elem = elem->next) |
| 362 | commit_list_insert(elem->item, &cb->mark_list); |
| 363 | } else { |
| 364 | commit_list_insert(cb->tip_commit, &cb->mark_list); |
| 365 | } |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 366 | cb->mark_limit = cb->cmd.expire_total; |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 367 | mark_reachable(cb); |
| 368 | } |
| 369 | } |
| 370 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 371 | static void reflog_expiry_cleanup(void *cb_data) |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 372 | { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 373 | struct expire_reflog_policy_cb *cb = cb_data; |
| 374 | |
Michael Haggerty | c48a163 | 2014-12-12 09:56:48 +0100 | [diff] [blame] | 375 | if (cb->unreachable_expire_kind != UE_ALWAYS) { |
| 376 | if (cb->unreachable_expire_kind == UE_HEAD) { |
| 377 | struct commit_list *elem; |
| 378 | for (elem = cb->tips; elem; elem = elem->next) |
| 379 | clear_commit_marks(elem->item, REACHABLE); |
| 380 | free_commit_list(cb->tips); |
| 381 | } else { |
| 382 | clear_commit_marks(cb->tip_commit, REACHABLE); |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | |
Michael Haggerty | 5bcad1b | 2015-05-25 18:38:40 +0000 | [diff] [blame] | 387 | static int collect_reflog(const char *ref, const struct object_id *oid, int unused, void *cb_data) |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 388 | { |
| 389 | struct collected_reflog *e; |
| 390 | struct collect_reflog_cb *cb = cb_data; |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 391 | |
Jeff King | 96ffc06 | 2016-02-22 17:44:32 -0500 | [diff] [blame] | 392 | FLEX_ALLOC_STR(e, reflog, ref); |
brian m. carlson | b8acac5 | 2017-10-15 22:06:58 +0000 | [diff] [blame] | 393 | oidcpy(&e->oid, oid); |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 394 | ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc); |
| 395 | cb->e[cb->nr++] = e; |
| 396 | return 0; |
| 397 | } |
| 398 | |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 399 | static struct reflog_expire_cfg { |
| 400 | struct reflog_expire_cfg *next; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 401 | timestamp_t expire_total; |
| 402 | timestamp_t expire_unreachable; |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 403 | char pattern[FLEX_ARRAY]; |
| 404 | } *reflog_expire_cfg, **reflog_expire_cfg_tail; |
| 405 | |
| 406 | static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) |
| 407 | { |
| 408 | struct reflog_expire_cfg *ent; |
| 409 | |
| 410 | if (!reflog_expire_cfg_tail) |
| 411 | reflog_expire_cfg_tail = &reflog_expire_cfg; |
| 412 | |
| 413 | for (ent = reflog_expire_cfg; ent; ent = ent->next) |
Jeff King | c3a700f | 2016-02-19 06:21:08 -0500 | [diff] [blame] | 414 | if (!strncmp(ent->pattern, pattern, len) && |
| 415 | ent->pattern[len] == '\0') |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 416 | return ent; |
| 417 | |
Jeff King | 96ffc06 | 2016-02-22 17:44:32 -0500 | [diff] [blame] | 418 | FLEX_ALLOC_MEM(ent, pattern, pattern, len); |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 419 | *reflog_expire_cfg_tail = ent; |
| 420 | reflog_expire_cfg_tail = &(ent->next); |
| 421 | return ent; |
| 422 | } |
| 423 | |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 424 | /* expiry timer slot */ |
| 425 | #define EXPIRE_TOTAL 01 |
| 426 | #define EXPIRE_UNREACH 02 |
| 427 | |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 428 | static int reflog_expire_config(const char *var, const char *value, void *cb) |
Junio C Hamano | 4aec56d | 2006-12-27 01:47:57 -0800 | [diff] [blame] | 429 | { |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 430 | const char *pattern, *key; |
| 431 | int pattern_len; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 432 | timestamp_t expire; |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 433 | int slot; |
| 434 | struct reflog_expire_cfg *ent; |
| 435 | |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 436 | if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 437 | return git_default_config(var, value, cb); |
| 438 | |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 439 | if (!strcmp(key, "reflogexpire")) { |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 440 | slot = EXPIRE_TOTAL; |
Haaris Mehmood | 5f96742 | 2017-11-18 02:27:27 +0000 | [diff] [blame] | 441 | if (git_config_expiry_date(&expire, var, value)) |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 442 | return -1; |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 443 | } else if (!strcmp(key, "reflogexpireunreachable")) { |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 444 | slot = EXPIRE_UNREACH; |
Haaris Mehmood | 5f96742 | 2017-11-18 02:27:27 +0000 | [diff] [blame] | 445 | if (git_config_expiry_date(&expire, var, value)) |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 446 | return -1; |
| 447 | } else |
| 448 | return git_default_config(var, value, cb); |
| 449 | |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 450 | if (!pattern) { |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 451 | switch (slot) { |
| 452 | case EXPIRE_TOTAL: |
| 453 | default_reflog_expire = expire; |
| 454 | break; |
| 455 | case EXPIRE_UNREACH: |
| 456 | default_reflog_expire_unreachable = expire; |
| 457 | break; |
| 458 | } |
Junio C Hamano | 4f342b9 | 2008-02-11 10:50:06 -0800 | [diff] [blame] | 459 | return 0; |
| 460 | } |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 461 | |
Jeff King | b3873c3 | 2013-01-23 01:27:37 -0500 | [diff] [blame] | 462 | ent = find_cfg_ent(pattern, pattern_len); |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 463 | if (!ent) |
| 464 | return -1; |
| 465 | switch (slot) { |
| 466 | case EXPIRE_TOTAL: |
| 467 | ent->expire_total = expire; |
| 468 | break; |
| 469 | case EXPIRE_UNREACH: |
| 470 | ent->expire_unreachable = expire; |
| 471 | break; |
Junio C Hamano | 4f342b9 | 2008-02-11 10:50:06 -0800 | [diff] [blame] | 472 | } |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 473 | return 0; |
| 474 | } |
| 475 | |
| 476 | static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, const char *ref) |
| 477 | { |
| 478 | struct reflog_expire_cfg *ent; |
| 479 | |
| 480 | if (slot == (EXPIRE_TOTAL|EXPIRE_UNREACH)) |
| 481 | return; /* both given explicitly -- nothing to tweak */ |
| 482 | |
| 483 | for (ent = reflog_expire_cfg; ent; ent = ent->next) { |
Ævar Arnfjörð Bjarmason | 55d3426 | 2017-06-22 21:38:08 +0000 | [diff] [blame] | 484 | if (!wildmatch(ent->pattern, ref, 0)) { |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 485 | if (!(slot & EXPIRE_TOTAL)) |
| 486 | cb->expire_total = ent->expire_total; |
| 487 | if (!(slot & EXPIRE_UNREACH)) |
| 488 | cb->expire_unreachable = ent->expire_unreachable; |
| 489 | return; |
| 490 | } |
| 491 | } |
| 492 | |
Junio C Hamano | 60bce2b | 2008-06-28 22:24:49 -0700 | [diff] [blame] | 493 | /* |
| 494 | * If unconfigured, make stash never expire |
| 495 | */ |
| 496 | if (!strcmp(ref, "refs/stash")) { |
| 497 | if (!(slot & EXPIRE_TOTAL)) |
| 498 | cb->expire_total = 0; |
| 499 | if (!(slot & EXPIRE_UNREACH)) |
| 500 | cb->expire_unreachable = 0; |
| 501 | return; |
| 502 | } |
| 503 | |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 504 | /* Nothing matched -- use the default value */ |
| 505 | if (!(slot & EXPIRE_TOTAL)) |
| 506 | cb->expire_total = default_reflog_expire; |
| 507 | if (!(slot & EXPIRE_UNREACH)) |
| 508 | cb->expire_unreachable = default_reflog_expire_unreachable; |
Junio C Hamano | 4aec56d | 2006-12-27 01:47:57 -0800 | [diff] [blame] | 509 | } |
| 510 | |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 511 | static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) |
| 512 | { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 513 | struct expire_reflog_policy_cb cb; |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 514 | timestamp_t now = time(NULL); |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 515 | int i, status, do_all; |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 516 | int explicit_expiry = 0; |
Michael Haggerty | aba56c8 | 2014-12-12 09:56:49 +0100 | [diff] [blame] | 517 | unsigned int flags = 0; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 518 | |
Adam Simpkins | 4a9f439 | 2010-02-26 19:50:03 -0800 | [diff] [blame] | 519 | default_reflog_expire_unreachable = now - 30 * 24 * 3600; |
| 520 | default_reflog_expire = now - 90 * 24 * 3600; |
Johannes Schindelin | ef90d6d | 2008-05-14 18:46:53 +0100 | [diff] [blame] | 521 | git_config(reflog_expire_config, NULL); |
Junio C Hamano | 4aec56d | 2006-12-27 01:47:57 -0800 | [diff] [blame] | 522 | |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 523 | save_commit_buffer = 0; |
| 524 | do_all = status = 0; |
| 525 | memset(&cb, 0, sizeof(cb)); |
Junio C Hamano | 4aec56d | 2006-12-27 01:47:57 -0800 | [diff] [blame] | 526 | |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 527 | cb.cmd.expire_total = default_reflog_expire; |
| 528 | cb.cmd.expire_unreachable = default_reflog_expire_unreachable; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 529 | |
| 530 | for (i = 1; i < argc; i++) { |
| 531 | const char *arg = argv[i]; |
| 532 | if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) |
Michael Haggerty | 98f31d8 | 2014-12-12 09:56:50 +0100 | [diff] [blame] | 533 | flags |= EXPIRE_REFLOGS_DRY_RUN; |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 534 | else if (starts_with(arg, "--expire=")) { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 535 | if (parse_expiry_date(arg + 9, &cb.cmd.expire_total)) |
Junio C Hamano | 3d27b9b | 2013-04-17 15:38:08 -0700 | [diff] [blame] | 536 | die(_("'%s' is not a valid timestamp"), arg); |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 537 | explicit_expiry |= EXPIRE_TOTAL; |
| 538 | } |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 539 | else if (starts_with(arg, "--expire-unreachable=")) { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 540 | if (parse_expiry_date(arg + 21, &cb.cmd.expire_unreachable)) |
Junio C Hamano | 3d27b9b | 2013-04-17 15:38:08 -0700 | [diff] [blame] | 541 | die(_("'%s' is not a valid timestamp"), arg); |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 542 | explicit_expiry |= EXPIRE_UNREACH; |
| 543 | } |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 544 | else if (!strcmp(arg, "--stale-fix")) |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 545 | cb.cmd.stalefix = 1; |
Brandon Casey | 2b81fab | 2008-02-22 12:56:50 -0600 | [diff] [blame] | 546 | else if (!strcmp(arg, "--rewrite")) |
Michael Haggerty | 553daf1 | 2014-12-12 09:56:56 +0100 | [diff] [blame] | 547 | flags |= EXPIRE_REFLOGS_REWRITE; |
Brandon Casey | 55f1056 | 2008-02-22 13:04:12 -0600 | [diff] [blame] | 548 | else if (!strcmp(arg, "--updateref")) |
Michael Haggerty | c4c4fbf | 2014-12-12 09:56:51 +0100 | [diff] [blame] | 549 | flags |= EXPIRE_REFLOGS_UPDATE_REF; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 550 | else if (!strcmp(arg, "--all")) |
| 551 | do_all = 1; |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 552 | else if (!strcmp(arg, "--verbose")) |
Michael Haggerty | bc11155 | 2014-12-12 09:56:55 +0100 | [diff] [blame] | 553 | flags |= EXPIRE_REFLOGS_VERBOSE; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 554 | else if (!strcmp(arg, "--")) { |
| 555 | i++; |
| 556 | break; |
| 557 | } |
| 558 | else if (arg[0] == '-') |
| 559 | usage(reflog_expire_usage); |
| 560 | else |
| 561 | break; |
| 562 | } |
Junio C Hamano | 3cb22b8 | 2008-06-15 23:48:46 -0700 | [diff] [blame] | 563 | |
| 564 | /* |
| 565 | * We can trust the commits and objects reachable from refs |
| 566 | * even in older repository. We cannot trust what's reachable |
| 567 | * from reflog if the repository was pruned with older git. |
| 568 | */ |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 569 | if (cb.cmd.stalefix) { |
| 570 | init_revisions(&cb.cmd.revs, prefix); |
Michael Haggerty | bc11155 | 2014-12-12 09:56:55 +0100 | [diff] [blame] | 571 | if (flags & EXPIRE_REFLOGS_VERBOSE) |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 572 | printf("Marking reachable objects..."); |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 573 | mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL); |
Michael Haggerty | bc11155 | 2014-12-12 09:56:55 +0100 | [diff] [blame] | 574 | if (flags & EXPIRE_REFLOGS_VERBOSE) |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 575 | putchar('\n'); |
| 576 | } |
| 577 | |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 578 | if (do_all) { |
| 579 | struct collect_reflog_cb collected; |
| 580 | int i; |
| 581 | |
| 582 | memset(&collected, 0, sizeof(collected)); |
Michael Haggerty | 5bcad1b | 2015-05-25 18:38:40 +0000 | [diff] [blame] | 583 | for_each_reflog(collect_reflog, &collected); |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 584 | for (i = 0; i < collected.nr; i++) { |
| 585 | struct collected_reflog *e = collected.e[i]; |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 586 | set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog); |
brian m. carlson | 0155f71 | 2017-10-15 22:07:04 +0000 | [diff] [blame] | 587 | status |= reflog_expire(e->reflog, &e->oid, flags, |
Michael Haggerty | fa5b183 | 2014-12-12 09:56:59 +0100 | [diff] [blame] | 588 | reflog_expiry_prepare, |
| 589 | should_expire_reflog_ent, |
| 590 | reflog_expiry_cleanup, |
| 591 | &cb); |
Junio C Hamano | bda3a31 | 2008-01-25 23:53:05 -0800 | [diff] [blame] | 592 | free(e); |
| 593 | } |
| 594 | free(collected.e); |
| 595 | } |
| 596 | |
Pieter de Bie | 90fb46e | 2008-08-10 22:22:21 +0200 | [diff] [blame] | 597 | for (; i < argc; i++) { |
| 598 | char *ref; |
brian m. carlson | b8acac5 | 2017-10-15 22:06:58 +0000 | [diff] [blame] | 599 | struct object_id oid; |
brian m. carlson | 334dc52 | 2017-10-15 22:06:59 +0000 | [diff] [blame] | 600 | if (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) { |
Pieter de Bie | 90fb46e | 2008-08-10 22:22:21 +0200 | [diff] [blame] | 601 | status |= error("%s points nowhere!", argv[i]); |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 602 | continue; |
| 603 | } |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 604 | set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref); |
brian m. carlson | 0155f71 | 2017-10-15 22:07:04 +0000 | [diff] [blame] | 605 | status |= reflog_expire(ref, &oid, flags, |
Michael Haggerty | fa5b183 | 2014-12-12 09:56:59 +0100 | [diff] [blame] | 606 | reflog_expiry_prepare, |
| 607 | should_expire_reflog_ent, |
| 608 | reflog_expiry_cleanup, |
| 609 | &cb); |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 610 | } |
| 611 | return status; |
| 612 | } |
| 613 | |
brian m. carlson | 9461d27 | 2017-02-21 23:47:32 +0000 | [diff] [blame] | 614 | static int count_reflog_ent(struct object_id *ooid, struct object_id *noid, |
Johannes Schindelin | dddbad7 | 2017-04-26 21:29:31 +0200 | [diff] [blame] | 615 | const char *email, timestamp_t timestamp, int tz, |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 616 | const char *message, void *cb_data) |
| 617 | { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 618 | struct expire_reflog_policy_cb *cb = cb_data; |
| 619 | if (!cb->cmd.expire_total || timestamp < cb->cmd.expire_total) |
| 620 | cb->cmd.recno++; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 621 | return 0; |
| 622 | } |
| 623 | |
| 624 | static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) |
| 625 | { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 626 | struct expire_reflog_policy_cb cb; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 627 | int i, status = 0; |
Michael Haggerty | aba56c8 | 2014-12-12 09:56:49 +0100 | [diff] [blame] | 628 | unsigned int flags = 0; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 629 | |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 630 | memset(&cb, 0, sizeof(cb)); |
| 631 | |
| 632 | for (i = 1; i < argc; i++) { |
Brandon Casey | 3c386aa | 2008-02-22 15:08:59 -0600 | [diff] [blame] | 633 | const char *arg = argv[i]; |
| 634 | if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) |
Michael Haggerty | 98f31d8 | 2014-12-12 09:56:50 +0100 | [diff] [blame] | 635 | flags |= EXPIRE_REFLOGS_DRY_RUN; |
Brandon Casey | 2b81fab | 2008-02-22 12:56:50 -0600 | [diff] [blame] | 636 | else if (!strcmp(arg, "--rewrite")) |
Michael Haggerty | 553daf1 | 2014-12-12 09:56:56 +0100 | [diff] [blame] | 637 | flags |= EXPIRE_REFLOGS_REWRITE; |
Brandon Casey | 55f1056 | 2008-02-22 13:04:12 -0600 | [diff] [blame] | 638 | else if (!strcmp(arg, "--updateref")) |
Michael Haggerty | c4c4fbf | 2014-12-12 09:56:51 +0100 | [diff] [blame] | 639 | flags |= EXPIRE_REFLOGS_UPDATE_REF; |
Brandon Casey | 3c386aa | 2008-02-22 15:08:59 -0600 | [diff] [blame] | 640 | else if (!strcmp(arg, "--verbose")) |
Michael Haggerty | bc11155 | 2014-12-12 09:56:55 +0100 | [diff] [blame] | 641 | flags |= EXPIRE_REFLOGS_VERBOSE; |
Brandon Casey | 3c386aa | 2008-02-22 15:08:59 -0600 | [diff] [blame] | 642 | else if (!strcmp(arg, "--")) { |
| 643 | i++; |
| 644 | break; |
| 645 | } |
| 646 | else if (arg[0] == '-') |
| 647 | usage(reflog_delete_usage); |
| 648 | else |
| 649 | break; |
| 650 | } |
| 651 | |
| 652 | if (argc - i < 1) |
| 653 | return error("Nothing to delete?"); |
| 654 | |
| 655 | for ( ; i < argc; i++) { |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 656 | const char *spec = strstr(argv[i], "@{"); |
brian m. carlson | b8acac5 | 2017-10-15 22:06:58 +0000 | [diff] [blame] | 657 | struct object_id oid; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 658 | char *ep, *ref; |
| 659 | int recno; |
| 660 | |
| 661 | if (!spec) { |
Brandon Casey | cb97cc9 | 2008-01-04 19:11:37 -0600 | [diff] [blame] | 662 | status |= error("Not a reflog: %s", argv[i]); |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 663 | continue; |
| 664 | } |
| 665 | |
brian m. carlson | 334dc52 | 2017-10-15 22:06:59 +0000 | [diff] [blame] | 666 | if (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) { |
Junio C Hamano | 55beff4 | 2008-08-10 23:21:25 -0700 | [diff] [blame] | 667 | status |= error("no reflog for '%s'", argv[i]); |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 668 | continue; |
| 669 | } |
| 670 | |
| 671 | recno = strtoul(spec + 2, &ep, 10); |
| 672 | if (*ep == '}') { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 673 | cb.cmd.recno = -recno; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 674 | for_each_reflog_ent(ref, count_reflog_ent, &cb); |
| 675 | } else { |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 676 | cb.cmd.expire_total = approxidate(spec + 2); |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 677 | for_each_reflog_ent(ref, count_reflog_ent, &cb); |
Michael Haggerty | b729eff | 2014-12-12 09:56:58 +0100 | [diff] [blame] | 678 | cb.cmd.expire_total = 0; |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 679 | } |
| 680 | |
brian m. carlson | 0155f71 | 2017-10-15 22:07:04 +0000 | [diff] [blame] | 681 | status |= reflog_expire(ref, &oid, flags, |
Michael Haggerty | fa5b183 | 2014-12-12 09:56:59 +0100 | [diff] [blame] | 682 | reflog_expiry_prepare, |
| 683 | should_expire_reflog_ent, |
| 684 | reflog_expiry_cleanup, |
| 685 | &cb); |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 686 | free(ref); |
| 687 | } |
| 688 | return status; |
| 689 | } |
| 690 | |
David Turner | afcb2e7 | 2015-07-21 17:04:53 -0400 | [diff] [blame] | 691 | static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) |
| 692 | { |
| 693 | int i, start = 0; |
| 694 | |
| 695 | for (i = 1; i < argc; i++) { |
| 696 | const char *arg = argv[i]; |
| 697 | if (!strcmp(arg, "--")) { |
| 698 | i++; |
| 699 | break; |
| 700 | } |
| 701 | else if (arg[0] == '-') |
| 702 | usage(reflog_exists_usage); |
| 703 | else |
| 704 | break; |
| 705 | } |
| 706 | |
| 707 | start = i; |
| 708 | |
| 709 | if (argc - start != 1) |
| 710 | usage(reflog_exists_usage); |
| 711 | |
| 712 | if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL)) |
| 713 | die("invalid ref format: %s", argv[start]); |
| 714 | return !reflog_exists(argv[start]); |
| 715 | } |
| 716 | |
Junio C Hamano | 1389d9d | 2007-01-06 02:16:19 -0800 | [diff] [blame] | 717 | /* |
| 718 | * main "reflog" |
| 719 | */ |
| 720 | |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 721 | static const char reflog_usage[] = |
David Turner | afcb2e7 | 2015-07-21 17:04:53 -0400 | [diff] [blame] | 722 | "git reflog [ show | expire | delete | exists ]"; |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 723 | |
| 724 | int cmd_reflog(int argc, const char **argv, const char *prefix) |
| 725 | { |
Jonathan Nieder | 99caeed | 2009-11-09 09:05:01 -0600 | [diff] [blame] | 726 | if (argc > 1 && !strcmp(argv[1], "-h")) |
| 727 | usage(reflog_usage); |
| 728 | |
Linus Torvalds | cf39f54 | 2007-02-08 09:51:56 -0800 | [diff] [blame] | 729 | /* With no command, we default to showing it. */ |
| 730 | if (argc < 2 || *argv[1] == '-') |
| 731 | return cmd_log_reflog(argc, argv, prefix); |
| 732 | |
| 733 | if (!strcmp(argv[1], "show")) |
| 734 | return cmd_log_reflog(argc - 1, argv + 1, prefix); |
| 735 | |
| 736 | if (!strcmp(argv[1], "expire")) |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 737 | return cmd_reflog_expire(argc - 1, argv + 1, prefix); |
Linus Torvalds | cf39f54 | 2007-02-08 09:51:56 -0800 | [diff] [blame] | 738 | |
Johannes Schindelin | 552cecc | 2007-10-17 02:50:45 +0100 | [diff] [blame] | 739 | if (!strcmp(argv[1], "delete")) |
| 740 | return cmd_reflog_delete(argc - 1, argv + 1, prefix); |
| 741 | |
David Turner | afcb2e7 | 2015-07-21 17:04:53 -0400 | [diff] [blame] | 742 | if (!strcmp(argv[1], "exists")) |
| 743 | return cmd_reflog_exists(argc - 1, argv + 1, prefix); |
| 744 | |
Michael Schubert | bf01d4a | 2011-08-01 13:20:42 +0200 | [diff] [blame] | 745 | return cmd_log_reflog(argc, argv, prefix); |
Junio C Hamano | 4264dc1 | 2006-12-19 00:23:12 -0800 | [diff] [blame] | 746 | } |