Raw
1 #include "git-compat-util.h"
2 #include "abspath.h"
3 #include "chdir-notify.h"
4 #include "gettext.h"
5 #include "lockfile.h"
6 #include "object-file.h"
7 #include "odb.h"
8 #include "odb/source.h"
9 #include "odb/source-files.h"
10 #include "odb/source-loose.h"
11 #include "packfile.h"
12 #include "strbuf.h"
13 #include "write-or-die.h"
14
15 static void odb_source_files_reparent(const char *name UNUSED,
16 const char *old_cwd,
17 const char *new_cwd,
18 void *cb_data)
19 {
20 struct odb_source_files *files = cb_data;
21 char *path = reparent_relative_path(old_cwd, new_cwd,
22 files->base.path);
23 free(files->base.path);
24 files->base.path = path;
25 }
26
27 static void odb_source_files_free(struct odb_source *source)
28 {
29 struct odb_source_files *files = odb_source_files_downcast(source);
30 chdir_notify_unregister(NULL, odb_source_files_reparent, files);
31 odb_source_free(&files->loose->base);
32 odb_source_free(&files->packed->base);
33 odb_source_release(&files->base);
34 free(files);
35 }
36
37 static void odb_source_files_close(struct odb_source *source)
38 {
39 struct odb_source_files *files = odb_source_files_downcast(source);
40 odb_source_close(&files->loose->base);
41 odb_source_close(&files->packed->base);
42 }
43
44 static void odb_source_files_prepare(struct odb_source *source,
45 enum odb_prepare_flags flags)
46 {
47 struct odb_source_files *files = odb_source_files_downcast(source);
48 odb_source_prepare(&files->loose->base, flags);
49 odb_source_prepare(&files->packed->base, flags);
50 }
51
52 static int odb_source_files_read_object_info(struct odb_source *source,
53 const struct object_id *oid,
54 struct object_info *oi,
55 enum object_info_flags flags)
56 {
57 struct odb_source_files *files = odb_source_files_downcast(source);
58
59 if (!odb_source_read_object_info(&files->packed->base, oid, oi, flags) ||
60 !odb_source_read_object_info(&files->loose->base, oid, oi, flags))
61 return 0;
62
63 return -1;
64 }
65
66 static int odb_source_files_read_object_stream(struct odb_read_stream **out,
67 struct odb_source *source,
68 const struct object_id *oid)
69 {
70 struct odb_source_files *files = odb_source_files_downcast(source);
71 if (!odb_source_read_object_stream(out, &files->packed->base, oid) ||
72 !odb_source_read_object_stream(out, &files->loose->base, oid))
73 return 0;
74 return -1;
75 }
76
77 static int odb_source_files_for_each_object(struct odb_source *source,
78 const struct object_info *request,
79 odb_for_each_object_cb cb,
80 void *cb_data,
81 const struct odb_for_each_object_options *opts)
82 {
83 struct odb_source_files *files = odb_source_files_downcast(source);
84 int ret;
85
86 if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
87 ret = odb_source_for_each_object(&files->loose->base, request, cb, cb_data, opts);
88 if (ret)
89 return ret;
90 }
91
92 ret = odb_source_for_each_object(&files->packed->base, request, cb, cb_data, opts);
93 if (ret)
94 return ret;
95
96 return 0;
97 }
98
99 static int odb_source_files_count_objects(struct odb_source *source,
100 enum odb_count_objects_flags flags,
101 unsigned long *out)
102 {
103 struct odb_source_files *files = odb_source_files_downcast(source);
104 unsigned long count;
105 int ret;
106
107 ret = odb_source_count_objects(&files->packed->base, flags, &count);
108 if (ret < 0)
109 goto out;
110
111 if (!(flags & ODB_COUNT_OBJECTS_APPROXIMATE)) {
112 unsigned long loose_count;
113
114 ret = odb_source_count_objects(&files->loose->base, flags, &loose_count);
115 if (ret < 0)
116 goto out;
117
118 count += loose_count;
119 }
120
121 *out = count;
122 ret = 0;
123
124 out:
125 return ret;
126 }
127
128 static int odb_source_files_find_abbrev_len(struct odb_source *source,
129 const struct object_id *oid,
130 unsigned min_len,
131 unsigned *out)
132 {
133 struct odb_source_files *files = odb_source_files_downcast(source);
134 unsigned len = min_len;
135 int ret;
136
137 ret = odb_source_find_abbrev_len(&files->packed->base, oid, len, &len);
138 if (ret < 0)
139 goto out;
140
141 ret = odb_source_find_abbrev_len(&files->loose->base, oid, len, &len);
142 if (ret < 0)
143 goto out;
144
145 *out = len;
146 ret = 0;
147
148 out:
149 return ret;
150 }
151
152 static int odb_source_files_freshen_object(struct odb_source *source,
153 const struct object_id *oid,
154 const time_t *mtime)
155 {
156 struct odb_source_files *files = odb_source_files_downcast(source);
157 if (odb_source_freshen_object(&files->packed->base, oid, mtime) ||
158 odb_source_freshen_object(&files->loose->base, oid, mtime))
159 return 1;
160 return 0;
161 }
162
163 static int odb_source_files_write_object(struct odb_source *source,
164 const void *buf, size_t len,
165 enum object_type type,
166 const struct object_id *oid,
167 const struct object_id *compat_oid,
168 const time_t *mtime,
169 enum odb_write_object_flags flags)
170 {
171 struct odb_source_files *files = odb_source_files_downcast(source);
172 return odb_source_write_object(&files->loose->base, buf, len, type,
173 oid, compat_oid, mtime, flags);
174 }
175
176 static int odb_source_files_write_object_stream(struct odb_source *source,
177 struct odb_write_stream *stream,
178 size_t len,
179 struct object_id *oid)
180 {
181 struct odb_source_files *files = odb_source_files_downcast(source);
182 return odb_source_write_object_stream(&files->loose->base, stream, len, oid);
183 }
184
185 static int odb_source_files_begin_transaction(struct odb_source *source,
186 struct odb_transaction **out,
187 enum odb_transaction_flags flags)
188 {
189 return odb_transaction_files_begin(source, out, flags);
190 }
191
192 static int odb_source_files_read_alternates(struct odb_source *source,
193 struct strvec *out)
194 {
195 struct strbuf buf = STRBUF_INIT;
196 char *path;
197
198 path = xstrfmt("%s/info/alternates", source->path);
199 if (strbuf_read_file(&buf, path, 1024) < 0) {
200 warn_on_fopen_errors(path);
201 free(path);
202 return 0;
203 }
204 parse_alternates(buf.buf, '\n', source->path, out);
205
206 strbuf_release(&buf);
207 free(path);
208 return 0;
209 }
210
211 static int odb_source_files_write_alternate(struct odb_source *source,
212 const char *alternate)
213 {
214 struct lock_file lock = LOCK_INIT;
215 char *path = xstrfmt("%s/%s", source->path, "info/alternates");
216 FILE *in, *out;
217 int found = 0;
218 int ret;
219
220 repo_hold_lock_file_for_update(source->odb->repo, &lock, path,
221 LOCK_DIE_ON_ERROR);
222 out = fdopen_lock_file(&lock, "w");
223 if (!out) {
224 ret = error_errno(_("unable to fdopen alternates lockfile"));
225 goto out;
226 }
227
228 in = fopen(path, "r");
229 if (in) {
230 struct strbuf line = STRBUF_INIT;
231
232 while (strbuf_getline(&line, in) != EOF) {
233 if (!strcmp(alternate, line.buf)) {
234 found = 1;
235 break;
236 }
237 fprintf_or_die(out, "%s\n", line.buf);
238 }
239
240 strbuf_release(&line);
241 fclose(in);
242 } else if (errno != ENOENT) {
243 ret = error_errno(_("unable to read alternates file"));
244 goto out;
245 }
246
247 if (found) {
248 rollback_lock_file(&lock);
249 } else {
250 fprintf_or_die(out, "%s\n", alternate);
251 if (commit_lock_file(&lock)) {
252 ret = error_errno(_("unable to move new alternates file into place"));
253 goto out;
254 }
255 }
256
257 ret = 0;
258
259 out:
260 free(path);
261 return ret;
262 }
263
264 struct odb_source_files *odb_source_files_new(struct object_database *odb,
265 const char *path,
266 bool local)
267 {
268 struct odb_source_files *files;
269
270 CALLOC_ARRAY(files, 1);
271 odb_source_init(&files->base, odb, ODB_SOURCE_FILES, path, local);
272 files->loose = odb_source_loose_new(odb, path, local);
273 files->packed = odb_source_packed_new(odb, path, local);
274
275 files->base.free = odb_source_files_free;
276 files->base.close = odb_source_files_close;
277 files->base.prepare = odb_source_files_prepare;
278 files->base.read_object_info = odb_source_files_read_object_info;
279 files->base.read_object_stream = odb_source_files_read_object_stream;
280 files->base.for_each_object = odb_source_files_for_each_object;
281 files->base.count_objects = odb_source_files_count_objects;
282 files->base.find_abbrev_len = odb_source_files_find_abbrev_len;
283 files->base.freshen_object = odb_source_files_freshen_object;
284 files->base.write_object = odb_source_files_write_object;
285 files->base.write_object_stream = odb_source_files_write_object_stream;
286 files->base.begin_transaction = odb_source_files_begin_transaction;
287 files->base.read_alternates = odb_source_files_read_alternates;
288 files->base.write_alternate = odb_source_files_write_alternate;
289
290 /*
291 * Ideally, we would only ever store absolute paths in the source. This
292 * is not (yet) possible though because we access and assume relative
293 * paths in the primary ODB source in some user-facing functionality.
294 */
295 if (!is_absolute_path(path))
296 chdir_notify_register(NULL, odb_source_files_reparent, files);
297
298 return files;
299 }