git

Форк
0
/
loose.c 
261 строка · 6.6 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "hash.h"
5
#include "path.h"
6
#include "object-store.h"
7
#include "hex.h"
8
#include "wrapper.h"
9
#include "gettext.h"
10
#include "loose.h"
11
#include "lockfile.h"
12
#include "oidtree.h"
13

14
static const char *loose_object_header = "# loose-object-idx\n";
15

16
static inline int should_use_loose_object_map(struct repository *repo)
17
{
18
	return repo->compat_hash_algo && repo->gitdir;
19
}
20

21
void loose_object_map_init(struct loose_object_map **map)
22
{
23
	struct loose_object_map *m;
24
	m = xmalloc(sizeof(**map));
25
	m->to_compat = kh_init_oid_map();
26
	m->to_storage = kh_init_oid_map();
27
	*map = m;
28
}
29

30
static int insert_oid_pair(kh_oid_map_t *map, const struct object_id *key, const struct object_id *value)
31
{
32
	khiter_t pos;
33
	int ret;
34
	struct object_id *stored;
35

36
	pos = kh_put_oid_map(map, *key, &ret);
37

38
	/* This item already exists in the map. */
39
	if (ret == 0)
40
		return 0;
41

42
	stored = xmalloc(sizeof(*stored));
43
	oidcpy(stored, value);
44
	kh_value(map, pos) = stored;
45
	return 1;
46
}
47

48
static int insert_loose_map(struct object_directory *odb,
49
			    const struct object_id *oid,
50
			    const struct object_id *compat_oid)
51
{
52
	struct loose_object_map *map = odb->loose_map;
53
	int inserted = 0;
54

55
	inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
56
	inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
57
	if (inserted)
58
		oidtree_insert(odb->loose_objects_cache, compat_oid);
59

60
	return inserted;
61
}
62

63
static int load_one_loose_object_map(struct repository *repo, struct object_directory *dir)
64
{
65
	struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
66
	FILE *fp;
67

68
	if (!dir->loose_map)
69
		loose_object_map_init(&dir->loose_map);
70
	if (!dir->loose_objects_cache) {
71
		ALLOC_ARRAY(dir->loose_objects_cache, 1);
72
		oidtree_init(dir->loose_objects_cache);
73
	}
74

75
	insert_loose_map(dir, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
76
	insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob);
77
	insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid);
78

79
	strbuf_git_common_path(&path, repo, "objects/loose-object-idx");
80
	fp = fopen(path.buf, "rb");
81
	if (!fp) {
82
		strbuf_release(&path);
83
		return 0;
84
	}
85

86
	errno = 0;
87
	if (strbuf_getwholeline(&buf, fp, '\n') || strcmp(buf.buf, loose_object_header))
88
		goto err;
89
	while (!strbuf_getline_lf(&buf, fp)) {
90
		const char *p;
91
		struct object_id oid, compat_oid;
92
		if (parse_oid_hex_algop(buf.buf, &oid, &p, repo->hash_algo) ||
93
		    *p++ != ' ' ||
94
		    parse_oid_hex_algop(p, &compat_oid, &p, repo->compat_hash_algo) ||
95
		    p != buf.buf + buf.len)
96
			goto err;
97
		insert_loose_map(dir, &oid, &compat_oid);
98
	}
99

100
	strbuf_release(&buf);
101
	strbuf_release(&path);
102
	return errno ? -1 : 0;
103
err:
104
	strbuf_release(&buf);
105
	strbuf_release(&path);
106
	return -1;
107
}
108

109
int repo_read_loose_object_map(struct repository *repo)
110
{
111
	struct object_directory *dir;
112

113
	if (!should_use_loose_object_map(repo))
114
		return 0;
115

116
	prepare_alt_odb(repo);
117

118
	for (dir = repo->objects->odb; dir; dir = dir->next) {
119
		if (load_one_loose_object_map(repo, dir) < 0) {
120
			return -1;
121
		}
122
	}
123
	return 0;
124
}
125

126
int repo_write_loose_object_map(struct repository *repo)
127
{
128
	kh_oid_map_t *map = repo->objects->odb->loose_map->to_compat;
129
	struct lock_file lock;
130
	int fd;
131
	khiter_t iter;
132
	struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
133

134
	if (!should_use_loose_object_map(repo))
135
		return 0;
136

137
	strbuf_git_common_path(&path, repo, "objects/loose-object-idx");
138
	fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1);
139
	iter = kh_begin(map);
140
	if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0)
141
		goto errout;
142

143
	for (; iter != kh_end(map); iter++) {
144
		if (kh_exist(map, iter)) {
145
			if (oideq(&kh_key(map, iter), the_hash_algo->empty_tree) ||
146
			    oideq(&kh_key(map, iter), the_hash_algo->empty_blob))
147
				continue;
148
			strbuf_addf(&buf, "%s %s\n", oid_to_hex(&kh_key(map, iter)), oid_to_hex(kh_value(map, iter)));
149
			if (write_in_full(fd, buf.buf, buf.len) < 0)
150
				goto errout;
151
			strbuf_reset(&buf);
152
		}
153
	}
154
	strbuf_release(&buf);
155
	if (commit_lock_file(&lock) < 0) {
156
		error_errno(_("could not write loose object index %s"), path.buf);
157
		strbuf_release(&path);
158
		return -1;
159
	}
160
	strbuf_release(&path);
161
	return 0;
162
errout:
163
	rollback_lock_file(&lock);
164
	strbuf_release(&buf);
165
	error_errno(_("failed to write loose object index %s\n"), path.buf);
166
	strbuf_release(&path);
167
	return -1;
168
}
169

170
static int write_one_object(struct repository *repo, const struct object_id *oid,
171
			    const struct object_id *compat_oid)
172
{
173
	struct lock_file lock;
174
	int fd;
175
	struct stat st;
176
	struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
177

178
	strbuf_git_common_path(&path, repo, "objects/loose-object-idx");
179
	hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1);
180

181
	fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666);
182
	if (fd < 0)
183
		goto errout;
184
	if (fstat(fd, &st) < 0)
185
		goto errout;
186
	if (!st.st_size && write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0)
187
		goto errout;
188

189
	strbuf_addf(&buf, "%s %s\n", oid_to_hex(oid), oid_to_hex(compat_oid));
190
	if (write_in_full(fd, buf.buf, buf.len) < 0)
191
		goto errout;
192
	if (close(fd))
193
		goto errout;
194
	adjust_shared_perm(path.buf);
195
	rollback_lock_file(&lock);
196
	strbuf_release(&buf);
197
	strbuf_release(&path);
198
	return 0;
199
errout:
200
	error_errno(_("failed to write loose object index %s\n"), path.buf);
201
	close(fd);
202
	rollback_lock_file(&lock);
203
	strbuf_release(&buf);
204
	strbuf_release(&path);
205
	return -1;
206
}
207

208
int repo_add_loose_object_map(struct repository *repo, const struct object_id *oid,
209
			      const struct object_id *compat_oid)
210
{
211
	int inserted = 0;
212

213
	if (!should_use_loose_object_map(repo))
214
		return 0;
215

216
	inserted = insert_loose_map(repo->objects->odb, oid, compat_oid);
217
	if (inserted)
218
		return write_one_object(repo, oid, compat_oid);
219
	return 0;
220
}
221

222
int repo_loose_object_map_oid(struct repository *repo,
223
			      const struct object_id *src,
224
			      const struct git_hash_algo *to,
225
			      struct object_id *dest)
226
{
227
	struct object_directory *dir;
228
	kh_oid_map_t *map;
229
	khiter_t pos;
230

231
	for (dir = repo->objects->odb; dir; dir = dir->next) {
232
		struct loose_object_map *loose_map = dir->loose_map;
233
		if (!loose_map)
234
			continue;
235
		map = (to == repo->compat_hash_algo) ?
236
			loose_map->to_compat :
237
			loose_map->to_storage;
238
		pos = kh_get_oid_map(map, *src);
239
		if (pos < kh_end(map)) {
240
			oidcpy(dest, kh_value(map, pos));
241
			return 0;
242
		}
243
	}
244
	return -1;
245
}
246

247
void loose_object_map_clear(struct loose_object_map **map)
248
{
249
	struct loose_object_map *m = *map;
250
	struct object_id *oid;
251

252
	if (!m)
253
		return;
254

255
	kh_foreach_value(m->to_compat, oid, free(oid));
256
	kh_foreach_value(m->to_storage, oid, free(oid));
257
	kh_destroy_oid_map(m->to_compat);
258
	kh_destroy_oid_map(m->to_storage);
259
	free(m);
260
	*map = NULL;
261
}
262

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.