Skip to content

Commit 56a64fc

Browse files
committed
Merge branch 'rp/maintenance-qol'
'git maintenance register' is taught to write configuration to an arbitrary path, and 'git for-each-repo' is taught to expand tilde characters in paths. * rp/maintenance-qol: builtin/gc.c: fix use-after-free in maintenance_unregister() maintenance --unregister: fix uninit'd data use & -Wdeclaration-after-statement maintenance: add option to register in a specific config for-each-repo: interpolate repo path arguments
2 parents 3b041ea + 03744bb commit 56a64fc

File tree

5 files changed

+69
-22
lines changed

5 files changed

+69
-22
lines changed

Documentation/git-maintenance.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ stop::
5050
the background maintenance is restarted later.
5151

5252
register::
53-
Initialize Git config values so any scheduled maintenance will
54-
start running on this repository. This adds the repository to the
55-
`maintenance.repo` config variable in the current user's global
56-
config and enables some recommended configuration values for
57-
`maintenance.<task>.schedule`. The tasks that are enabled are safe
58-
for running in the background without disrupting foreground
59-
processes.
53+
Initialize Git config values so any scheduled maintenance will start
54+
running on this repository. This adds the repository to the
55+
`maintenance.repo` config variable in the current user's global config,
56+
or the config specified by --config-file option, and enables some
57+
recommended configuration values for `maintenance.<task>.schedule`. The
58+
tasks that are enabled are safe for running in the background without
59+
disrupting foreground processes.
6060
+
6161
The `register` subcommand will also set the `maintenance.strategy` config
6262
value to `incremental`, if this value is not previously set. The

builtin/for-each-repo.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv)
1414
{
1515
int i;
1616
struct child_process child = CHILD_PROCESS_INIT;
17+
char *abspath = interpolate_path(path, 0);
1718

1819
child.git_cmd = 1;
19-
strvec_pushl(&child.args, "-C", path, NULL);
20+
strvec_pushl(&child.args, "-C", abspath, NULL);
2021

2122
for (i = 0; i < argc; i++)
2223
strvec_push(&child.args, argv[i]);
2324

25+
free(abspath);
26+
2427
return run_command(&child);
2528
}
2629

builtin/gc.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,13 +1480,15 @@ static char *get_maintpath(void)
14801480
}
14811481

14821482
static char const * const builtin_maintenance_register_usage[] = {
1483-
"git maintenance register",
1483+
"git maintenance register [--config-file <path>]",
14841484
NULL
14851485
};
14861486

14871487
static int maintenance_register(int argc, const char **argv, const char *prefix)
14881488
{
1489+
char *config_file = NULL;
14891490
struct option options[] = {
1491+
OPT_STRING(0, "config-file", &config_file, N_("file"), N_("use given config file")),
14901492
OPT_END(),
14911493
};
14921494
int found = 0;
@@ -1523,12 +1525,16 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
15231525

15241526
if (!found) {
15251527
int rc;
1526-
char *user_config, *xdg_config;
1527-
git_global_config(&user_config, &xdg_config);
1528-
if (!user_config)
1529-
die(_("$HOME not set"));
1528+
char *user_config = NULL, *xdg_config = NULL;
1529+
1530+
if (!config_file) {
1531+
git_global_config(&user_config, &xdg_config);
1532+
config_file = user_config;
1533+
if (!user_config)
1534+
die(_("$HOME not set"));
1535+
}
15301536
rc = git_config_set_multivar_in_file_gently(
1531-
user_config, "maintenance.repo", maintpath,
1537+
config_file, "maintenance.repo", maintpath,
15321538
CONFIG_REGEX_NONE, 0);
15331539
free(user_config);
15341540
free(xdg_config);
@@ -1543,14 +1549,16 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
15431549
}
15441550

15451551
static char const * const builtin_maintenance_unregister_usage[] = {
1546-
"git maintenance unregister [--force]",
1552+
"git maintenance unregister [--config-file <path>] [--force]",
15471553
NULL
15481554
};
15491555

15501556
static int maintenance_unregister(int argc, const char **argv, const char *prefix)
15511557
{
15521558
int force = 0;
1559+
char *config_file = NULL;
15531560
struct option options[] = {
1561+
OPT_STRING(0, "config-file", &config_file, N_("file"), N_("use given config file")),
15541562
OPT__FORCE(&force,
15551563
N_("return success even if repository was not registered"),
15561564
PARSE_OPT_NOCOMPLETE),
@@ -1561,14 +1569,21 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
15611569
int found = 0;
15621570
struct string_list_item *item;
15631571
const struct string_list *list;
1572+
struct config_set cs = { { 0 } };
15641573

15651574
argc = parse_options(argc, argv, prefix, options,
15661575
builtin_maintenance_unregister_usage, 0);
15671576
if (argc)
15681577
usage_with_options(builtin_maintenance_unregister_usage,
15691578
options);
15701579

1571-
list = git_config_get_value_multi(key);
1580+
if (config_file) {
1581+
git_configset_init(&cs);
1582+
git_configset_add_file(&cs, config_file);
1583+
list = git_configset_get_value_multi(&cs, key);
1584+
} else {
1585+
list = git_config_get_value_multi(key);
1586+
}
15721587
if (list) {
15731588
for_each_string_list_item(item, list) {
15741589
if (!strcmp(maintpath, item->string)) {
@@ -1580,12 +1595,15 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
15801595

15811596
if (found) {
15821597
int rc;
1583-
char *user_config, *xdg_config;
1584-
git_global_config(&user_config, &xdg_config);
1585-
if (!user_config)
1586-
die(_("$HOME not set"));
1598+
char *user_config = NULL, *xdg_config = NULL;
1599+
if (!config_file) {
1600+
git_global_config(&user_config, &xdg_config);
1601+
config_file = user_config;
1602+
if (!user_config)
1603+
die(_("$HOME not set"));
1604+
}
15871605
rc = git_config_set_multivar_in_file_gently(
1588-
user_config, key, NULL, maintpath,
1606+
config_file, key, NULL, maintpath,
15891607
CONFIG_FLAGS_MULTI_REPLACE | CONFIG_FLAGS_FIXED_VALUE);
15901608
free(user_config);
15911609
free(xdg_config);
@@ -1598,6 +1616,7 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
15981616
die(_("repository '%s' is not registered"), maintpath);
15991617
}
16001618

1619+
git_configset_clear(&cs);
16011620
free(maintpath);
16021621
return 0;
16031622
}

t/t0068-for-each-repo.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@ test_expect_success 'run based on configured value' '
88
git init one &&
99
git init two &&
1010
git init three &&
11+
git init ~/four &&
1112
git -C two commit --allow-empty -m "DID NOT RUN" &&
1213
git config run.key "$TRASH_DIRECTORY/one" &&
1314
git config --add run.key "$TRASH_DIRECTORY/three" &&
15+
git config --add run.key "~/four" &&
1416
git for-each-repo --config=run.key commit --allow-empty -m "ran" &&
1517
git -C one log -1 --pretty=format:%s >message &&
1618
grep ran message &&
1719
git -C two log -1 --pretty=format:%s >message &&
1820
! grep ran message &&
1921
git -C three log -1 --pretty=format:%s >message &&
2022
grep ran message &&
23+
git -C ~/four log -1 --pretty=format:%s >message &&
24+
grep ran message &&
2125
git for-each-repo --config=run.key -- commit --allow-empty -m "ran again" &&
2226
git -C one log -1 --pretty=format:%s >message &&
2327
grep again message &&
2428
git -C two log -1 --pretty=format:%s >message &&
2529
! grep again message &&
2630
git -C three log -1 --pretty=format:%s >message &&
31+
grep again message &&
32+
git -C ~/four log -1 --pretty=format:%s >message &&
2733
grep again message
2834
'
2935

t/t7900-maintenance.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,28 @@ test_expect_success 'register and unregister' '
500500
git config --global --get-all maintenance.repo >actual &&
501501
test_cmp before actual &&
502502
503+
git config --file ./other --add maintenance.repo /existing1 &&
504+
git config --file ./other --add maintenance.repo /existing2 &&
505+
git config --file ./other --get-all maintenance.repo >before &&
506+
507+
git maintenance register --config-file ./other &&
508+
test_cmp_config false maintenance.auto &&
509+
git config --file ./other --get-all maintenance.repo >between &&
510+
cp before expect &&
511+
pwd >>expect &&
512+
test_cmp expect between &&
513+
514+
git maintenance unregister --config-file ./other &&
515+
git config --file ./other --get-all maintenance.repo >actual &&
516+
test_cmp before actual &&
517+
503518
test_must_fail git maintenance unregister 2>err &&
504519
grep "is not registered" err &&
505-
git maintenance unregister --force
520+
git maintenance unregister --force &&
521+
522+
test_must_fail git maintenance unregister --config-file ./other 2>err &&
523+
grep "is not registered" err &&
524+
git maintenance unregister --config-file ./other --force
506525
'
507526

508527
test_expect_success !MINGW 'register and unregister with regex metacharacters' '

0 commit comments

Comments
 (0)