3636#include "reflog.h"
3737#include "repack.h"
3838#include "rerere.h"
39+ #include "revision.h"
3940#include "blob.h"
4041#include "tree.h"
4142#include "promisor-remote.h"
@@ -286,12 +287,26 @@ static void maintenance_run_opts_release(struct maintenance_run_opts *opts)
286287
287288static int pack_refs_condition (UNUSED struct gc_config * cfg )
288289{
289- /*
290- * The auto-repacking logic for refs is handled by the ref backends and
291- * exposed via `git pack-refs --auto`. We thus always return truish
292- * here and let the backend decide for us.
293- */
294- return 1 ;
290+ struct string_list included_refs = STRING_LIST_INIT_NODUP ;
291+ struct ref_exclusions excludes = REF_EXCLUSIONS_INIT ;
292+ struct refs_optimize_opts optimize_opts = {
293+ .exclusions = & excludes ,
294+ .includes = & included_refs ,
295+ .flags = REFS_OPTIMIZE_PRUNE | REFS_OPTIMIZE_AUTO ,
296+ };
297+ bool required ;
298+
299+ /* Check for all refs, similar to 'git refs optimize --all'. */
300+ string_list_append (optimize_opts .includes , "*" );
301+
302+ if (refs_optimize_required (get_main_ref_store (the_repository ),
303+ & optimize_opts , & required ))
304+ return 0 ;
305+
306+ clear_ref_exclusions (& excludes );
307+ string_list_clear (& included_refs , 0 );
308+
309+ return required ;
295310}
296311
297312static int maintenance_task_pack_refs (struct maintenance_run_opts * opts ,
@@ -1095,9 +1110,6 @@ static int maintenance_opt_schedule(const struct option *opt, const char *arg,
10951110 return 0 ;
10961111}
10971112
1098- /* Remember to update object flag allocation in object.h */
1099- #define SEEN (1u<<0)
1100-
11011113struct cg_auto_data {
11021114 int num_not_in_graph ;
11031115 int limit ;
@@ -3444,7 +3456,67 @@ static int maintenance_stop(int argc, const char **argv, const char *prefix,
34443456 return update_background_schedule (NULL , 0 );
34453457}
34463458
3447- static const char * const builtin_maintenance_usage [] = {
3459+ static const char * const builtin_maintenance_is_needed_usage [] = {
3460+ "git maintenance is-needed [--task=<task>] [--schedule]" ,
3461+ NULL
3462+ };
3463+
3464+ static int maintenance_is_needed (int argc , const char * * argv , const char * prefix ,
3465+ struct repository * repo UNUSED )
3466+ {
3467+ struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT ;
3468+ struct string_list selected_tasks = STRING_LIST_INIT_DUP ;
3469+ struct gc_config cfg = GC_CONFIG_INIT ;
3470+ struct option options [] = {
3471+ OPT_BOOL (0 , "auto" , & opts .auto_flag ,
3472+ N_ ("run tasks based on the state of the repository" )),
3473+ OPT_CALLBACK_F (0 , "task" , & selected_tasks , N_ ("task" ),
3474+ N_ ("check a specific task" ),
3475+ PARSE_OPT_NONEG , task_option_parse ),
3476+ OPT_END ()
3477+ };
3478+ bool is_needed = false;
3479+
3480+ argc = parse_options (argc , argv , prefix , options ,
3481+ builtin_maintenance_is_needed_usage ,
3482+ PARSE_OPT_STOP_AT_NON_OPTION );
3483+ if (argc )
3484+ usage_with_options (builtin_maintenance_is_needed_usage , options );
3485+
3486+ gc_config (& cfg );
3487+ initialize_task_config (& opts , & selected_tasks );
3488+
3489+ if (opts .auto_flag ) {
3490+ for (size_t i = 0 ; i < opts .tasks_nr ; i ++ ) {
3491+ if (tasks [opts .tasks [i ]].auto_condition &&
3492+ tasks [opts .tasks [i ]].auto_condition (& cfg )) {
3493+ is_needed = true;
3494+ break ;
3495+ }
3496+ }
3497+ } else {
3498+ /*
3499+ * When not using --auto we always require maintenance right now.
3500+ *
3501+ * TODO: this certainly is too eager, as some maintenance tasks may
3502+ * decide to not do anything because the data structures are already
3503+ * fully optimized. We may eventually want to extend the auto
3504+ * condition to also cover non-auto runs so that we can detect such
3505+ * cases.
3506+ */
3507+ is_needed = true;
3508+ }
3509+
3510+ string_list_clear (& selected_tasks , 0 );
3511+ maintenance_run_opts_release (& opts );
3512+ gc_config_release (& cfg );
3513+
3514+ if (is_needed )
3515+ return 0 ;
3516+ return 1 ;
3517+ }
3518+
3519+ static const char * const builtin_maintenance_usage [] = {
34483520 N_ ("git maintenance <subcommand> [<options>]" ),
34493521 NULL ,
34503522};
@@ -3461,6 +3533,7 @@ int cmd_maintenance(int argc,
34613533 OPT_SUBCOMMAND ("stop" , & fn , maintenance_stop ),
34623534 OPT_SUBCOMMAND ("register" , & fn , maintenance_register ),
34633535 OPT_SUBCOMMAND ("unregister" , & fn , maintenance_unregister ),
3536+ OPT_SUBCOMMAND ("is-needed" , & fn , maintenance_is_needed ),
34643537 OPT_END (),
34653538 };
34663539
0 commit comments