resolve_gitlink_ref(): implement using resolve_ref_recursively()

resolve_ref_recursively() can handle references in arbitrary files reference stores, so use it to resolve "gitlink" (i.e., submodule) references. Aside from removing redundant code, this allows submodule lookups to benefit from the much more robust code that we use for reading non-submodule references. And, since the code is now agnostic about reference backends, it will work for any future references backend (so move its definition to refs.c). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Sep 4, 2016 at 18:08 UTC 424dcc7683a37d1f14aa0dd485300001cb854f6c
2 files changed +24 -67
refs.c
+24
@@ -1299,6 +1299,30 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
1299 resolve_flags, sha1, flags);
1300 }
1301
1302 +int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
1303 +{
1304 + int len = strlen(path);
1305 + struct strbuf submodule = STRBUF_INIT;
1306 + struct ref_store *refs;
1307 + int flags;
1308 +
1309 + while (len && path[len-1] == '/')
1310 + len--;
1311 + if (!len)
1312 + return -1;
1313 +
1314 + strbuf_add(&submodule, path, len);
1315 + refs = get_ref_store(submodule.buf);
1316 + strbuf_release(&submodule);
1317 + if (!refs)
1318 + return -1;
1319 +
1320 + if (!resolve_ref_recursively(refs, refname, 0, sha1, &flags) ||
1321 + is_null_sha1(sha1))
1322 + return -1;
1323 + return 0;
1324 +}
1325 +
1326 /* A pointer to the ref_store for the main repository: */
1327 static struct ref_store *main_ref_store;
1328
refs/files-backend.c
-67
@@ -1494,73 +1494,6 @@ static void unlock_ref(struct ref_lock *lock)
1494 free(lock);
1495 }
1496
1497 -#define MAXREFLEN (1024)
1498 -
1499 -static int resolve_gitlink_ref_recursive(struct files_ref_store *refs,
1500 - const char *refname, unsigned char *sha1,
1501 - int recursion)
1502 -{
1503 - int fd, len;
1504 - char buffer[128], *p;
1505 - char *path;
1506 -
1507 - if (recursion > SYMREF_MAXDEPTH || strlen(refname) > MAXREFLEN)
1508 - return -1;
1509 - path = *refs->base.submodule
1510 - ? git_pathdup_submodule(refs->base.submodule, "%s", refname)
1511 - : git_pathdup("%s", refname);
1512 - fd = open(path, O_RDONLY);
1513 - free(path);
1514 - if (fd < 0) {
1515 - unsigned int flags;
1516 -
1517 - return resolve_packed_ref(refs, refname, sha1, &flags);
1518 - }
1519 -
1520 - len = read(fd, buffer, sizeof(buffer)-1);
1521 - close(fd);
1522 - if (len < 0)
1523 - return -1;
1524 - while (len && isspace(buffer[len-1]))
1525 - len--;
1526 - buffer[len] = 0;
1527 -
1528 - /* Was it a detached head or an old-fashioned symlink? */
1529 - if (!get_sha1_hex(buffer, sha1))
1530 - return 0;
1531 -
1532 - /* Symref? */
1533 - if (strncmp(buffer, "ref:", 4))
1534 - return -1;
1535 - p = buffer + 4;
1536 - while (isspace(*p))
1537 - p++;
1538 -
1539 - return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);
1540 -}
1541 -
1542 -int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
1543 -{
1544 - int len = strlen(path);
1545 - struct strbuf submodule = STRBUF_INIT;
1546 - struct files_ref_store *refs;
1547 -
1548 - while (len && path[len-1] == '/')
1549 - len--;
1550 - if (!len)
1551 - return -1;
1552 -
1553 - strbuf_add(&submodule, path, len);
1554 - refs = get_files_ref_store(submodule.buf, "resolve_gitlink_ref");
1555 - if (!refs) {
1556 - strbuf_release(&submodule);
1557 - return -1;
1558 - }
1559 - strbuf_release(&submodule);
1560 -
1561 - return resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
1562 -}
1563 -
1497 /*
1498 * Lock refname, without following symrefs, and set *lock_p to point
1499 * at a newly-allocated lock object. Fill in lock->old_oid, referent,