Merge branch 'jk/remote-tracking-ref-leakfix' into hn/status-compare-with-push

* jk/remote-tracking-ref-leakfix:
  remote: always allocate branch.push_tracking_ref
  remote: fix leak in branch_get_push_1() with invalid "simple" config
  remote: drop const return of tracking_for_push_dest()
  remote: return non-const pointer from error_buf()
This commit is contained in:
Junio C Hamano 2026-01-20 13:35:47 -08:00
commit 2aa9b75b43
3 changed files with 24 additions and 11 deletions

View File

@ -272,6 +272,7 @@ static void branch_release(struct branch *branch)
free((char *)branch->refname);
free(branch->remote_name);
free(branch->pushremote_name);
free(branch->push_tracking_ref);
merge_clear(branch);
}
@ -1838,7 +1839,7 @@ int branch_merge_matches(struct branch *branch,
}
__attribute__((format (printf,2,3)))
static const char *error_buf(struct strbuf *err, const char *fmt, ...)
static char *error_buf(struct strbuf *err, const char *fmt, ...)
{
if (err) {
va_list ap;
@ -1876,9 +1877,9 @@ const char *branch_get_upstream(struct branch *branch, struct strbuf *err)
return branch->merge[0]->dst;
}
static const char *tracking_for_push_dest(struct remote *remote,
const char *refname,
struct strbuf *err)
static char *tracking_for_push_dest(struct remote *remote,
const char *refname,
struct strbuf *err)
{
char *ret;
@ -1890,8 +1891,8 @@ static const char *tracking_for_push_dest(struct remote *remote,
return ret;
}
static const char *branch_get_push_1(struct repository *repo,
struct branch *branch, struct strbuf *err)
static char *branch_get_push_1(struct repository *repo,
struct branch *branch, struct strbuf *err)
{
struct remote_state *remote_state = repo->remote_state;
struct remote *remote;
@ -1906,7 +1907,7 @@ static const char *branch_get_push_1(struct repository *repo,
if (remote->push.nr) {
char *dst;
const char *ret;
char *ret;
dst = apply_refspecs(&remote->push, branch->refname);
if (!dst)
@ -1931,12 +1932,13 @@ static const char *branch_get_push_1(struct repository *repo,
return tracking_for_push_dest(remote, branch->refname, err);
case PUSH_DEFAULT_UPSTREAM:
return branch_get_upstream(branch, err);
return xstrdup_or_null(branch_get_upstream(branch, err));
case PUSH_DEFAULT_UNSPECIFIED:
case PUSH_DEFAULT_SIMPLE:
{
const char *up, *cur;
const char *up;
char *cur;
up = branch_get_upstream(branch, err);
if (!up)
@ -1944,9 +1946,11 @@ static const char *branch_get_push_1(struct repository *repo,
cur = tracking_for_push_dest(remote, branch->refname, err);
if (!cur)
return NULL;
if (strcmp(cur, up))
if (strcmp(cur, up)) {
free(cur);
return error_buf(err,
_("cannot resolve 'simple' push to a single destination"));
}
return cur;
}
}

View File

@ -331,7 +331,7 @@ struct branch {
int merge_alloc;
const char *push_tracking_ref;
char *push_tracking_ref;
};
struct branch *branch_get(const char *name);

View File

@ -1744,6 +1744,15 @@ test_expect_success ':remotename and :remoteref' '
)
'
test_expect_success '%(push) with an invalid push-simple config' '
echo "refs/heads/main " >expect &&
git -c push.default=simple \
-c remote.pushdefault=myfork \
for-each-ref \
--format="%(refname) %(push)" refs/heads/main >actual &&
test_cmp expect actual
'
test_expect_success "${git_for_each_ref} --ignore-case ignores case" '
${git_for_each_ref} --format="%(refname)" refs/heads/MAIN >actual &&
test_must_be_empty actual &&