#include "cache.h"
-#include "mru.h"
+#include "list.h"
#include "pack.h"
+#include "repository.h"
#include "dir.h"
#include "mergesort.h"
#include "packfile.h"
#include "list.h"
#include "streaming.h"
#include "sha1-lookup.h"
+#include "commit.h"
+#include "object.h"
+#include "tag.h"
+#include "tree-walk.h"
+#include "tree.h"
+#include "object-store.h"
char *odb_pack_name(struct strbuf *buf,
const unsigned char *sha1,
static unsigned int pack_max_fds;
static size_t peak_pack_mapped;
static size_t pack_mapped;
-struct packed_git *packed_git;
-struct mru packed_git_mru;
#define SZ_FMT PRIuMAX
static inline uintmax_t sz_fmt(size_t s) { return s; }
if (current)
scan_windows(current, &lru_p, &lru_w, &lru_l);
- for (p = packed_git; p; p = p->next)
+ for (p = the_repository->objects->packed_git; p; p = p->next)
scan_windows(p, &lru_p, &lru_w, &lru_l);
if (lru_p) {
munmap(lru_w->base, lru_w->len);
close_pack_index(p);
}
-void close_all_packs(void)
+void close_all_packs(struct raw_object_store *o)
{
struct packed_git *p;
- for (p = packed_git; p; p = p->next)
+ for (p = o->packed_git; p; p = p->next)
if (p->do_not_close)
die("BUG: want to close pack marked 'do-not-close'");
else
struct pack_window *mru_w = NULL;
int accept_windows_inuse = 1;
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if (p->pack_fd == -1)
continue;
find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
return NULL;
/*
- * ".pack" is long enough to hold any suffix we're adding (and
+ * ".promisor" is long enough to hold any suffix we're adding (and
* the use xsnprintf double-checks that)
*/
- alloc = st_add3(path_len, strlen(".pack"), 1);
+ alloc = st_add3(path_len, strlen(".promisor"), 1);
p = alloc_packed_git(alloc);
memcpy(p->pack_name, path, path_len);
if (!access(p->pack_name, F_OK))
p->pack_keep = 1;
+ xsnprintf(p->pack_name + path_len, alloc - path_len, ".promisor");
+ if (!access(p->pack_name, F_OK))
+ p->pack_promisor = 1;
+
xsnprintf(p->pack_name + path_len, alloc - path_len, ".pack");
if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
free(p);
if (pack->pack_fd != -1)
pack_open_fds++;
- pack->next = packed_git;
- packed_git = pack;
+ pack->next = the_repository->objects->packed_git;
+ the_repository->objects->packed_git = pack;
}
void (*report_garbage)(unsigned seen_bits, const char *path);
base_len = path.len;
if (strip_suffix_mem(path.buf, &base_len, ".idx")) {
/* Don't reopen a pack we already have. */
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p;
+ p = p->next) {
size_t len;
if (strip_suffix(p->pack_name, ".pack", &len) &&
len == base_len &&
if (ends_with(de->d_name, ".idx") ||
ends_with(de->d_name, ".pack") ||
ends_with(de->d_name, ".bitmap") ||
- ends_with(de->d_name, ".keep"))
+ ends_with(de->d_name, ".keep") ||
+ ends_with(de->d_name, ".promisor"))
string_list_append(&garbage, path.buf);
else
report_garbage(PACKDIR_FILE_GARBAGE, path.buf);
strbuf_release(&path);
}
-static int approximate_object_count_valid;
-
/*
* Give a fast, rough count of the number of objects in the repository. This
* ignores loose objects completely. If you have a lot of them, then either
*/
unsigned long approximate_object_count(void)
{
- static unsigned long count;
- if (!approximate_object_count_valid) {
+ if (!the_repository->objects->approximate_object_count_valid) {
+ unsigned long count;
struct packed_git *p;
prepare_packed_git();
count = 0;
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if (open_pack_index(p))
continue;
count += p->num_objects;
}
+ the_repository->objects->approximate_object_count = count;
}
- return count;
+ return the_repository->objects->approximate_object_count;
}
static void *get_next_packed_git(const void *p)
static void rearrange_packed_git(void)
{
- packed_git = llist_mergesort(packed_git, get_next_packed_git,
- set_next_packed_git, sort_pack);
+ the_repository->objects->packed_git = llist_mergesort(
+ the_repository->objects->packed_git, get_next_packed_git,
+ set_next_packed_git, sort_pack);
}
static void prepare_packed_git_mru(void)
{
struct packed_git *p;
- mru_clear(&packed_git_mru);
- for (p = packed_git; p; p = p->next)
- mru_append(&packed_git_mru, p);
+ INIT_LIST_HEAD(&the_repository->objects->packed_git_mru);
+
+ for (p = the_repository->objects->packed_git; p; p = p->next)
+ list_add_tail(&p->mru, &the_repository->objects->packed_git_mru);
}
-static int prepare_packed_git_run_once = 0;
void prepare_packed_git(void)
{
struct alternate_object_database *alt;
- if (prepare_packed_git_run_once)
+ if (the_repository->objects->packed_git_initialized)
return;
prepare_packed_git_one(get_object_directory(), 1);
- prepare_alt_odb();
- for (alt = alt_odb_list; alt; alt = alt->next)
+ prepare_alt_odb(the_repository);
+ for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next)
prepare_packed_git_one(alt->path, 0);
rearrange_packed_git();
prepare_packed_git_mru();
- prepare_packed_git_run_once = 1;
+ the_repository->objects->packed_git_initialized = 1;
}
void reprepare_packed_git(void)
{
- approximate_object_count_valid = 0;
- prepare_packed_git_run_once = 0;
+ the_repository->objects->approximate_object_count_valid = 0;
+ the_repository->objects->packed_git_initialized = 0;
prepare_packed_git();
}
+struct packed_git *get_packed_git(struct repository *r)
+{
+ return r->objects->packed_git;
+}
+
+struct list_head *get_packed_git_mru(struct repository *r)
+{
+ return &r->objects->packed_git_mru;
+}
+
unsigned long unpack_object_header_buffer(const unsigned char *buf,
unsigned long len, enum object_type *type, unsigned long *sizep)
{
struct packed_git *p;
unsigned i;
- for (p = packed_git; p; p = p->next)
+ for (p = the_repository->objects->packed_git; p; p = p->next)
for (i = 0; i < p->num_bad_objects; i++)
if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
return p;
return off;
index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
check_pack_index_ptr(p, index);
- return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
- ntohl(*((uint32_t *)(index + 4)));
+ return get_be64(index);
}
}
*/
int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
{
- struct mru_entry *p;
+ struct list_head *pos;
prepare_packed_git();
- if (!packed_git)
+ if (!the_repository->objects->packed_git)
return 0;
- for (p = packed_git_mru.head; p; p = p->next) {
- if (fill_pack_entry(sha1, e, p->item)) {
- mru_mark(&packed_git_mru, p);
+ list_for_each(pos, &the_repository->objects->packed_git_mru) {
+ struct packed_git *p = list_entry(pos, struct packed_git, mru);
+ if (fill_pack_entry(sha1, e, p)) {
+ list_move(&p->mru,
+ &the_repository->objects->packed_git_mru);
return 1;
}
}
int pack_errors = 0;
prepare_packed_git();
- for (p = packed_git; p; p = p->next) {
+ for (p = the_repository->objects->packed_git; p; p = p->next) {
if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
continue;
+ if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+ !p->pack_promisor)
+ continue;
if (open_pack_index(p)) {
pack_errors = 1;
continue;
}
return r ? r : pack_errors;
}
+
+static int add_promisor_object(const struct object_id *oid,
+ struct packed_git *pack,
+ uint32_t pos,
+ void *set_)
+{
+ struct oidset *set = set_;
+ struct object *obj = parse_object(oid);
+ if (!obj)
+ return 1;
+
+ oidset_insert(set, oid);
+
+ /*
+ * If this is a tree, commit, or tag, the objects it refers
+ * to are also promisor objects. (Blobs refer to no objects->)
+ */
+ if (obj->type == OBJ_TREE) {
+ struct tree *tree = (struct tree *)obj;
+ struct tree_desc desc;
+ struct name_entry entry;
+ if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
+ /*
+ * Error messages are given when packs are
+ * verified, so do not print any here.
+ */
+ return 0;
+ while (tree_entry_gently(&desc, &entry))
+ oidset_insert(set, entry.oid);
+ } else if (obj->type == OBJ_COMMIT) {
+ struct commit *commit = (struct commit *) obj;
+ struct commit_list *parents = commit->parents;
+
+ oidset_insert(set, &commit->tree->object.oid);
+ for (; parents; parents = parents->next)
+ oidset_insert(set, &parents->item->object.oid);
+ } else if (obj->type == OBJ_TAG) {
+ struct tag *tag = (struct tag *) obj;
+ oidset_insert(set, &tag->tagged->oid);
+ }
+ return 0;
+}
+
+int is_promisor_object(const struct object_id *oid)
+{
+ static struct oidset promisor_objects;
+ static int promisor_objects_prepared;
+
+ if (!promisor_objects_prepared) {
+ if (repository_format_partial_clone) {
+ for_each_packed_object(add_promisor_object,
+ &promisor_objects,
+ FOR_EACH_OBJECT_PROMISOR_ONLY);
+ }
+ promisor_objects_prepared = 1;
+ }
+ return oidset_contains(&promisor_objects, oid);
+}