1 #include "git-compat-util.h"
4 #include "object-store.h"
12 static const char *loose_object_header
= "# loose-object-idx\n";
14 static inline int should_use_loose_object_map(struct repository
*repo
)
16 return repo
->compat_hash_algo
&& repo
->gitdir
;
19 void loose_object_map_init(struct loose_object_map
**map
)
21 struct loose_object_map
*m
;
22 m
= xmalloc(sizeof(**map
));
23 m
->to_compat
= kh_init_oid_map();
24 m
->to_storage
= kh_init_oid_map();
28 static int insert_oid_pair(kh_oid_map_t
*map
, const struct object_id
*key
, const struct object_id
*value
)
32 struct object_id
*stored
;
34 pos
= kh_put_oid_map(map
, *key
, &ret
);
36 /* This item already exists in the map. */
40 stored
= xmalloc(sizeof(*stored
));
41 oidcpy(stored
, value
);
42 kh_value(map
, pos
) = stored
;
46 static int insert_loose_map(struct object_directory
*odb
,
47 const struct object_id
*oid
,
48 const struct object_id
*compat_oid
)
50 struct loose_object_map
*map
= odb
->loose_map
;
53 inserted
|= insert_oid_pair(map
->to_compat
, oid
, compat_oid
);
54 inserted
|= insert_oid_pair(map
->to_storage
, compat_oid
, oid
);
56 oidtree_insert(odb
->loose_objects_cache
, compat_oid
);
61 static int load_one_loose_object_map(struct repository
*repo
, struct object_directory
*dir
)
63 struct strbuf buf
= STRBUF_INIT
, path
= STRBUF_INIT
;
67 loose_object_map_init(&dir
->loose_map
);
68 if (!dir
->loose_objects_cache
) {
69 ALLOC_ARRAY(dir
->loose_objects_cache
, 1);
70 oidtree_init(dir
->loose_objects_cache
);
73 insert_loose_map(dir
, repo
->hash_algo
->empty_tree
, repo
->compat_hash_algo
->empty_tree
);
74 insert_loose_map(dir
, repo
->hash_algo
->empty_blob
, repo
->compat_hash_algo
->empty_blob
);
75 insert_loose_map(dir
, repo
->hash_algo
->null_oid
, repo
->compat_hash_algo
->null_oid
);
77 strbuf_git_common_path(&path
, repo
, "objects/loose-object-idx");
78 fp
= fopen(path
.buf
, "rb");
80 strbuf_release(&path
);
85 if (strbuf_getwholeline(&buf
, fp
, '\n') || strcmp(buf
.buf
, loose_object_header
))
87 while (!strbuf_getline_lf(&buf
, fp
)) {
89 struct object_id oid
, compat_oid
;
90 if (parse_oid_hex_algop(buf
.buf
, &oid
, &p
, repo
->hash_algo
) ||
92 parse_oid_hex_algop(p
, &compat_oid
, &p
, repo
->compat_hash_algo
) ||
93 p
!= buf
.buf
+ buf
.len
)
95 insert_loose_map(dir
, &oid
, &compat_oid
);
99 strbuf_release(&path
);
100 return errno
? -1 : 0;
102 strbuf_release(&buf
);
103 strbuf_release(&path
);
107 int repo_read_loose_object_map(struct repository
*repo
)
109 struct object_directory
*dir
;
111 if (!should_use_loose_object_map(repo
))
114 prepare_alt_odb(repo
);
116 for (dir
= repo
->objects
->odb
; dir
; dir
= dir
->next
) {
117 if (load_one_loose_object_map(repo
, dir
) < 0) {
124 int repo_write_loose_object_map(struct repository
*repo
)
126 kh_oid_map_t
*map
= repo
->objects
->odb
->loose_map
->to_compat
;
127 struct lock_file lock
;
130 struct strbuf buf
= STRBUF_INIT
, path
= STRBUF_INIT
;
132 if (!should_use_loose_object_map(repo
))
135 strbuf_git_common_path(&path
, repo
, "objects/loose-object-idx");
136 fd
= hold_lock_file_for_update_timeout(&lock
, path
.buf
, LOCK_DIE_ON_ERROR
, -1);
137 iter
= kh_begin(map
);
138 if (write_in_full(fd
, loose_object_header
, strlen(loose_object_header
)) < 0)
141 for (; iter
!= kh_end(map
); iter
++) {
142 if (kh_exist(map
, iter
)) {
143 if (oideq(&kh_key(map
, iter
), the_hash_algo
->empty_tree
) ||
144 oideq(&kh_key(map
, iter
), the_hash_algo
->empty_blob
))
146 strbuf_addf(&buf
, "%s %s\n", oid_to_hex(&kh_key(map
, iter
)), oid_to_hex(kh_value(map
, iter
)));
147 if (write_in_full(fd
, buf
.buf
, buf
.len
) < 0)
152 strbuf_release(&buf
);
153 if (commit_lock_file(&lock
) < 0) {
154 error_errno(_("could not write loose object index %s"), path
.buf
);
155 strbuf_release(&path
);
158 strbuf_release(&path
);
161 rollback_lock_file(&lock
);
162 strbuf_release(&buf
);
163 error_errno(_("failed to write loose object index %s\n"), path
.buf
);
164 strbuf_release(&path
);
168 static int write_one_object(struct repository
*repo
, const struct object_id
*oid
,
169 const struct object_id
*compat_oid
)
171 struct lock_file lock
;
174 struct strbuf buf
= STRBUF_INIT
, path
= STRBUF_INIT
;
176 strbuf_git_common_path(&path
, repo
, "objects/loose-object-idx");
177 hold_lock_file_for_update_timeout(&lock
, path
.buf
, LOCK_DIE_ON_ERROR
, -1);
179 fd
= open(path
.buf
, O_WRONLY
| O_CREAT
| O_APPEND
, 0666);
182 if (fstat(fd
, &st
) < 0)
184 if (!st
.st_size
&& write_in_full(fd
, loose_object_header
, strlen(loose_object_header
)) < 0)
187 strbuf_addf(&buf
, "%s %s\n", oid_to_hex(oid
), oid_to_hex(compat_oid
));
188 if (write_in_full(fd
, buf
.buf
, buf
.len
) < 0)
192 adjust_shared_perm(path
.buf
);
193 rollback_lock_file(&lock
);
194 strbuf_release(&buf
);
195 strbuf_release(&path
);
198 error_errno(_("failed to write loose object index %s\n"), path
.buf
);
200 rollback_lock_file(&lock
);
201 strbuf_release(&buf
);
202 strbuf_release(&path
);
206 int repo_add_loose_object_map(struct repository
*repo
, const struct object_id
*oid
,
207 const struct object_id
*compat_oid
)
211 if (!should_use_loose_object_map(repo
))
214 inserted
= insert_loose_map(repo
->objects
->odb
, oid
, compat_oid
);
216 return write_one_object(repo
, oid
, compat_oid
);
220 int repo_loose_object_map_oid(struct repository
*repo
,
221 const struct object_id
*src
,
222 const struct git_hash_algo
*to
,
223 struct object_id
*dest
)
225 struct object_directory
*dir
;
229 for (dir
= repo
->objects
->odb
; dir
; dir
= dir
->next
) {
230 struct loose_object_map
*loose_map
= dir
->loose_map
;
233 map
= (to
== repo
->compat_hash_algo
) ?
234 loose_map
->to_compat
:
235 loose_map
->to_storage
;
236 pos
= kh_get_oid_map(map
, *src
);
237 if (pos
< kh_end(map
)) {
238 oidcpy(dest
, kh_value(map
, pos
));
245 void loose_object_map_clear(struct loose_object_map
**map
)
247 struct loose_object_map
*m
= *map
;
248 struct object_id
*oid
;
253 kh_foreach_value(m
->to_compat
, oid
, free(oid
));
254 kh_foreach_value(m
->to_storage
, oid
, free(oid
));
255 kh_destroy_oid_map(m
->to_compat
);
256 kh_destroy_oid_map(m
->to_storage
);