fix paths stored in pack meta data, improving file deltification The old code was broken and stored an empty path or filenames, instead of a repository-relative path. Which means we didn't sort files for deltification as was intended. Fixing this provides much better deltas in large pack files written by gotadmin pack -a. In my test case, pack size changed from 2GB to 1.5GB. ok op@
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
diff --git a/lib/pack_create.c b/lib/pack_create.c
index 5415448..0752cac 100644
--- a/lib/pack_create.c
+++ b/lib/pack_create.c
@@ -954,6 +954,8 @@ load_tree_entries(struct got_object_id_queue *ids, int want_meta,
err = got_object_qid_alloc(&qid, id);
if (err)
break;
+ qid->data = p;
+ p = NULL;
STAILQ_INSERT_TAIL(ids, qid, entry);
} else if (S_ISREG(mode) || S_ISLNK(mode)) {
err = add_object(want_meta,
@@ -963,9 +965,12 @@ load_tree_entries(struct got_object_id_queue *ids, int want_meta,
progress_cb, progress_arg, rl);
if (err)
break;
+ free(p);
+ p = NULL;
+ } else {
+ free(p);
+ p = NULL;
}
- free(p);
- p = NULL;
}
got_object_tree_close(tree);
@@ -993,11 +998,18 @@ load_tree(int want_meta, struct got_object_idset *idset,
err = got_object_qid_alloc(&qid, tree_id);
if (err)
return err;
+ qid->data = strdup(dpath);
+ if (qid->data == NULL) {
+ err = got_error_from_errno("strdup");
+ got_object_qid_free(qid);
+ return err;
+ }
STAILQ_INIT(&tree_ids);
STAILQ_INSERT_TAIL(&tree_ids, qid, entry);
while (!STAILQ_EMPTY(&tree_ids)) {
+ const char *path;
if (cancel_cb) {
err = (*cancel_cb)(cancel_arg);
if (err)
@@ -1006,32 +1018,38 @@ load_tree(int want_meta, struct got_object_idset *idset,
qid = STAILQ_FIRST(&tree_ids);
STAILQ_REMOVE_HEAD(&tree_ids, entry);
+ path = qid->data;
if (got_object_idset_contains(idset, &qid->id) ||
got_object_idset_contains(idset_exclude, &qid->id)) {
+ free(qid->data);
got_object_qid_free(qid);
continue;
}
err = add_object(want_meta, want_meta ? idset : idset_exclude,
- &qid->id, dpath, GOT_OBJ_TYPE_TREE,
+ &qid->id, path, GOT_OBJ_TYPE_TREE,
mtime, loose_obj_only, repo,
ncolored, nfound, ntrees, progress_cb, progress_arg, rl);
if (err) {
+ free(qid->data);
got_object_qid_free(qid);
break;
}
err = load_tree_entries(&tree_ids, want_meta, idset,
idset_exclude, &qid->id,
- dpath, mtime, repo, loose_obj_only, ncolored, nfound,
+ path, mtime, repo, loose_obj_only, ncolored, nfound,
ntrees, progress_cb, progress_arg, rl,
cancel_cb, cancel_arg);
+ free(qid->data);
got_object_qid_free(qid);
if (err)
break;
}
+ STAILQ_FOREACH(qid, &tree_ids, entry)
+ free(qid->data);
got_object_id_queue_free(&tree_ids);
return err;
}