1 #define USE_THE_REPOSITORY_VARIABLE
12 #include "parse-options.h"
14 #define BUILTIN_REFLOG_SHOW_USAGE \
15 N_("git reflog [show] [<log-options>] [<ref>]")
17 #define BUILTIN_REFLOG_LIST_USAGE \
20 #define BUILTIN_REFLOG_EXPIRE_USAGE \
21 N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
22 " [--rewrite] [--updateref] [--stale-fix]\n" \
23 " [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]")
25 #define BUILTIN_REFLOG_DELETE_USAGE \
26 N_("git reflog delete [--rewrite] [--updateref]\n" \
27 " [--dry-run | -n] [--verbose] <ref>@{<specifier>}...")
29 #define BUILTIN_REFLOG_EXISTS_USAGE \
30 N_("git reflog exists <ref>")
32 #define BUILTIN_REFLOG_DROP_USAGE \
33 N_("git reflog drop [--all [--single-worktree] | <refs>...]")
35 static const char *const reflog_show_usage
[] = {
36 BUILTIN_REFLOG_SHOW_USAGE
,
40 static const char *const reflog_list_usage
[] = {
41 BUILTIN_REFLOG_LIST_USAGE
,
45 static const char *const reflog_expire_usage
[] = {
46 BUILTIN_REFLOG_EXPIRE_USAGE
,
50 static const char *const reflog_delete_usage
[] = {
51 BUILTIN_REFLOG_DELETE_USAGE
,
55 static const char *const reflog_exists_usage
[] = {
56 BUILTIN_REFLOG_EXISTS_USAGE
,
60 static const char *const reflog_drop_usage
[] = {
61 BUILTIN_REFLOG_DROP_USAGE
,
65 static const char *const reflog_usage
[] = {
66 BUILTIN_REFLOG_SHOW_USAGE
,
67 BUILTIN_REFLOG_LIST_USAGE
,
68 BUILTIN_REFLOG_EXPIRE_USAGE
,
69 BUILTIN_REFLOG_DELETE_USAGE
,
70 BUILTIN_REFLOG_DROP_USAGE
,
71 BUILTIN_REFLOG_EXISTS_USAGE
,
75 struct worktree_reflogs
{
76 struct worktree
*worktree
;
77 struct string_list reflogs
;
80 static int collect_reflog(const char *ref
, void *cb_data
)
82 struct worktree_reflogs
*cb
= cb_data
;
83 struct worktree
*worktree
= cb
->worktree
;
84 struct strbuf newref
= STRBUF_INIT
;
87 * Avoid collecting the same shared ref multiple times because
88 * they are available via all worktrees.
90 if (!worktree
->is_current
&&
91 parse_worktree_ref(ref
, NULL
, NULL
, NULL
) == REF_WORKTREE_SHARED
)
94 strbuf_worktree_ref(worktree
, &newref
, ref
);
95 string_list_append_nodup(&cb
->reflogs
, strbuf_detach(&newref
, NULL
));
100 static int expire_unreachable_callback(const struct option
*opt
,
104 struct reflog_expire_options
*opts
= opt
->value
;
106 BUG_ON_OPT_NEG(unset
);
108 if (parse_expiry_date(arg
, &opts
->expire_unreachable
))
109 die(_("invalid timestamp '%s' given to '--%s'"),
110 arg
, opt
->long_name
);
112 opts
->explicit_expiry
|= REFLOG_EXPIRE_UNREACH
;
116 static int expire_total_callback(const struct option
*opt
,
120 struct reflog_expire_options
*opts
= opt
->value
;
122 BUG_ON_OPT_NEG(unset
);
124 if (parse_expiry_date(arg
, &opts
->expire_total
))
125 die(_("invalid timestamp '%s' given to '--%s'"),
126 arg
, opt
->long_name
);
128 opts
->explicit_expiry
|= REFLOG_EXPIRE_TOTAL
;
132 static int cmd_reflog_show(int argc
, const char **argv
, const char *prefix
,
133 struct repository
*repo UNUSED
)
135 struct option options
[] = {
139 parse_options(argc
, argv
, prefix
, options
, reflog_show_usage
,
140 PARSE_OPT_KEEP_DASHDASH
| PARSE_OPT_KEEP_ARGV0
|
141 PARSE_OPT_KEEP_UNKNOWN_OPT
);
143 return cmd_log_reflog(argc
, argv
, prefix
, the_repository
);
146 static int show_reflog(const char *refname
, void *cb_data UNUSED
)
148 printf("%s\n", refname
);
152 static int cmd_reflog_list(int argc
, const char **argv
, const char *prefix
,
153 struct repository
*repo UNUSED
)
155 struct option options
[] = {
158 struct ref_store
*ref_store
;
160 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_list_usage
, 0);
162 return error(_("%s does not accept arguments: '%s'"),
165 ref_store
= get_main_ref_store(the_repository
);
167 return refs_for_each_reflog(ref_store
, show_reflog
, NULL
);
170 static int cmd_reflog_expire(int argc
, const char **argv
, const char *prefix
,
171 struct repository
*repo UNUSED
)
173 timestamp_t now
= time(NULL
);
174 struct reflog_expire_options opts
= REFLOG_EXPIRE_OPTIONS_INIT(now
);
175 int i
, status
, do_all
, single_worktree
= 0;
176 unsigned int flags
= 0;
178 reflog_expiry_should_prune_fn
*should_prune_fn
= should_expire_reflog_ent
;
179 const struct option options
[] = {
180 OPT_BIT('n', "dry-run", &flags
, N_("do not actually prune any entries"),
181 EXPIRE_REFLOGS_DRY_RUN
),
182 OPT_BIT(0, "rewrite", &flags
,
183 N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
184 EXPIRE_REFLOGS_REWRITE
),
185 OPT_BIT(0, "updateref", &flags
,
186 N_("update the reference to the value of the top reflog entry"),
187 EXPIRE_REFLOGS_UPDATE_REF
),
188 OPT_BOOL(0, "verbose", &verbose
, N_("print extra information on screen")),
189 OPT_CALLBACK_F(0, "expire", &opts
, N_("timestamp"),
190 N_("prune entries older than the specified time"),
192 expire_total_callback
),
193 OPT_CALLBACK_F(0, "expire-unreachable", &opts
, N_("timestamp"),
194 N_("prune entries older than <time> that are not reachable from the current tip of the branch"),
196 expire_unreachable_callback
),
197 OPT_BOOL(0, "stale-fix", &opts
.stalefix
,
198 N_("prune any reflog entries that point to broken commits")),
199 OPT_BOOL(0, "all", &do_all
, N_("process the reflogs of all references")),
200 OPT_BOOL(0, "single-worktree", &single_worktree
,
201 N_("limits processing to reflogs from the current worktree only")),
205 git_config(reflog_expire_config
, &opts
);
207 save_commit_buffer
= 0;
210 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_expire_usage
, 0);
213 should_prune_fn
= should_expire_reflog_ent_verbose
;
216 * We can trust the commits and objects reachable from refs
217 * even in older repository. We cannot trust what's reachable
218 * from reflog if the repository was pruned with older git.
221 struct rev_info revs
;
223 repo_init_revisions(the_repository
, &revs
, prefix
);
224 revs
.do_not_die_on_missing_objects
= 1;
225 revs
.ignore_missing
= 1;
226 revs
.ignore_missing_links
= 1;
228 printf(_("Marking reachable objects..."));
229 mark_reachable_objects(&revs
, 0, 0, NULL
);
230 release_revisions(&revs
);
236 struct worktree_reflogs collected
= {
237 .reflogs
= STRING_LIST_INIT_DUP
,
239 struct string_list_item
*item
;
240 struct worktree
**worktrees
, **p
;
242 worktrees
= get_worktrees();
243 for (p
= worktrees
; *p
; p
++) {
244 if (single_worktree
&& !(*p
)->is_current
)
246 collected
.worktree
= *p
;
247 refs_for_each_reflog(get_worktree_ref_store(*p
),
248 collect_reflog
, &collected
);
250 free_worktrees(worktrees
);
252 for_each_string_list_item(item
, &collected
.reflogs
) {
253 struct expire_reflog_policy_cb cb
= {
255 .dry_run
= !!(flags
& EXPIRE_REFLOGS_DRY_RUN
),
258 reflog_expire_options_set_refname(&cb
.opts
, item
->string
);
259 status
|= refs_reflog_expire(get_main_ref_store(the_repository
),
261 reflog_expiry_prepare
,
263 reflog_expiry_cleanup
,
266 string_list_clear(&collected
.reflogs
, 0);
269 for (i
= 0; i
< argc
; i
++) {
271 struct expire_reflog_policy_cb cb
= { .opts
= opts
};
273 if (!repo_dwim_log(the_repository
, argv
[i
], strlen(argv
[i
]), NULL
, &ref
)) {
274 status
|= error(_("reflog could not be found: '%s'"), argv
[i
]);
277 reflog_expire_options_set_refname(&cb
.opts
, ref
);
278 status
|= refs_reflog_expire(get_main_ref_store(the_repository
),
280 reflog_expiry_prepare
,
282 reflog_expiry_cleanup
,
289 static int cmd_reflog_delete(int argc
, const char **argv
, const char *prefix
,
290 struct repository
*repo UNUSED
)
293 unsigned int flags
= 0;
296 const struct option options
[] = {
297 OPT_BIT('n', "dry-run", &flags
, N_("do not actually prune any entries"),
298 EXPIRE_REFLOGS_DRY_RUN
),
299 OPT_BIT(0, "rewrite", &flags
,
300 N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
301 EXPIRE_REFLOGS_REWRITE
),
302 OPT_BIT(0, "updateref", &flags
,
303 N_("update the reference to the value of the top reflog entry"),
304 EXPIRE_REFLOGS_UPDATE_REF
),
305 OPT_BOOL(0, "verbose", &verbose
, N_("print extra information on screen")),
309 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_delete_usage
, 0);
312 return error(_("no reflog specified to delete"));
314 for (i
= 0; i
< argc
; i
++)
315 status
|= reflog_delete(argv
[i
], flags
, verbose
);
320 static int cmd_reflog_exists(int argc
, const char **argv
, const char *prefix
,
321 struct repository
*repo UNUSED
)
323 struct option options
[] = {
328 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_exists_usage
,
331 usage_with_options(reflog_exists_usage
, options
);
334 if (check_refname_format(refname
, REFNAME_ALLOW_ONELEVEL
))
335 die(_("invalid ref format: %s"), refname
);
336 return !refs_reflog_exists(get_main_ref_store(the_repository
),
340 static int cmd_reflog_drop(int argc
, const char **argv
, const char *prefix
,
341 struct repository
*repo
)
343 int ret
= 0, do_all
= 0, single_worktree
= 0;
344 const struct option options
[] = {
345 OPT_BOOL(0, "all", &do_all
, N_("drop the reflogs of all references")),
346 OPT_BOOL(0, "single-worktree", &single_worktree
,
347 N_("drop reflogs from the current worktree only")),
351 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_drop_usage
, 0);
354 usage(_("references specified along with --all"));
357 struct worktree_reflogs collected
= {
358 .reflogs
= STRING_LIST_INIT_DUP
,
360 struct string_list_item
*item
;
361 struct worktree
**worktrees
, **p
;
363 worktrees
= get_worktrees();
364 for (p
= worktrees
; *p
; p
++) {
365 if (single_worktree
&& !(*p
)->is_current
)
367 collected
.worktree
= *p
;
368 refs_for_each_reflog(get_worktree_ref_store(*p
),
369 collect_reflog
, &collected
);
371 free_worktrees(worktrees
);
373 for_each_string_list_item(item
, &collected
.reflogs
)
374 ret
|= refs_delete_reflog(get_main_ref_store(repo
),
376 string_list_clear(&collected
.reflogs
, 0);
381 for (int i
= 0; i
< argc
; i
++) {
383 if (!repo_dwim_log(repo
, argv
[i
], strlen(argv
[i
]), NULL
, &ref
)) {
384 ret
|= error(_("reflog could not be found: '%s'"), argv
[i
]);
388 ret
|= refs_delete_reflog(get_main_ref_store(repo
), ref
);
398 int cmd_reflog(int argc
,
401 struct repository
*repository
)
403 parse_opt_subcommand_fn
*fn
= NULL
;
404 struct option options
[] = {
405 OPT_SUBCOMMAND("show", &fn
, cmd_reflog_show
),
406 OPT_SUBCOMMAND("list", &fn
, cmd_reflog_list
),
407 OPT_SUBCOMMAND("expire", &fn
, cmd_reflog_expire
),
408 OPT_SUBCOMMAND("delete", &fn
, cmd_reflog_delete
),
409 OPT_SUBCOMMAND("exists", &fn
, cmd_reflog_exists
),
410 OPT_SUBCOMMAND("drop", &fn
, cmd_reflog_drop
),
414 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_usage
,
415 PARSE_OPT_SUBCOMMAND_OPTIONAL
|
416 PARSE_OPT_KEEP_DASHDASH
| PARSE_OPT_KEEP_ARGV0
|
417 PARSE_OPT_KEEP_UNKNOWN_OPT
);
419 return fn(argc
- 1, argv
+ 1, prefix
, repository
);
421 return cmd_log_reflog(argc
, argv
, prefix
, repository
);