Skip to content

Commit c3a6bad

Browse files
committed
Merge commit '742245763b' into HEAD
* commit '742245763b': docs: indicate http.sslCertType and sslKeyType maintenance: add prune-remote-refs task doc: give attr.tree a bit more visibility transport: don't ignore git-receive-pack(1) exit code on atomic push t5504: modernize test by moving heredocs into test bodies
2 parents fcae86a + 7422457 commit c3a6bad

File tree

9 files changed

+253
-35
lines changed

9 files changed

+253
-35
lines changed

Documentation/config/http.adoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,18 @@ http.sslBackend::
216216
This option is ignored if cURL lacks support for choosing the SSL
217217
backend at runtime.
218218

219+
http.sslCertType::
220+
Type of client certificate used when fetching or pushing over HTTPS.
221+
(e.g. "PEM", "DER", or "P12"). See also libcurl `CURLOPT_SSLCERTTYPE`
222+
Can be overridden by the `GIT_SSL_CERT_TYPE` environment variable.
223+
224+
http.sslKeyType::
225+
Type of client private key used when fetching or pushing over HTTPS.
226+
(e.g. "PEM", "DER", or "ENG"). Particularly useful when set to "ENG"
227+
for authenticating with PKCS#11 tokens. See also libcurl
228+
`CURLOPT_SSLCERTTYPE` . Can be overridden by the `GIT_SSL_KEY_TYPE`
229+
environment variable.
230+
219231
http.schannelCheckRevoke::
220232
Used to enforce or disable certificate revocation checks in cURL
221233
when http.sslBackend is set to "schannel". Defaults to `true` if

Documentation/git-maintenance.adoc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,26 @@ pack-refs::
158158
need to iterate across many references. See linkgit:git-pack-refs[1]
159159
for more information.
160160

161+
prune-remote-refs::
162+
The `prune-remote-refs` task runs `git remote prune` on each remote
163+
repository registered in the local repository. This task helps clean
164+
up deleted remote branches, improving the performance of operations
165+
that iterate through the refs. See linkgit:git-remote[1] for more
166+
information. This task is disabled by default.
167+
+
168+
NOTE: This task is opt-in to prevent unexpected removal of remote refs
169+
for users of linkgit:git-maintenance[1]. For most users, configuring `fetch.prune=true`
170+
is an acceptable solution, as it will automatically clean up stale remote-tracking
171+
branches during normal fetch operations. However, this task can be useful in
172+
specific scenarios:
173+
+
174+
--
175+
* When using selective fetching (e.g., `git fetch origin +foo:refs/remotes/origin/foo`)
176+
where `fetch.prune` would only affect refs that are explicitly fetched.
177+
* When third-party tools might perform unexpected full fetches, and you want
178+
periodic cleanup independently of fetch operations.
179+
--
180+
161181
OPTIONS
162182
-------
163183
--auto::

Documentation/git.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,10 @@ If you just want to run git as if it was started in `<path>` then use
228228
--attr-source=<tree-ish>::
229229
Read gitattributes from <tree-ish> instead of the worktree. See
230230
linkgit:gitattributes[5]. This is equivalent to setting the
231-
`GIT_ATTR_SOURCE` environment variable.
231+
`GIT_ATTR_SOURCE` environment variable. The `attr.tree`
232+
configuration variable is used as a fallback when this option
233+
or the environment variable are not in use.
234+
232235

233236
GIT COMMANDS
234237
------------

builtin/gc.c

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "lockfile.h"
2424
#include "parse-options.h"
2525
#include "run-command.h"
26+
#include "remote.h"
2627
#include "sigchain.h"
2728
#include "strvec.h"
2829
#include "commit.h"
@@ -921,6 +922,63 @@ static int maintenance_opt_schedule(const struct option *opt, const char *arg,
921922
return 0;
922923
}
923924

925+
struct remote_cb_data {
926+
struct maintenance_run_opts *maintenance_opts;
927+
struct string_list failed_remotes;
928+
};
929+
930+
static void report_failed_remotes(struct string_list *failed_remotes,
931+
const char *action_name)
932+
{
933+
if (failed_remotes->nr) {
934+
int i;
935+
struct strbuf msg = STRBUF_INIT;
936+
strbuf_addf(&msg, _("failed to %s the following remotes: "),
937+
action_name);
938+
for (i = 0; i < failed_remotes->nr; i++) {
939+
if (i)
940+
strbuf_addstr(&msg, ", ");
941+
strbuf_addstr(&msg, failed_remotes->items[i].string);
942+
}
943+
error("%s", msg.buf);
944+
strbuf_release(&msg);
945+
}
946+
}
947+
948+
static int prune_remote(struct remote *remote, void *cb_data)
949+
{
950+
struct child_process child = CHILD_PROCESS_INIT;
951+
struct remote_cb_data *data = cb_data;
952+
953+
if (!remote->url.nr)
954+
return 0;
955+
956+
child.git_cmd = 1;
957+
strvec_pushl(&child.args, "remote", "prune", remote->name, NULL);
958+
959+
if (run_command(&child))
960+
string_list_append(&data->failed_remotes, remote->name);
961+
962+
return 0;
963+
}
964+
965+
static int maintenance_task_prune_remote(struct maintenance_run_opts *opts,
966+
struct gc_config *cfg UNUSED)
967+
{
968+
struct remote_cb_data cbdata = { .maintenance_opts = opts,
969+
.failed_remotes = STRING_LIST_INIT_DUP };
970+
971+
int result;
972+
result = for_each_remote(prune_remote, &cbdata);
973+
974+
report_failed_remotes(&cbdata.failed_remotes, "prune");
975+
if (cbdata.failed_remotes.nr)
976+
result = 1;
977+
978+
string_list_clear(&cbdata.failed_remotes, 0);
979+
return result;
980+
}
981+
924982
/* Remember to update object flag allocation in object.h */
925983
#define SEEN (1u<<0)
926984

@@ -1041,8 +1099,8 @@ static int maintenance_task_commit_graph(struct maintenance_run_opts *opts,
10411099

10421100
static int fetch_remote(struct remote *remote, void *cbdata)
10431101
{
1044-
struct maintenance_run_opts *opts = cbdata;
10451102
struct child_process child = CHILD_PROCESS_INIT;
1103+
struct remote_cb_data *data = cbdata;
10461104

10471105
if (remote->skip_default_update)
10481106
return 0;
@@ -1053,21 +1111,34 @@ static int fetch_remote(struct remote *remote, void *cbdata)
10531111
"--no-write-fetch-head", "--recurse-submodules=no",
10541112
NULL);
10551113

1056-
if (opts->quiet)
1114+
if (data->maintenance_opts->quiet)
10571115
strvec_push(&child.args, "--quiet");
10581116

1059-
return !!run_command(&child);
1117+
if (run_command(&child))
1118+
string_list_append(&data->failed_remotes, remote->name);
1119+
1120+
return 0;
10601121
}
10611122

10621123
static int maintenance_task_prefetch(struct maintenance_run_opts *opts,
10631124
struct gc_config *cfg UNUSED)
10641125
{
1065-
if (for_each_remote(fetch_remote, opts)) {
1066-
error(_("failed to prefetch remotes"));
1067-
return 1;
1126+
struct remote_cb_data cbdata = { .maintenance_opts = opts,
1127+
.failed_remotes = STRING_LIST_INIT_DUP };
1128+
1129+
int result = 0;
1130+
1131+
if (for_each_remote(fetch_remote, &cbdata)) {
1132+
error(_("failed to prefetch some remotes"));
1133+
result = 1;
10681134
}
10691135

1070-
return 0;
1136+
report_failed_remotes(&cbdata.failed_remotes, "prefetch");
1137+
if (cbdata.failed_remotes.nr)
1138+
result = 1;
1139+
1140+
string_list_clear(&cbdata.failed_remotes, 0);
1141+
return result;
10711142
}
10721143

10731144
static int maintenance_task_gc(struct maintenance_run_opts *opts,
@@ -1383,6 +1454,7 @@ enum maintenance_task_label {
13831454
TASK_GC,
13841455
TASK_COMMIT_GRAPH,
13851456
TASK_PACK_REFS,
1457+
TASK_PRUNE_REMOTE_REFS,
13861458

13871459
/* Leave as final value */
13881460
TASK__COUNT
@@ -1419,6 +1491,10 @@ static struct maintenance_task tasks[] = {
14191491
maintenance_task_pack_refs,
14201492
pack_refs_condition,
14211493
},
1494+
[TASK_PRUNE_REMOTE_REFS] = {
1495+
"prune-remote-refs",
1496+
maintenance_task_prune_remote,
1497+
},
14221498
};
14231499

14241500
static int compare_tasks_by_selection(const void *a_, const void *b_)
@@ -1513,6 +1589,8 @@ static void initialize_maintenance_strategy(void)
15131589
tasks[TASK_LOOSE_OBJECTS].schedule = SCHEDULE_DAILY;
15141590
tasks[TASK_PACK_REFS].enabled = 1;
15151591
tasks[TASK_PACK_REFS].schedule = SCHEDULE_WEEKLY;
1592+
tasks[TASK_PRUNE_REMOTE_REFS].enabled = 0;
1593+
tasks[TASK_PRUNE_REMOTE_REFS].schedule = SCHEDULE_DAILY;
15161594
}
15171595
}
15181596

send-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ int send_pack(struct repository *r,
632632
reject_atomic_push(remote_refs, args->send_mirror);
633633
error("atomic push failed for ref %s. status: %d",
634634
ref->name, ref->status);
635-
ret = args->porcelain ? 0 : -1;
635+
ret = -1;
636636
goto out;
637637
}
638638
/* else fallthrough */

t/t5504-fetch-receive-strict.sh

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@ test_expect_success 'fetch with transfer.fsckobjects' '
6464
)
6565
'
6666

67-
cat >exp <<EOF
68-
To dst
69-
! refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects)
70-
Done
71-
EOF
72-
7367
test_expect_success 'push without strict' '
7468
rm -rf dst &&
7569
git init dst &&
@@ -78,6 +72,11 @@ test_expect_success 'push without strict' '
7872
git config fetch.fsckobjects false &&
7973
git config transfer.fsckobjects false
8074
) &&
75+
cat >exp <<-EOF &&
76+
To dst
77+
! refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects)
78+
Done
79+
EOF
8180
test_must_fail git push --porcelain dst main:refs/heads/test >act &&
8281
test_cmp exp act
8382
'
@@ -94,11 +93,6 @@ test_expect_success 'push with !receive.fsckobjects' '
9493
test_cmp exp act
9594
'
9695

97-
cat >exp <<EOF
98-
To dst
99-
! refs/heads/main:refs/heads/test [remote rejected] (unpacker error)
100-
EOF
101-
10296
test_expect_success 'push with receive.fsckobjects' '
10397
rm -rf dst &&
10498
git init dst &&
@@ -107,6 +101,11 @@ test_expect_success 'push with receive.fsckobjects' '
107101
git config receive.fsckobjects true &&
108102
git config transfer.fsckobjects false
109103
) &&
104+
cat >exp <<-EOF &&
105+
To dst
106+
! refs/heads/main:refs/heads/test [remote rejected] (unpacker error)
107+
Done
108+
EOF
110109
test_must_fail git push --porcelain dst main:refs/heads/test >act &&
111110
test_cmp exp act
112111
'
@@ -129,15 +128,14 @@ test_expect_success 'repair the "corrupt or missing" object' '
129128
git fsck
130129
'
131130

132-
cat >bogus-commit <<EOF
133-
tree $EMPTY_TREE
134-
author Bugs Bunny 1234567890 +0000
135-
committer Bugs Bunny <[email protected]> 1234567890 +0000
136-
137-
This commit object intentionally broken
138-
EOF
139-
140131
test_expect_success 'setup bogus commit' '
132+
cat >bogus-commit <<-EOF &&
133+
tree $EMPTY_TREE
134+
author Bugs Bunny 1234567890 +0000
135+
committer Bugs Bunny <[email protected]> 1234567890 +0000
136+
137+
This commit object intentionally broken
138+
EOF
141139
commit="$(git hash-object --literally -t commit -w --stdin <bogus-commit)"
142140
'
143141

t/t5543-atomic-push.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,34 @@ test_expect_success 'atomic push reports (reject by non-ff)' '
280280
test_cmp expect actual
281281
'
282282

283+
test_expect_success 'atomic push reports exit code failure' '
284+
write_script receive-pack-wrapper <<-\EOF &&
285+
git-receive-pack "$@"
286+
exit 1
287+
EOF
288+
test_must_fail git -C workbench push --atomic \
289+
--receive-pack="${SQ}$(pwd)${SQ}/receive-pack-wrapper" \
290+
up HEAD:refs/heads/no-conflict 2>err &&
291+
cat >expect <<-EOF &&
292+
To ../upstream
293+
* [new branch] HEAD -> no-conflict
294+
error: failed to push some refs to ${SQ}../upstream${SQ}
295+
EOF
296+
test_cmp expect err
297+
'
298+
299+
test_expect_success 'atomic push reports exit code failure with porcelain' '
300+
write_script receive-pack-wrapper <<-\EOF &&
301+
git-receive-pack "$@"
302+
exit 1
303+
EOF
304+
test_must_fail git -C workbench push --atomic --porcelain \
305+
--receive-pack="${SQ}$(pwd)${SQ}/receive-pack-wrapper" \
306+
up HEAD:refs/heads/no-conflict-porcelain 2>err &&
307+
cat >expect <<-EOF &&
308+
error: failed to push some refs to ${SQ}../upstream${SQ}
309+
EOF
310+
test_cmp expect err
311+
'
312+
283313
test_done

0 commit comments

Comments
 (0)