Skip to content

Commit 4b4d97c

Browse files
committed
Merge branch 'ds/scalar-unregister-idempotent'
"scalar unregister" in a repository that is already been unregistered reported an error. * ds/scalar-unregister-idempotent: string-list: document iterator behavior on NULL input gc: replace config subprocesses with API calls scalar: make 'unregister' idempotent maintenance: add 'unregister --force'
2 parents dc6dd55 + d151f0c commit 4b4d97c

File tree

6 files changed

+96
-36
lines changed

6 files changed

+96
-36
lines changed

Documentation/git-maintenance.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ SYNOPSIS
1111
[verse]
1212
'git maintenance' run [<options>]
1313
'git maintenance' start [--scheduler=<scheduler>]
14-
'git maintenance' (stop|register|unregister)
14+
'git maintenance' (stop|register|unregister) [<options>]
1515

1616

1717
DESCRIPTION
@@ -79,6 +79,10 @@ unregister::
7979
Remove the current repository from background maintenance. This
8080
only removes the repository from the configured list. It does not
8181
stop the background maintenance processes from running.
82+
+
83+
The `unregister` subcommand will report an error if the current repository
84+
is not already registered. Use the `--force` option to return success even
85+
when the current repository is not registered.
8286

8387
TASKS
8488
-----

builtin/gc.c

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,11 +1470,12 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
14701470
struct option options[] = {
14711471
OPT_END(),
14721472
};
1473-
int rc;
1473+
int found = 0;
1474+
const char *key = "maintenance.repo";
14741475
char *config_value;
1475-
struct child_process config_set = CHILD_PROCESS_INIT;
1476-
struct child_process config_get = CHILD_PROCESS_INIT;
14771476
char *maintpath = get_maintpath();
1477+
struct string_list_item *item;
1478+
const struct string_list *list;
14781479

14791480
argc = parse_options(argc, argv, prefix, options,
14801481
builtin_maintenance_register_usage, 0);
@@ -1491,60 +1492,95 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)
14911492
else
14921493
git_config_set("maintenance.strategy", "incremental");
14931494

1494-
config_get.git_cmd = 1;
1495-
strvec_pushl(&config_get.args, "config", "--global", "--get",
1496-
"--fixed-value", "maintenance.repo", maintpath, NULL);
1497-
config_get.out = -1;
1498-
1499-
if (start_command(&config_get)) {
1500-
rc = error(_("failed to run 'git config'"));
1501-
goto done;
1495+
list = git_config_get_value_multi(key);
1496+
if (list) {
1497+
for_each_string_list_item(item, list) {
1498+
if (!strcmp(maintpath, item->string)) {
1499+
found = 1;
1500+
break;
1501+
}
1502+
}
15021503
}
15031504

1504-
/* We already have this value in our config! */
1505-
if (!finish_command(&config_get)) {
1506-
rc = 0;
1507-
goto done;
1505+
if (!found) {
1506+
int rc;
1507+
char *user_config, *xdg_config;
1508+
git_global_config(&user_config, &xdg_config);
1509+
if (!user_config)
1510+
die(_("$HOME not set"));
1511+
rc = git_config_set_multivar_in_file_gently(
1512+
user_config, "maintenance.repo", maintpath,
1513+
CONFIG_REGEX_NONE, 0);
1514+
free(user_config);
1515+
free(xdg_config);
1516+
1517+
if (rc)
1518+
die(_("unable to add '%s' value of '%s'"),
1519+
key, maintpath);
15081520
}
15091521

1510-
config_set.git_cmd = 1;
1511-
strvec_pushl(&config_set.args, "config", "--add", "--global", "maintenance.repo",
1512-
maintpath, NULL);
1513-
1514-
rc = run_command(&config_set);
1515-
1516-
done:
15171522
free(maintpath);
1518-
return rc;
1523+
return 0;
15191524
}
15201525

15211526
static char const * const builtin_maintenance_unregister_usage[] = {
1522-
"git maintenance unregister",
1527+
"git maintenance unregister [--force]",
15231528
NULL
15241529
};
15251530

15261531
static int maintenance_unregister(int argc, const char **argv, const char *prefix)
15271532
{
1533+
int force = 0;
15281534
struct option options[] = {
1535+
OPT__FORCE(&force,
1536+
N_("return success even if repository was not registered"),
1537+
PARSE_OPT_NOCOMPLETE),
15291538
OPT_END(),
15301539
};
1531-
int rc;
1532-
struct child_process config_unset = CHILD_PROCESS_INIT;
1540+
const char *key = "maintenance.repo";
15331541
char *maintpath = get_maintpath();
1542+
int found = 0;
1543+
struct string_list_item *item;
1544+
const struct string_list *list;
15341545

15351546
argc = parse_options(argc, argv, prefix, options,
15361547
builtin_maintenance_unregister_usage, 0);
15371548
if (argc)
15381549
usage_with_options(builtin_maintenance_unregister_usage,
15391550
options);
15401551

1541-
config_unset.git_cmd = 1;
1542-
strvec_pushl(&config_unset.args, "config", "--global", "--unset",
1543-
"--fixed-value", "maintenance.repo", maintpath, NULL);
1552+
list = git_config_get_value_multi(key);
1553+
if (list) {
1554+
for_each_string_list_item(item, list) {
1555+
if (!strcmp(maintpath, item->string)) {
1556+
found = 1;
1557+
break;
1558+
}
1559+
}
1560+
}
1561+
1562+
if (found) {
1563+
int rc;
1564+
char *user_config, *xdg_config;
1565+
git_global_config(&user_config, &xdg_config);
1566+
if (!user_config)
1567+
die(_("$HOME not set"));
1568+
rc = git_config_set_multivar_in_file_gently(
1569+
user_config, key, NULL, maintpath,
1570+
CONFIG_FLAGS_MULTI_REPLACE | CONFIG_FLAGS_FIXED_VALUE);
1571+
free(user_config);
1572+
free(xdg_config);
1573+
1574+
if (rc &&
1575+
(!force || rc == CONFIG_NOTHING_SET))
1576+
die(_("unable to unset '%s' value of '%s'"),
1577+
key, maintpath);
1578+
} else if (!force) {
1579+
die(_("repository '%s' is not registered"), maintpath);
1580+
}
15441581

1545-
rc = run_command(&config_unset);
15461582
free(maintpath);
1547-
return rc;
1583+
return 0;
15481584
}
15491585

15501586
static const char *get_frequency(enum schedule_priority schedule)

scalar.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,10 @@ static int set_recommended_config(int reconfigure)
207207

208208
static int toggle_maintenance(int enable)
209209
{
210-
return run_git("maintenance", enable ? "start" : "unregister", NULL);
210+
return run_git("maintenance",
211+
enable ? "start" : "unregister",
212+
enable ? NULL : "--force",
213+
NULL);
211214
}
212215

213216
static int add_or_remove_enlistment(int add)

string-list.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
141141
int for_each_string_list(struct string_list *list,
142142
string_list_each_func_t func, void *cb_data);
143143

144-
/** Iterate over each item, as a macro. */
144+
/**
145+
* Iterate over each item, as a macro.
146+
*
147+
* Be sure that 'list' is non-NULL. The macro cannot perform NULL
148+
* checks due to -Werror=address errors.
149+
*/
145150
#define for_each_string_list_item(item,list) \
146151
for (item = (list)->items; \
147152
item && item < (list)->items + (list)->nr; \

t/t7900-maintenance.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,11 @@ test_expect_success 'maintenance.strategy inheritance' '
480480

481481
test_expect_success 'register and unregister' '
482482
test_when_finished git config --global --unset-all maintenance.repo &&
483+
484+
test_must_fail git maintenance unregister 2>err &&
485+
grep "is not registered" err &&
486+
git maintenance unregister --force &&
487+
483488
git config --global --add maintenance.repo /existing1 &&
484489
git config --global --add maintenance.repo /existing2 &&
485490
git config --global --get-all maintenance.repo >before &&
@@ -493,7 +498,11 @@ test_expect_success 'register and unregister' '
493498
494499
git maintenance unregister &&
495500
git config --global --get-all maintenance.repo >actual &&
496-
test_cmp before actual
501+
test_cmp before actual &&
502+
503+
test_must_fail git maintenance unregister 2>err &&
504+
grep "is not registered" err &&
505+
git maintenance unregister --force
497506
'
498507

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

t/t9210-scalar.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ test_expect_success 'scalar unregister' '
116116
test_must_fail git config --get --global --fixed-value \
117117
maintenance.repo "$(pwd)/vanish/src" &&
118118
scalar list >scalar.repos &&
119-
! grep -F "$(pwd)/vanish/src" scalar.repos
119+
! grep -F "$(pwd)/vanish/src" scalar.repos &&
120+
121+
# scalar unregister should be idempotent
122+
scalar unregister vanish
120123
'
121124

122125
test_expect_success 'set up repository to clone' '

0 commit comments

Comments
 (0)