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 <sbel...@google.com>
---
 builtin/clone.c | 42 ++++++--------------------------
 cache.h         |  1 +
 sha1_file.c     | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+), 35 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index f044a8c..24b17539 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -282,44 +282,16 @@ static void strip_trailing_slashes(char *dir)
 
 static int add_one_reference(struct string_list_item *item, void *cb_data)
 {
-       char *ref_git;
-       const char *repo;
-       struct strbuf alternate = STRBUF_INIT;
-
-       /* Beware: read_gitfile(), real_path() and mkpath() return static 
buffer */
-       ref_git = xstrdup(real_path(item->string));
-
-       repo = read_gitfile(ref_git);
-       if (!repo)
-               repo = read_gitfile(mkpath("%s/.git", ref_git));
-       if (repo) {
-               free(ref_git);
-               ref_git = xstrdup(repo);
-       }
-
-       if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
-               char *ref_git_git = mkpathdup("%s/.git", ref_git);
-               free(ref_git);
-               ref_git = ref_git_git;
-       } else if (!is_directory(mkpath("%s/objects", ref_git))) {
-               struct strbuf sb = STRBUF_INIT;
-               if (get_common_dir(&sb, ref_git))
-                       die(_("reference repository '%s' as a linked checkout 
is not supported yet."),
-                           item->string);
-               die(_("reference repository '%s' is not a local repository."),
-                   item->string);
-       }
+       struct strbuf sb = STRBUF_INIT;
+       char *ref_git = compute_alternate_path(item->string, &sb);
 
-       if (!access(mkpath("%s/shallow", ref_git), F_OK))
-               die(_("reference repository '%s' is shallow"), item->string);
+       if (!ref_git)
+               die("%s", sb.buf);
 
-       if (!access(mkpath("%s/info/grafts", ref_git), F_OK))
-               die(_("reference repository '%s' is grafted"), item->string);
+       strbuf_addf(&sb, "%s/objects", ref_git);
+       add_to_alternates_file(sb.buf);
 
-       strbuf_addf(&alternate, "%s/objects", ref_git);
-       add_to_alternates_file(alternate.buf);
-       strbuf_release(&alternate);
-       free(ref_git);
+       strbuf_release(&sb);
        return 0;
 }
 
diff --git a/cache.h b/cache.h
index 95a0bd3..35f41f7 100644
--- a/cache.h
+++ b/cache.h
@@ -1344,6 +1344,7 @@ extern struct alternate_object_database {
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
 extern void read_info_alternates(const char * relative_base, int depth);
+extern char *compute_alternate_path(const char *path, struct strbuf *err);
 extern void add_to_alternates_file(const char *reference);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 extern int foreach_alt_odb(alt_odb_fn, void*);
diff --git a/sha1_file.c b/sha1_file.c
index 02940f1..7351d8c 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -418,6 +418,80 @@ void add_to_alternates_file(const char *reference)
        free(alts);
 }
 
+/*
+ * Compute the exact path an alternate is at and returns it. In case of
+ * error NULL is returned and the human readable error is added to `err`
+ * `path` may be relative and should point to $GITDIR.
+ * `err` must not be null.
+ */
+char *compute_alternate_path(const char *path, struct strbuf *err)
+{
+       char *ref_git = NULL;
+       const char *repo, *ref_git_s;
+       struct strbuf err_buf = STRBUF_INIT;
+
+       ref_git_s = real_path_if_valid(path);
+       if (!ref_git_s) {
+               strbuf_addf(&err_buf, _("path '%s' does not exist"), path);
+               goto out;
+       } else
+               /*
+                * Beware: read_gitfile(), real_path() and mkpath()
+                * return static buffer
+                */
+               ref_git = xstrdup(ref_git_s);
+
+       repo = read_gitfile(ref_git);
+       if (!repo)
+               repo = read_gitfile(mkpath("%s/.git", ref_git));
+       if (repo) {
+               free(ref_git);
+               ref_git = xstrdup(repo);
+       }
+
+       if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
+               char *ref_git_git = mkpathdup("%s/.git", ref_git);
+               free(ref_git);
+               ref_git = ref_git_git;
+       } else if (!is_directory(mkpath("%s/objects", ref_git))) {
+               struct strbuf sb = STRBUF_INIT;
+               if (get_common_dir(&sb, ref_git)) {
+                       strbuf_addf(&err_buf,
+                                   _("reference repository '%s' as a linked "
+                                     "checkout is not supported yet."),
+                                   path);
+                       goto out;
+               }
+
+               strbuf_addf(&err_buf, _("reference repository '%s' is not a "
+                                       "local repository."), path);
+               goto out;
+       }
+
+       if (!access(mkpath("%s/shallow", ref_git), F_OK)) {
+               strbuf_addf(&err_buf, _("reference repository '%s' is shallow"),
+                           path);
+               goto out;
+       }
+
+       if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) {
+               strbuf_addf(&err_buf,
+                           _("reference repository '%s' is grafted"),
+                           path);
+               goto out;
+       }
+
+out:
+       if (err_buf.len) {
+               strbuf_addbuf(err, &err_buf);
+               free(ref_git);
+               ref_git = NULL;
+       }
+
+       strbuf_release(&err_buf);
+       return ref_git;
+}
+
 int foreach_alt_odb(alt_odb_fn fn, void *cb)
 {
        struct alternate_object_database *ent;
-- 
2.9.2.737.g4a14654

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to