clone: factor out checking for an alternate path
In a later patch we want to determine if a path is suitable as an alternate from other commands than builtin/clone. Move the checking functionality of `add_one_reference` to `compute_alternate_path` that is defined in cache.h. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stefan Beller committed
Aug 15, 2016 at 14:53 UTC
9eeea7d2bc8132cfaa1b79271c077e80317f3ae1
3 files changed
+86
-34
builtin/clone.c
+9
-34
@@ -282,44 +282,19 @@ static void strip_trailing_slashes(char *dir)
282
283
static int add_one_reference(struct string_list_item *item, void *cb_data)
284
{
285
- char *ref_git;
286
- const char *repo;
287
- struct strbuf alternate = STRBUF_INIT;
288
-
289
- /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */
290
- ref_git = xstrdup(real_path(item->string));
291
-
292
- repo = read_gitfile(ref_git);
293
- if (!repo)
294
- repo = read_gitfile(mkpath("%s/.git", ref_git));
295
- if (repo) {
296
- free(ref_git);
297
- ref_git = xstrdup(repo);
298
- }
299
-
300
- if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
301
- char *ref_git_git = mkpathdup("%s/.git", ref_git);
302
- free(ref_git);
303
- ref_git = ref_git_git;
304
- } else if (!is_directory(mkpath("%s/objects", ref_git))) {
305
- struct strbuf sb = STRBUF_INIT;
306
- if (get_common_dir(&sb, ref_git))
307
- die(_("reference repository '%s' as a linked checkout is not supported yet."),
308
- item->string);
309
- die(_("reference repository '%s' is not a local repository."),
310
- item->string);
311
- }
285
+ struct strbuf err = STRBUF_INIT;
286
+ struct strbuf sb = STRBUF_INIT;
287
+ char *ref_git = compute_alternate_path(item->string, &err);
288
313
- if (!access(mkpath("%s/shallow", ref_git), F_OK))
314
- die(_("reference repository '%s' is shallow"), item->string);
289
+ if (!ref_git)
290
+ die("%s", err.buf);
291
316
- if (!access(mkpath("%s/info/grafts", ref_git), F_OK))
317
- die(_("reference repository '%s' is grafted"), item->string);
292
+ strbuf_addf(&sb, "%s/objects", ref_git);
293
+ add_to_alternates_file(sb.buf);
294
319
- strbuf_addf(&alternate, "%s/objects", ref_git);
320
- add_to_alternates_file(alternate.buf);
321
- strbuf_release(&alternate);
295
free(ref_git);
296
+ strbuf_release(&err);
297
+ strbuf_release(&sb);
298
return 0;
299
}
300
cache.h
+1
@@ -1342,6 +1342,7 @@ extern struct alternate_object_database {
1342
} *alt_odb_list;
1343
extern void prepare_alt_odb(void);
1344
extern void read_info_alternates(const char * relative_base, int depth);
1345
+extern char *compute_alternate_path(const char *path, struct strbuf *err);
1346
extern void add_to_alternates_file(const char *reference);
1347
typedef int alt_odb_fn(struct alternate_object_database *, void *);
1348
extern int foreach_alt_odb(alt_odb_fn, void*);
sha1_file.c
+76
@@ -425,6 +425,82 @@ void add_to_alternates_file(const char *reference)
425
free(alts);
426
}
427
428
+/*
429
+ * Compute the exact path an alternate is at and returns it. In case of
430
+ * error NULL is returned and the human readable error is added to `err`
431
+ * `path` may be relative and should point to $GITDIR.
432
+ * `err` must not be null.
433
+ */
434
+char *compute_alternate_path(const char *path, struct strbuf *err)
435
+{
436
+ char *ref_git = NULL;
437
+ const char *repo, *ref_git_s;
438
+ int seen_error = 0;
439
+
440
+ ref_git_s = real_path_if_valid(path);
441
+ if (!ref_git_s) {
442
+ seen_error = 1;
443
+ strbuf_addf(err, _("path '%s' does not exist"), path);
444
+ goto out;
445
+ } else
446
+ /*
447
+ * Beware: read_gitfile(), real_path() and mkpath()
448
+ * return static buffer
449
+ */
450
+ ref_git = xstrdup(ref_git_s);
451
+
452
+ repo = read_gitfile(ref_git);
453
+ if (!repo)
454
+ repo = read_gitfile(mkpath("%s/.git", ref_git));
455
+ if (repo) {
456
+ free(ref_git);
457
+ ref_git = xstrdup(repo);
458
+ }
459
+
460
+ if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
461
+ char *ref_git_git = mkpathdup("%s/.git", ref_git);
462
+ free(ref_git);
463
+ ref_git = ref_git_git;
464
+ } else if (!is_directory(mkpath("%s/objects", ref_git))) {
465
+ struct strbuf sb = STRBUF_INIT;
466
+ seen_error = 1;
467
+ if (get_common_dir(&sb, ref_git)) {
468
+ strbuf_addf(err,
469
+ _("reference repository '%s' as a linked "
470
+ "checkout is not supported yet."),
471
+ path);
472
+ goto out;
473
+ }
474
+
475
+ strbuf_addf(err, _("reference repository '%s' is not a "
476
+ "local repository."), path);
477
+ goto out;
478
+ }
479
+
480
+ if (!access(mkpath("%s/shallow", ref_git), F_OK)) {
481
+ strbuf_addf(err, _("reference repository '%s' is shallow"),
482
+ path);
483
+ seen_error = 1;
484
+ goto out;
485
+ }
486
+
487
+ if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) {
488
+ strbuf_addf(err,
489
+ _("reference repository '%s' is grafted"),
490
+ path);
491
+ seen_error = 1;
492
+ goto out;
493
+ }
494
+
495
+out:
496
+ if (seen_error) {
497
+ free(ref_git);
498
+ ref_git = NULL;
499
+ }
500
+
501
+ return ref_git;
502
+}
503
+
504
int foreach_alt_odb(alt_odb_fn fn, void *cb)
505
{
506
struct alternate_object_database *ent;