+static struct alternate_object_database
+{
+ char *base;
+ char *name;
+} *alt_odb;
+
+static void prepare_alt_odb(void)
+{
+ int pass, totlen, i;
+ void *buf;
+ const char *cp, *last;
+ char *op = 0;
+ const char *alt = getenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
+
+ for (totlen = pass = 0; pass < 2; pass++) {
+ last = alt;
+ i = 0;
+ do {
+ cp = strchr(last, ':') ? : last + strlen(last);
+ if (last != cp) {
+ /* 43 = 40-byte + 2 '/' + terminating NUL */
+ int pfxlen = cp - last;
+ int entlen = pfxlen + 43;
+ if (pass == 0)
+ totlen += entlen;
+ else {
+ alt_odb[i].base = op;
+ alt_odb[i].name = op + pfxlen + 1;
+ memcpy(op, last, pfxlen);
+ op[pfxlen] = op[pfxlen + 3] = '/';
+ op[entlen-1] = 0;
+ op += entlen;
+ }
+ i++;
+ }
+ while (*cp && *cp == ':')
+ cp++;
+ last = cp;
+ } while (*cp);
+ if (pass)
+ break;
+ alt_odb = buf = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);
+ alt_odb[i].base = alt_odb[i].name = 0;
+ op = (char*)(&alt_odb[i+1]);
+ }
+}
+
+static char *find_sha1_file(const unsigned char *sha1, struct stat *st)
+{
+ int i;
+ char *name = sha1_file_name(sha1);
+
+ if (!stat(name, st))
+ return name;
+ if (!alt_odb)
+ prepare_alt_odb();
+ for (i = 0; (name = alt_odb[i].name) != NULL; i++) {
+ fill_sha1_path(name, sha1);
+ if (!stat(alt_odb[i].base, st))
+ return alt_odb[i].base;
+ }
+ return NULL;
+}
+