Skip to content

Commit b52518a

Browse files
committed
Merge branch 'ds/background-maintenance-with-credential' into seen
* ds/background-maintenance-with-credential: scalar: configure maintenance during 'reconfigure' maintenance: add custom config to background jobs credential: add new interactive config option
2 parents 148f673 + b9183b0 commit b52518a

File tree

7 files changed

+114
-12
lines changed

7 files changed

+114
-12
lines changed

Documentation/config/credential.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ credential.helper::
99
Note that multiple helpers may be defined. See linkgit:gitcredentials[7]
1010
for details and examples.
1111

12+
credential.interactive::
13+
By default, Git and any configured credential helpers will ask for
14+
user input when new credentials are required. Many of these helpers
15+
will succeed based on stored credentials if those credentials are
16+
still valid. To avoid the possibility of user interactivity from
17+
Git, set `credential.interactive=false`. Some credential helpers
18+
respect this option as well.
19+
1220
credential.useHttpPath::
1321
When acquiring credentials, consider the "path" component of an http
1422
or https URL to be important. Defaults to false. See

builtin/gc.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,42 @@ static const char *get_frequency(enum schedule_priority schedule)
17681768
}
17691769
}
17701770

1771+
static const char *extraconfig[] = {
1772+
"credential.interactive=false",
1773+
"core.askPass=true", /* 'true' returns success, but no output. */
1774+
NULL
1775+
};
1776+
1777+
static const char *get_extra_config_parameters(void) {
1778+
static const char *result = NULL;
1779+
struct strbuf builder = STRBUF_INIT;
1780+
1781+
if (result)
1782+
return result;
1783+
1784+
for (const char **s = extraconfig; s && *s; s++)
1785+
strbuf_addf(&builder, "-c %s ", *s);
1786+
1787+
result = strbuf_detach(&builder, NULL);
1788+
return result;
1789+
}
1790+
1791+
static const char *get_extra_launchctl_strings(void) {
1792+
static const char *result = NULL;
1793+
struct strbuf builder = STRBUF_INIT;
1794+
1795+
if (result)
1796+
return result;
1797+
1798+
for (const char **s = extraconfig; s && *s; s++) {
1799+
strbuf_addstr(&builder, "<string>-c</string>\n");
1800+
strbuf_addf(&builder, "<string>%s</string>\n", *s);
1801+
}
1802+
1803+
result = strbuf_detach(&builder, NULL);
1804+
return result;
1805+
}
1806+
17711807
/*
17721808
* get_schedule_cmd` reads the GIT_TEST_MAINT_SCHEDULER environment variable
17731809
* to mock the schedulers that `git maintenance start` rely on.
@@ -1981,6 +2017,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
19812017
"<array>\n"
19822018
"<string>%s/git</string>\n"
19832019
"<string>--exec-path=%s</string>\n"
2020+
"%s" /* For extra config parameters. */
19842021
"<string>for-each-repo</string>\n"
19852022
"<string>--keep-going</string>\n"
19862023
"<string>--config=maintenance.repo</string>\n"
@@ -1990,7 +2027,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
19902027
"</array>\n"
19912028
"<key>StartCalendarInterval</key>\n"
19922029
"<array>\n";
1993-
strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency);
2030+
strbuf_addf(&plist, preamble, name, exec_path, exec_path,
2031+
get_extra_launchctl_strings(), frequency);
19942032

19952033
switch (schedule) {
19962034
case SCHEDULE_HOURLY:
@@ -2226,11 +2264,12 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
22262264
"<Actions Context=\"Author\">\n"
22272265
"<Exec>\n"
22282266
"<Command>\"%s\\headless-git.exe\"</Command>\n"
2229-
"<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
2267+
"<Arguments>--exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
22302268
"</Exec>\n"
22312269
"</Actions>\n"
22322270
"</Task>\n";
2233-
fprintf(tfile->fp, xml, exec_path, exec_path, frequency);
2271+
fprintf(tfile->fp, xml, exec_path, exec_path,
2272+
get_extra_config_parameters(), frequency);
22342273
strvec_split(&child.args, cmd);
22352274
strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml",
22362275
get_tempfile_path(tfile), NULL);
@@ -2381,8 +2420,8 @@ static int crontab_update_schedule(int run_maintenance, int fd)
23812420
"# replaced in the future by a Git command.\n\n");
23822421

23832422
strbuf_addf(&line_format,
2384-
"%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n",
2385-
exec_path, exec_path);
2423+
"%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n",
2424+
exec_path, exec_path, get_extra_config_parameters());
23862425
fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly");
23872426
fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily");
23882427
fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly");
@@ -2583,7 +2622,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
25832622
"\n"
25842623
"[Service]\n"
25852624
"Type=oneshot\n"
2586-
"ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n"
2625+
"ExecStart=\"%s/git\" --exec-path=\"%s\" %s for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n"
25872626
"LockPersonality=yes\n"
25882627
"MemoryDenyWriteExecute=yes\n"
25892628
"NoNewPrivileges=yes\n"
@@ -2593,7 +2632,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
25932632
"RestrictSUIDSGID=yes\n"
25942633
"SystemCallArchitectures=native\n"
25952634
"SystemCallFilter=@system-service\n";
2596-
if (fprintf(file, unit, exec_path, exec_path) < 0) {
2635+
if (fprintf(file, unit, exec_path, exec_path, get_extra_config_parameters()) < 0) {
25972636
error(_("failed to write to '%s'"), filename);
25982637
fclose(file);
25992638
goto error;

credential.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "strbuf.h"
1414
#include "urlmatch.h"
1515
#include "git-compat-util.h"
16+
#include "trace2.h"
17+
#include "repository.h"
1618

1719
void credential_init(struct credential *c)
1820
{
@@ -251,14 +253,36 @@ static char *credential_ask_one(const char *what, struct credential *c,
251253
return xstrdup(r);
252254
}
253255

254-
static void credential_getpass(struct credential *c)
256+
static int credential_getpass(struct credential *c)
255257
{
258+
int interactive;
259+
char *value;
260+
if (!git_config_get_maybe_bool("credential.interactive", &interactive) &&
261+
!interactive) {
262+
trace2_data_intmax("credential", the_repository,
263+
"interactive/skipped", 1);
264+
return -1;
265+
}
266+
if (!git_config_get_string("credential.interactive", &value)) {
267+
int same = !strcmp(value, "never");
268+
free(value);
269+
if (same) {
270+
trace2_data_intmax("credential", the_repository,
271+
"interactive/skipped", 1);
272+
return -1;
273+
}
274+
}
275+
276+
trace2_region_enter("credential", "interactive", the_repository);
256277
if (!c->username)
257278
c->username = credential_ask_one("Username", c,
258279
PROMPT_ASKPASS|PROMPT_ECHO);
259280
if (!c->password)
260281
c->password = credential_ask_one("Password", c,
261282
PROMPT_ASKPASS);
283+
trace2_region_leave("credential", "interactive", the_repository);
284+
285+
return 0;
262286
}
263287

264288
int credential_has_capability(const struct credential_capability *capa,
@@ -501,8 +525,8 @@ void credential_fill(struct credential *c, int all_capabilities)
501525
c->helpers.items[i].string);
502526
}
503527

504-
credential_getpass(c);
505-
if (!c->username && !c->password && !c->credential)
528+
if (credential_getpass(c) ||
529+
(!c->username && !c->password && !c->credential))
506530
die("unable to get password from user");
507531
}
508532

scalar.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ static int cmd_reconfigure(int argc, const char **argv)
733733

734734
the_repository = old_repo;
735735

736+
if (toggle_maintenance(1) >= 0)
737+
succeeded = 1;
738+
736739
loop_end:
737740
if (!succeeded) {
738741
res = -1;

t/t5551-http-fetch-smart.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,28 @@ test_expect_success 'clone from password-protected repository' '
186186
test_cmp expect actual
187187
'
188188

189+
test_expect_success 'credential.interactive=false skips askpass' '
190+
set_askpass bogus nonsense &&
191+
(
192+
GIT_TRACE2_EVENT="$(pwd)/interactive-true" &&
193+
export GIT_TRACE2_EVENT &&
194+
test_must_fail git clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-true-dir &&
195+
test_region credential interactive interactive-true &&
196+
197+
GIT_TRACE2_EVENT="$(pwd)/interactive-false" &&
198+
export GIT_TRACE2_EVENT &&
199+
test_must_fail git -c credential.interactive=false \
200+
clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-false-dir &&
201+
test_region ! credential interactive interactive-false &&
202+
203+
GIT_TRACE2_EVENT="$(pwd)/interactive-never" &&
204+
export GIT_TRACE2_EVENT &&
205+
test_must_fail git -c credential.interactive=never \
206+
clone --bare "$HTTPD_URL/auth/smart/repo.git" interactive-never-dir &&
207+
test_region ! credential interactive interactive-never
208+
)
209+
'
210+
189211
test_expect_success 'clone from auth-only-for-push repository' '
190212
echo two >expect &&
191213
set_askpass wrong &&

t/t7900-maintenance.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,9 @@ test_expect_success 'start and stop Linux/systemd maintenance' '
826826
test_systemd_analyze_verify "systemd/user/[email protected]" &&
827827
test_systemd_analyze_verify "systemd/user/[email protected]" &&
828828
829+
grep "core.askPass=true" "systemd/user/[email protected]" &&
830+
grep "credential.interactive=false" "systemd/user/[email protected]" &&
831+
829832
printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect &&
830833
test_cmp expect args &&
831834

t/t9210-scalar.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,11 @@ test_expect_success 'scalar reconfigure' '
194194
scalar reconfigure one &&
195195
test true = "$(git -C one/src config core.preloadIndex)" &&
196196
git -C one/src config core.preloadIndex false &&
197-
scalar reconfigure -a &&
198-
test true = "$(git -C one/src config core.preloadIndex)"
197+
rm one/src/cron.txt &&
198+
GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a &&
199+
test_path_is_file one/src/cron.txt &&
200+
test true = "$(git -C one/src config core.preloadIndex)" &&
201+
test_subcommand git maintenance start <reconfigure
199202
'
200203

201204
test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '

0 commit comments

Comments
 (0)