commit 3e6ceea0bd8a65737eb2231ce18d0e591dfb92ff from: Stefan Sperling date: Fri May 20 08:40:46 2022 UTC 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@ commit - 17259bfa94068499f61aec3129c47ae2671bd531 commit + 3e6ceea0bd8a65737eb2231ce18d0e591dfb92ff blob - 5415448aa86fb16df21cd1e028be51fecc89f699 blob + 0752cac5cd94dfe4ad0a77cc543573d72493829d --- lib/pack_create.c +++ lib/pack_create.c @@ -954,6 +954,8 @@ load_tree_entries(struct got_object_id_queue *ids, int 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 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); @@ -992,12 +997,19 @@ load_tree(int want_meta, struct got_object_idset *idse 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 *idse 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; }