Skip to content

Commit 10b635b

Browse files
avargitster
authored andcommitted
bundle: remove "ref_list" in favor of string-list.c API
Move away from the "struct ref_list" in bundle.c in favor of the almost identical string-list.c API. That API fits this use-case perfectly, but did not exist in its current form when this code was added in 2e0afaf (Add git-bundle: move objects and references by archive, 2007-02-22), with hindsight we could have used the path-list API, which later got renamed to string-list. See 8fd2cb4 (Extract helper bits from c-merge-recursive work, 2006-07-25) We need to change "name" to "string" and "oid" to "util" to make this conversion, but other than that the APIs are pretty much identical for what bundle.c made use of. Let's also replace the memset(..,0,...) pattern with a more idiomatic "INIT" macro, and finally add a *_release() function so to free the allocated memory. Before this the add_to_ref_list() would leak memory, now e.g. "bundle list-heads" reports no memory leaks at all under valgrind. In the bundle_header_init() function we're using a clever trick to memcpy() what we'd get from the corresponding BUNDLE_HEADER_INIT. There is a concurrent series to make use of that pattern more generally, see [1]. 1. https://lore.kernel.org/git/[email protected]/ Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Acked-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 15e7c7d commit 10b635b

File tree

4 files changed

+50
-43
lines changed

4 files changed

+50
-43
lines changed

builtin/bundle.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
100100
}
101101

102102
static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
103-
struct bundle_header header;
103+
struct bundle_header header = BUNDLE_HEADER_INIT;
104104
int bundle_fd = -1;
105105
int quiet = 0;
106106
int ret;
@@ -115,7 +115,6 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
115115
builtin_bundle_verify_usage, options, &bundle_file);
116116
/* bundle internals use argv[1] as further parameters */
117117

118-
memset(&header, 0, sizeof(header));
119118
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
120119
ret = 1;
121120
goto cleanup;
@@ -130,11 +129,12 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
130129
ret = 0;
131130
cleanup:
132131
free(bundle_file);
132+
bundle_header_release(&header);
133133
return ret;
134134
}
135135

136136
static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) {
137-
struct bundle_header header;
137+
struct bundle_header header = BUNDLE_HEADER_INIT;
138138
int bundle_fd = -1;
139139
int ret;
140140
struct option options[] = {
@@ -146,7 +146,6 @@ static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix
146146
builtin_bundle_list_heads_usage, options, &bundle_file);
147147
/* bundle internals use argv[1] as further parameters */
148148

149-
memset(&header, 0, sizeof(header));
150149
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
151150
ret = 1;
152151
goto cleanup;
@@ -155,11 +154,12 @@ static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix
155154
ret = !!list_bundle_refs(&header, argc, argv);
156155
cleanup:
157156
free(bundle_file);
157+
bundle_header_release(&header);
158158
return ret;
159159
}
160160

161161
static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) {
162-
struct bundle_header header;
162+
struct bundle_header header = BUNDLE_HEADER_INIT;
163163
int bundle_fd = -1;
164164
int ret;
165165
struct option options[] = {
@@ -171,7 +171,6 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
171171
builtin_bundle_unbundle_usage, options, &bundle_file);
172172
/* bundle internals use argv[1] as further parameters */
173173

174-
memset(&header, 0, sizeof(header));
175174
if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
176175
ret = 1;
177176
goto cleanup;
@@ -180,6 +179,7 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
180179
die(_("Need a repository to unbundle."));
181180
ret = !!unbundle(the_repository, &header, bundle_fd, 0) ||
182181
list_bundle_refs(&header, argc, argv);
182+
bundle_header_release(&header);
183183
cleanup:
184184
free(bundle_file);
185185
return ret;

bundle.c

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ static struct {
2323
{ 3, v3_bundle_signature },
2424
};
2525

26-
static void add_to_ref_list(const struct object_id *oid, const char *name,
27-
struct ref_list *list)
26+
void bundle_header_init(struct bundle_header *header)
2827
{
29-
ALLOC_GROW(list->list, list->nr + 1, list->alloc);
30-
oidcpy(&list->list[list->nr].oid, oid);
31-
list->list[list->nr].name = xstrdup(name);
32-
list->nr++;
28+
struct bundle_header blank = BUNDLE_HEADER_INIT;
29+
memcpy(header, &blank, sizeof(*header));
30+
}
31+
32+
void bundle_header_release(struct bundle_header *header)
33+
{
34+
string_list_clear(&header->prerequisites, 1);
35+
string_list_clear(&header->references, 1);
3336
}
3437

3538
static int parse_capability(struct bundle_header *header, const char *capability)
@@ -112,10 +115,11 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
112115
status = -1;
113116
break;
114117
} else {
118+
struct object_id *dup = oiddup(&oid);
115119
if (is_prereq)
116-
add_to_ref_list(&oid, "", &header->prerequisites);
120+
string_list_append(&header->prerequisites, "")->util = dup;
117121
else
118-
add_to_ref_list(&oid, p + 1, &header->references);
122+
string_list_append(&header->references, p + 1)->util = dup;
119123
}
120124
}
121125

@@ -139,19 +143,19 @@ int read_bundle_header(const char *path, struct bundle_header *header)
139143

140144
int is_bundle(const char *path, int quiet)
141145
{
142-
struct bundle_header header;
146+
struct bundle_header header = BUNDLE_HEADER_INIT;
143147
int fd = open(path, O_RDONLY);
144148

145149
if (fd < 0)
146150
return 0;
147-
memset(&header, 0, sizeof(header));
148151
fd = parse_bundle_header(fd, &header, quiet ? NULL : path);
149152
if (fd >= 0)
150153
close(fd);
154+
bundle_header_release(&header);
151155
return (fd >= 0);
152156
}
153157

154-
static int list_refs(struct ref_list *r, int argc, const char **argv)
158+
static int list_refs(struct string_list *r, int argc, const char **argv)
155159
{
156160
int i;
157161

@@ -162,14 +166,14 @@ static int list_refs(struct ref_list *r, int argc, const char **argv)
162166
if (argc > 1) {
163167
int j;
164168
for (j = 1; j < argc; j++)
165-
if (!strcmp(r->list[i].name, argv[j]))
169+
if (!strcmp(r->items[i].string, argv[j]))
166170
break;
167171
if (j == argc)
168172
continue;
169173
}
170174

171-
oid = &r->list[i].oid;
172-
name = r->list[i].name;
175+
oid = r->items[i].util;
176+
name = r->items[i].string;
173177
printf("%s %s\n", oid_to_hex(oid), name);
174178
}
175179
return 0;
@@ -186,7 +190,7 @@ int verify_bundle(struct repository *r,
186190
* Do fast check, then if any prereqs are missing then go line by line
187191
* to be verbose about the errors
188192
*/
189-
struct ref_list *p = &header->prerequisites;
193+
struct string_list *p = &header->prerequisites;
190194
struct rev_info revs;
191195
const char *argv[] = {NULL, "--all", NULL};
192196
struct commit *commit;
@@ -198,9 +202,9 @@ int verify_bundle(struct repository *r,
198202

199203
repo_init_revisions(r, &revs, NULL);
200204
for (i = 0; i < p->nr; i++) {
201-
struct ref_list_entry *e = p->list + i;
202-
const char *name = e->name;
203-
struct object_id *oid = &e->oid;
205+
struct string_list_item *e = p->items + i;
206+
const char *name = e->string;
207+
struct object_id *oid = e->util;
204208
struct object *o = parse_object(r, oid);
205209
if (o) {
206210
o->flags |= PREREQ_MARK;
@@ -225,9 +229,9 @@ int verify_bundle(struct repository *r,
225229
i--;
226230

227231
for (i = 0; i < p->nr; i++) {
228-
struct ref_list_entry *e = p->list + i;
229-
const char *name = e->name;
230-
struct object_id *oid = &e->oid;
232+
struct string_list_item *e = p->items + i;
233+
const char *name = e->string;
234+
const struct object_id *oid = e->util;
231235
struct object *o = parse_object(r, oid);
232236
assert(o); /* otherwise we'd have returned early */
233237
if (o->flags & SHOWN)
@@ -239,15 +243,15 @@ int verify_bundle(struct repository *r,
239243

240244
/* Clean up objects used, as they will be reused. */
241245
for (i = 0; i < p->nr; i++) {
242-
struct ref_list_entry *e = p->list + i;
243-
struct object_id *oid = &e->oid;
246+
struct string_list_item *e = p->items + i;
247+
struct object_id *oid = e->util;
244248
commit = lookup_commit_reference_gently(r, oid, 1);
245249
if (commit)
246250
clear_commit_marks(commit, ALL_REV_FLAGS);
247251
}
248252

249253
if (verbose) {
250-
struct ref_list *r;
254+
struct string_list *r;
251255

252256
r = &header->references;
253257
printf_ln(Q_("The bundle contains this ref:",

bundle.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33

44
#include "strvec.h"
55
#include "cache.h"
6-
7-
struct ref_list {
8-
unsigned int nr, alloc;
9-
struct ref_list_entry {
10-
struct object_id oid;
11-
char *name;
12-
} *list;
13-
};
6+
#include "string-list.h"
147

158
struct bundle_header {
169
unsigned version;
17-
struct ref_list prerequisites;
18-
struct ref_list references;
10+
struct string_list prerequisites;
11+
struct string_list references;
1912
const struct git_hash_algo *hash_algo;
2013
};
2114

15+
#define BUNDLE_HEADER_INIT \
16+
{ \
17+
.prerequisites = STRING_LIST_INIT_DUP, \
18+
.references = STRING_LIST_INIT_DUP, \
19+
}
20+
void bundle_header_init(struct bundle_header *header);
21+
void bundle_header_release(struct bundle_header *header);
22+
2223
int is_bundle(const char *path, int quiet);
2324
int read_bundle_header(const char *path, struct bundle_header *header);
2425
int create_bundle(struct repository *r, const char *path,

transport.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ static struct ref *get_refs_from_bundle(struct transport *transport,
147147
transport->hash_algo = data->header.hash_algo;
148148

149149
for (i = 0; i < data->header.references.nr; i++) {
150-
struct ref_list_entry *e = data->header.references.list + i;
151-
const char *name = e->name;
150+
struct string_list_item *e = data->header.references.items + i;
151+
const char *name = e->string;
152152
struct ref *ref = alloc_ref(name);
153-
struct object_id *oid = &e->oid;
153+
struct object_id *oid = e->util;
154154
oidcpy(&ref->old_oid, oid);
155155
ref->next = result;
156156
result = ref;
@@ -177,6 +177,7 @@ static int close_bundle(struct transport *transport)
177177
struct bundle_transport_data *data = transport->data;
178178
if (data->fd > 0)
179179
close(data->fd);
180+
bundle_header_release(&data->header);
180181
free(data);
181182
return 0;
182183
}
@@ -1083,6 +1084,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
10831084
die(_("git-over-rsync is no longer supported"));
10841085
} else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
10851086
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
1087+
bundle_header_init(&data->header);
10861088
transport_check_allowed("file");
10871089
ret->data = data;
10881090
ret->vtable = &bundle_vtable;

0 commit comments

Comments
 (0)