summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
authorRené Scharfe <l.s.r@web.de>2020-09-05 14:47:47 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-09-06 20:15:45 (GMT)
commit30035d9c66bc2a52352e3ad42b56047f06c20326 (patch)
tree72d735082b4dd68c78f6e363b86549b384cc29d8 /builtin
parent3a238e539bcdfe3f9eb5010fd218640c1b499f7a (diff)
downloadgit-30035d9c66bc2a52352e3ad42b56047f06c20326.zip
git-30035d9c66bc2a52352e3ad42b56047f06c20326.tar.gz
git-30035d9c66bc2a52352e3ad42b56047f06c20326.tar.bz2
push: release strbufs used for refspec formatting
map_refspec() either returns the passed in ref string or a detached strbuf. This makes it hard for callers to release the possibly allocated memory, and set_refspecs() consequently leaks it. Let map_refspec() append any refspecs directly and release its own strbufs after use. Rename it to refspec_append_mapped() and don't return anything to reflect its increased responsibility. set_refspecs() also leaks its strbufs. Do the same here and directly call refspec_append() in each if branch instead of holding onto a detached strbuf, then dispose of the allocated memory after use. We need to add an else branch for the final call because all the other conditional branches already add their formatted refspec now. setup_push_upstream() and setup_push_current() forgot to release their strbufs as well; plug these leaks, too, while at it. None of these leaks were likely to impact users, because the number and sizes of refspecs are usually small and the allocations are only done once per program run. Clean them up nevertheless, as another step on the long road towards zero memory leaks. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
-rw-r--r--builtin/push.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/builtin/push.c b/builtin/push.c
index bc94078..0f3c108 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -61,15 +61,17 @@ static struct refspec rs = REFSPEC_INIT_PUSH;
static struct string_list push_options_config = STRING_LIST_INIT_DUP;
-static const char *map_refspec(const char *ref,
- struct remote *remote, struct ref *local_refs)
+static void refspec_append_mapped(struct refspec *refspec, const char *ref,
+ struct remote *remote, struct ref *local_refs)
{
const char *branch_name;
struct ref *matched = NULL;
/* Does "ref" uniquely name our ref? */
- if (count_refspec_match(ref, local_refs, &matched) != 1)
- return ref;
+ if (count_refspec_match(ref, local_refs, &matched) != 1) {
+ refspec_append(refspec, ref);
+ return;
+ }
if (remote->push.nr) {
struct refspec_item query;
@@ -80,7 +82,9 @@ static const char *map_refspec(const char *ref,
strbuf_addf(&buf, "%s%s:%s",
query.force ? "+" : "",
query.src, query.dst);
- return strbuf_detach(&buf, NULL);
+ refspec_append(refspec, buf.buf);
+ strbuf_release(&buf);
+ return;
}
}
@@ -91,11 +95,13 @@ static const char *map_refspec(const char *ref,
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%s:%s",
ref, branch->merge[0]->src);
- return strbuf_detach(&buf, NULL);
+ refspec_append(refspec, buf.buf);
+ strbuf_release(&buf);
+ return;
}
}
- return ref;
+ refspec_append(refspec, ref);
}
static void set_refspecs(const char **refs, int nr, const char *repo)
@@ -115,22 +121,24 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
strbuf_addf(&tagref, ":refs/tags/%s", ref);
else
strbuf_addf(&tagref, "refs/tags/%s", ref);
- ref = strbuf_detach(&tagref, NULL);
+ refspec_append(&rs, tagref.buf);
+ strbuf_release(&tagref);
} else if (deleterefs) {
struct strbuf delref = STRBUF_INIT;
if (strchr(ref, ':'))
die(_("--delete only accepts plain target ref names"));
strbuf_addf(&delref, ":%s", ref);
- ref = strbuf_detach(&delref, NULL);
+ refspec_append(&rs, delref.buf);
+ strbuf_release(&delref);
} else if (!strchr(ref, ':')) {
if (!remote) {
/* lazily grab remote and local_refs */
remote = remote_get(repo);
local_refs = get_local_heads();
}
- ref = map_refspec(ref, remote, local_refs);
- }
- refspec_append(&rs, ref);
+ refspec_append_mapped(&rs, ref, remote, local_refs);
+ } else
+ refspec_append(&rs, ref);
}
}
@@ -221,6 +229,7 @@ static void setup_push_upstream(struct remote *remote, struct branch *branch,
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src);
refspec_append(&rs, refspec.buf);
+ strbuf_release(&refspec);
}
static void setup_push_current(struct remote *remote, struct branch *branch)
@@ -231,6 +240,7 @@ static void setup_push_current(struct remote *remote, struct branch *branch)
die(_(message_detached_head_die), remote->name);
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname);
refspec_append(&rs, refspec.buf);
+ strbuf_release(&refspec);
}
static int is_workflow_triangular(struct remote *remote)