@@ -1478,9 +1478,9 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
14781478
14791479static void initialize_maintenance_strategy (void )
14801480{
1481- char * config_str ;
1481+ const char * config_str ;
14821482
1483- if (git_config_get_string ("maintenance.strategy" , & config_str ))
1483+ if (git_config_get_string_tmp ("maintenance.strategy" , & config_str ))
14841484 return ;
14851485
14861486 if (!strcasecmp (config_str , "incremental" )) {
@@ -1782,32 +1782,33 @@ static const char *get_frequency(enum schedule_priority schedule)
17821782 * * If $GIT_TEST_MAINT_SCHEDULER is set, return true.
17831783 * In this case, the *cmd value is read as input.
17841784 *
1785- * * if the input value * cmd is the key of one of the comma-separated list
1786- * item, then *is_available is set to true and *cmd is modified and becomes
1785+ * * if the input value cmd is the key of one of the comma-separated list
1786+ * item, then *is_available is set to true and *out is set to
17871787 * the mock command.
17881788 *
17891789 * * if the input value *cmd isn’t the key of any of the comma-separated list
1790- * item, then *is_available is set to false.
1790+ * item, then *is_available is set to false and *out is set to the original
1791+ * command.
17911792 *
17921793 * Ex.:
17931794 * GIT_TEST_MAINT_SCHEDULER not set
17941795 * +-------+-------------------------------------------------+
17951796 * | Input | Output |
1796- * | *cmd | return code | *cmd | *is_available |
1797+ * | *cmd | return code | *out | *is_available |
17971798 * +-------+-------------+-------------------+---------------+
1798- * | "foo" | false | "foo" (unchanged) | (unchanged) |
1799+ * | "foo" | false | NULL | (unchanged) |
17991800 * +-------+-------------+-------------------+---------------+
18001801 *
18011802 * GIT_TEST_MAINT_SCHEDULER set to “foo:./mock_foo.sh,bar:./mock_bar.sh”
18021803 * +-------+-------------------------------------------------+
18031804 * | Input | Output |
1804- * | *cmd | return code | *cmd | *is_available |
1805+ * | *cmd | return code | *out | *is_available |
18051806 * +-------+-------------+-------------------+---------------+
18061807 * | "foo" | true | "./mock.foo.sh" | true |
1807- * | "qux" | true | "qux" (unchanged ) | false |
1808+ * | "qux" | true | "qux" (allocated ) | false |
18081809 * +-------+-------------+-------------------+---------------+
18091810 */
1810- static int get_schedule_cmd (const char * * cmd , int * is_available )
1811+ static int get_schedule_cmd (const char * cmd , int * is_available , char * * out )
18111812{
18121813 char * testing = xstrdup_or_null (getenv ("GIT_TEST_MAINT_SCHEDULER" ));
18131814 struct string_list_item * item ;
@@ -1826,16 +1827,22 @@ static int get_schedule_cmd(const char **cmd, int *is_available)
18261827 if (string_list_split_in_place (& pair , item -> string , ":" , 2 ) != 2 )
18271828 continue ;
18281829
1829- if (!strcmp (* cmd , pair .items [0 ].string )) {
1830- * cmd = pair .items [1 ].string ;
1830+ if (!strcmp (cmd , pair .items [0 ].string )) {
1831+ if (out )
1832+ * out = xstrdup (pair .items [1 ].string );
18311833 if (is_available )
18321834 * is_available = 1 ;
1833- string_list_clear (& list , 0 );
1834- UNLEAK (testing );
1835- return 1 ;
1835+ string_list_clear (& pair , 0 );
1836+ goto out ;
18361837 }
1838+
1839+ string_list_clear (& pair , 0 );
18371840 }
18381841
1842+ if (out )
1843+ * out = xstrdup (cmd );
1844+
1845+ out :
18391846 string_list_clear (& list , 0 );
18401847 free (testing );
18411848 return 1 ;
@@ -1852,9 +1859,8 @@ static int get_random_minute(void)
18521859
18531860static int is_launchctl_available (void )
18541861{
1855- const char * cmd = "launchctl" ;
18561862 int is_available ;
1857- if (get_schedule_cmd (& cmd , & is_available ))
1863+ if (get_schedule_cmd ("launchctl" , & is_available , NULL ))
18581864 return is_available ;
18591865
18601866#ifdef __APPLE__
@@ -1892,12 +1898,12 @@ static char *launchctl_get_uid(void)
18921898
18931899static int launchctl_boot_plist (int enable , const char * filename )
18941900{
1895- const char * cmd = "launchctl" ;
1901+ char * cmd ;
18961902 int result ;
18971903 struct child_process child = CHILD_PROCESS_INIT ;
18981904 char * uid = launchctl_get_uid ();
18991905
1900- get_schedule_cmd (& cmd , NULL );
1906+ get_schedule_cmd ("launchctl" , NULL , & cmd );
19011907 strvec_split (& child .args , cmd );
19021908 strvec_pushl (& child .args , enable ? "bootstrap" : "bootout" , uid ,
19031909 filename , NULL );
@@ -1910,6 +1916,7 @@ static int launchctl_boot_plist(int enable, const char *filename)
19101916
19111917 result = finish_command (& child );
19121918
1919+ free (cmd );
19131920 free (uid );
19141921 return result ;
19151922}
@@ -1961,10 +1968,10 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
19611968 static unsigned long lock_file_timeout_ms = ULONG_MAX ;
19621969 struct strbuf plist = STRBUF_INIT , plist2 = STRBUF_INIT ;
19631970 struct stat st ;
1964- const char * cmd = "launchctl" ;
1971+ char * cmd ;
19651972 int minute = get_random_minute ();
19661973
1967- get_schedule_cmd (& cmd , NULL );
1974+ get_schedule_cmd ("launchctl" , NULL , & cmd );
19681975 preamble = "<?xml version=\"1.0\"?>\n"
19691976 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
19701977 "<plist version=\"1.0\">"
@@ -2054,6 +2061,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
20542061
20552062 free (filename );
20562063 free (name );
2064+ free (cmd );
20572065 strbuf_release (& plist );
20582066 strbuf_release (& plist2 );
20592067 return 0 ;
@@ -2078,9 +2086,8 @@ static int launchctl_update_schedule(int run_maintenance, int fd UNUSED)
20782086
20792087static int is_schtasks_available (void )
20802088{
2081- const char * cmd = "schtasks" ;
20822089 int is_available ;
2083- if (get_schedule_cmd (& cmd , & is_available ))
2090+ if (get_schedule_cmd ("schtasks" , & is_available , NULL ))
20842091 return is_available ;
20852092
20862093#ifdef GIT_WINDOWS_NATIVE
@@ -2099,15 +2106,16 @@ static char *schtasks_task_name(const char *frequency)
20992106
21002107static int schtasks_remove_task (enum schedule_priority schedule )
21012108{
2102- const char * cmd = "schtasks" ;
2109+ char * cmd ;
21032110 struct child_process child = CHILD_PROCESS_INIT ;
21042111 const char * frequency = get_frequency (schedule );
21052112 char * name = schtasks_task_name (frequency );
21062113
2107- get_schedule_cmd (& cmd , NULL );
2114+ get_schedule_cmd ("schtasks" , NULL , & cmd );
21082115 strvec_split (& child .args , cmd );
21092116 strvec_pushl (& child .args , "/delete" , "/tn" , name , "/f" , NULL );
21102117 free (name );
2118+ free (cmd );
21112119
21122120 return run_command (& child );
21132121}
@@ -2121,7 +2129,7 @@ static int schtasks_remove_tasks(void)
21212129
21222130static int schtasks_schedule_task (const char * exec_path , enum schedule_priority schedule )
21232131{
2124- const char * cmd = "schtasks" ;
2132+ char * cmd ;
21252133 int result ;
21262134 struct child_process child = CHILD_PROCESS_INIT ;
21272135 const char * xml ;
@@ -2131,7 +2139,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
21312139 struct strbuf tfilename = STRBUF_INIT ;
21322140 int minute = get_random_minute ();
21332141
2134- get_schedule_cmd (& cmd , NULL );
2142+ get_schedule_cmd ("schtasks" , NULL , & cmd );
21352143
21362144 strbuf_addf (& tfilename , "%s/schedule_%s_XXXXXX" ,
21372145 repo_get_common_dir (the_repository ), frequency );
@@ -2237,6 +2245,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
22372245
22382246 delete_tempfile (& tfile );
22392247 free (name );
2248+ free (cmd );
22402249 return result ;
22412250}
22422251
@@ -2278,29 +2287,36 @@ static int check_crontab_process(const char *cmd)
22782287
22792288static int is_crontab_available (void )
22802289{
2281- const char * cmd = "crontab" ;
2290+ char * cmd ;
22822291 int is_available ;
2292+ int ret ;
22832293
2284- if (get_schedule_cmd (& cmd , & is_available ))
2285- return is_available ;
2294+ if (get_schedule_cmd ("crontab" , & is_available , & cmd )) {
2295+ ret = is_available ;
2296+ goto out ;
2297+ }
22862298
22872299#ifdef __APPLE__
22882300 /*
22892301 * macOS has cron, but it requires special permissions and will
22902302 * create a UI alert when attempting to run this command.
22912303 */
2292- return 0 ;
2304+ ret = 0 ;
22932305#else
2294- return check_crontab_process (cmd );
2306+ ret = check_crontab_process (cmd );
22952307#endif
2308+
2309+ out :
2310+ free (cmd );
2311+ return ret ;
22962312}
22972313
22982314#define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"
22992315#define END_LINE "# END GIT MAINTENANCE SCHEDULE"
23002316
23012317static int crontab_update_schedule (int run_maintenance , int fd )
23022318{
2303- const char * cmd = "crontab" ;
2319+ char * cmd ;
23042320 int result = 0 ;
23052321 int in_old_region = 0 ;
23062322 struct child_process crontab_list = CHILD_PROCESS_INIT ;
@@ -2310,15 +2326,17 @@ static int crontab_update_schedule(int run_maintenance, int fd)
23102326 struct tempfile * tmpedit = NULL ;
23112327 int minute = get_random_minute ();
23122328
2313- get_schedule_cmd (& cmd , NULL );
2329+ get_schedule_cmd ("crontab" , NULL , & cmd );
23142330 strvec_split (& crontab_list .args , cmd );
23152331 strvec_push (& crontab_list .args , "-l" );
23162332 crontab_list .in = -1 ;
23172333 crontab_list .out = dup (fd );
23182334 crontab_list .git_cmd = 0 ;
23192335
2320- if (start_command (& crontab_list ))
2321- return error (_ ("failed to run 'crontab -l'; your system might not support 'cron'" ));
2336+ if (start_command (& crontab_list )) {
2337+ result = error (_ ("failed to run 'crontab -l'; your system might not support 'cron'" ));
2338+ goto out ;
2339+ }
23222340
23232341 /* Ignore exit code, as an empty crontab will return error. */
23242342 finish_command (& crontab_list );
@@ -2388,8 +2406,10 @@ static int crontab_update_schedule(int run_maintenance, int fd)
23882406 result = error (_ ("'crontab' died" ));
23892407 else
23902408 fclose (cron_list );
2409+
23912410out :
23922411 delete_tempfile (& tmpedit );
2412+ free (cmd );
23932413 return result ;
23942414}
23952415
@@ -2412,10 +2432,9 @@ static int real_is_systemd_timer_available(void)
24122432
24132433static int is_systemd_timer_available (void )
24142434{
2415- const char * cmd = "systemctl" ;
24162435 int is_available ;
24172436
2418- if (get_schedule_cmd (& cmd , & is_available ))
2437+ if (get_schedule_cmd ("systemctl" , & is_available , NULL ))
24192438 return is_available ;
24202439
24212440 return real_is_systemd_timer_available ();
@@ -2596,9 +2615,10 @@ static int systemd_timer_enable_unit(int enable,
25962615 enum schedule_priority schedule ,
25972616 int minute )
25982617{
2599- const char * cmd = "systemctl" ;
2618+ char * cmd = NULL ;
26002619 struct child_process child = CHILD_PROCESS_INIT ;
26012620 const char * frequency = get_frequency (schedule );
2621+ int ret ;
26022622
26032623 /*
26042624 * Disabling the systemd unit while it is already disabled makes
@@ -2609,30 +2629,43 @@ static int systemd_timer_enable_unit(int enable,
26092629 * On the other hand, enabling a systemd unit which is already enabled
26102630 * produces no error.
26112631 */
2612- if (!enable )
2632+ if (!enable ) {
26132633 child .no_stderr = 1 ;
2614- else if (systemd_timer_write_timer_file (schedule , minute ))
2615- return -1 ;
2634+ } else if (systemd_timer_write_timer_file (schedule , minute )) {
2635+ ret = -1 ;
2636+ goto out ;
2637+ }
26162638
2617- get_schedule_cmd (& cmd , NULL );
2639+ get_schedule_cmd ("systemctl" , NULL , & cmd );
26182640 strvec_split (& child .args , cmd );
26192641 strvec_pushl (& child .args , "--user" , enable ? "enable" : "disable" ,
26202642 "--now" , NULL );
26212643 strvec_pushf (& child .args , SYSTEMD_UNIT_FORMAT , frequency , "timer" );
26222644
2623- if (start_command (& child ))
2624- return error (_ ("failed to start systemctl" ));
2625- if (finish_command (& child ))
2645+ if (start_command (& child )) {
2646+ ret = error (_ ("failed to start systemctl" ));
2647+ goto out ;
2648+ }
2649+
2650+ if (finish_command (& child )) {
26262651 /*
26272652 * Disabling an already disabled systemd unit makes
26282653 * systemctl fail.
26292654 * Let's ignore this failure.
26302655 *
26312656 * Enabling an enabled systemd unit doesn't fail.
26322657 */
2633- if (enable )
2634- return error (_ ("failed to run systemctl" ));
2635- return 0 ;
2658+ if (enable ) {
2659+ ret = error (_ ("failed to run systemctl" ));
2660+ goto out ;
2661+ }
2662+ }
2663+
2664+ ret = 0 ;
2665+
2666+ out :
2667+ free (cmd );
2668+ return ret ;
26362669}
26372670
26382671/*
0 commit comments