On a 'git add', instead of returning the SHA-1 of the subproject commit, write a real link object to the object database. Also implement parse_link_buffer() correspondingly. index_path() determines the upstream_url and checkout_rev from a pre-cloned submodule. The checkout_rev is set to the SHA-1 of the HEAD, and we get a non-floating submodule. While at it, fix the 'ls-tree' output to correctly show a link object. Signed-off-by: Ramkumar Ramachandra <artagnon@xxxxxxxxx> --- builtin/ls-tree.c | 4 ++-- link.c | 22 ++++++++++++++++++++++ sha1_file.c | 38 +++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index fb76e38..ab17fb5 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -6,7 +6,7 @@ #include "cache.h" #include "blob.h" #include "tree.h" -#include "commit.h" +#include "link.h" #include "quote.h" #include "builtin.h" #include "parse-options.h" @@ -76,7 +76,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, retval = READ_TREE_RECURSIVE; * */ - type = commit_type; + type = link_type; } else if (S_ISDIR(mode)) { if (show_recursive(base, baselen, pathname)) { retval = READ_TREE_RECURSIVE; diff --git a/link.c b/link.c index bb20a51..349646d 100644 --- a/link.c +++ b/link.c @@ -20,8 +20,30 @@ struct link *lookup_link(const unsigned char *sha1) int parse_link_buffer(struct link *item, void *buffer, unsigned long size) { + char *bufptr = buffer; + char *tail = buffer + size; + char *eol; + if (item->object.parsed) return 0; item->object.parsed = 1; + while (bufptr < tail) { + eol = strchr(bufptr, '\n'); + *eol = '\0'; + if (!prefixcmp(bufptr, "upstream_url = ")) + item->upstream_url = xstrdup(bufptr + 15); + else if (!prefixcmp(bufptr, "checkout_rev = ")) + item->checkout_rev = xstrdup(bufptr + 15); + else if (!prefixcmp(bufptr, "ref_name = ")) + item->ref_name = xstrdup(bufptr + 11); + else if (!prefixcmp(bufptr, "floating = ")) + item->floating = atoi(bufptr + 11); + else if (!prefixcmp(bufptr, "statthrough = ")) + item->statthrough = atoi(bufptr + 14); + else + return error("Parse error in link buffer"); + + bufptr = eol + 1; + } return 0; } diff --git a/sha1_file.c b/sha1_file.c index 5f573d9..a8a6d72 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -12,6 +12,7 @@ #include "pack.h" #include "blob.h" #include "commit.h" +#include "link.h" #include "run-command.h" #include "tag.h" #include "tree.h" @@ -35,6 +36,7 @@ static inline uintmax_t sz_fmt(size_t s) { return s; } const unsigned char null_sha1[20]; +void *upstream_url = NULL; /* * This is meant to hold a *small* number of objects that you would @@ -2859,10 +2861,19 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, return ret; } +static int parse_origin_url(const char *key, const char *value, void *cb) { + if (!strcmp(key, "remote.origin.url")) + upstream_url = xstrdup(value); + return 0; +} + int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags) { int fd; struct strbuf sb = STRBUF_INIT; + char pathbuf[PATH_MAX]; + const char *submodule_gitdir; + unsigned char checkout_rev[20]; switch (st->st_mode & S_IFMT) { case S_IFREG: @@ -2888,7 +2899,32 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned strbuf_release(&sb); break; case S_IFDIR: - return resolve_gitlink_ref(path, "HEAD", sha1); + /* gitlink. Prepare and write a new link object to + * the database. + */ + + /* Figure out upstream_url */ + sprintf(pathbuf, "%s/%s", path, ".git"); + submodule_gitdir = resolve_gitdir(pathbuf); + sprintf(pathbuf, "%s/%s", submodule_gitdir, "config"); + git_config_from_file(parse_origin_url, pathbuf, NULL); + if (!upstream_url) + die("Unable to read remote.origin.url from submodule"); + + /* Figure out checkout_rev */ + if (resolve_gitlink_ref(path, "HEAD", checkout_rev) < 0) + die("Unable to resolve submodule HEAD"); + + /* Add fields to the strbuf */ + strbuf_addf(&sb, "upstream_url = %s\n", (char *) upstream_url); + strbuf_addf(&sb, "checkout_rev = %s\n", sha1_to_hex(checkout_rev)); + if (!(flags & HASH_WRITE_OBJECT)) + hash_sha1_file(sb.buf, sb.len, link_type, sha1); + else if (write_sha1_file(sb.buf, sb.len, link_type, sha1)) + return error("%s: failed to insert into database", + path); + strbuf_release(&sb); + break; default: return error("%s: unsupported file type", path); } -- 1.8.2.380.g0d4e79b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html