int safe_create_leading_directories(char *path)
{
char *pos = path;
+ if (*pos == '/')
+ pos++;
while (pos) {
pos = strchr(pos, '/');
* alternate_object_database. The elements on this list come from
* non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
* environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
- * whose contents is exactly in the same format as that environment
- * variable. Its base points at a statically allocated buffer that
+ * whose contents is similar to that environment variable but can be
+ * LF separated. Its base points at a statically allocated buffer that
* contains "/the/directory/corresponding/to/.git/objects/...", while
* its name points just after the slash at the end of ".git/objects/"
* in the example above, and has enough space to hold 40-byte hex
{
const char *cp, *last;
struct alternate_object_database *ent;
+ const char *objdir = get_object_directory();
int base_len = -1;
last = alt;
for ( ; cp < ep && *cp != sep; cp++)
;
if (last != cp) {
+ struct alternate_object_database *alt;
/* 43 = 40-byte + 2 '/' + terminating NUL */
int pfxlen = cp - last;
int entlen = pfxlen + 43;
pfxlen += base_len;
}
ent = xmalloc(sizeof(*ent) + entlen);
- *alt_odb_tail = ent;
- alt_odb_tail = &(ent->next);
- ent->next = NULL;
+
if (*last != '/' && relative_base) {
memcpy(ent->base, relative_base, base_len - 1);
ent->base[base_len - 1] = '/';
ent->name = ent->base + pfxlen + 1;
ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
ent->base[entlen-1] = 0;
+
+ /* Prevent the common mistake of listing the same
+ * thing twice, or object directory itself.
+ */
+ for (alt = alt_odb_list; alt; alt = alt->next)
+ if (!memcmp(ent->base, alt->base, pfxlen))
+ goto bad;
+ if (!memcmp(ent->base, objdir, pfxlen)) {
+ bad:
+ free(ent);
+ }
+ else {
+ *alt_odb_tail = ent;
+ alt_odb_tail = &(ent->next);
+ ent->next = NULL;
+ }
}
while (cp < ep && *cp == sep)
cp++;
struct packed_git *p;
unsigned long idx_size;
void *idx_map;
+ unsigned char sha1[20];
if (check_packed_git_idx(path, &idx_size, &idx_map))
return NULL;
p->pack_last_used = 0;
p->pack_use_cnt = 0;
p->pack_local = local;
+ if (!get_sha1_hex(path + path_len - 40 - 4, sha1))
+ memcpy(p->sha1, sha1, 20);
return p;
}
prepare_packed_git_one(get_object_directory(), 1);
prepare_alt_odb();
for (alt = alt_odb_list; alt; alt = alt->next) {
- alt->name[0] = 0;
+ alt->name[-1] = 0;
prepare_packed_git_one(alt->base, 0);
+ alt->name[-1] = '/';
}
run_once = 1;
}
int move_temp_to_file(const char *tmpfile, char *filename)
{
int ret = link_temp_to_file(tmpfile, filename);
- if (ret) {
- /*
- * Coda hack - coda doesn't like cross-directory links,
- * so we fall back to a rename, which will mean that it
- * won't be able to check collisions, but that's not a
- * big deal.
- *
- * When this succeeds, we just return 0. We have nothing
- * left to unlink.
- */
- if (ret == EXDEV && !rename(tmpfile, filename))
+
+ /*
+ * Coda hack - coda doesn't like cross-directory links,
+ * so we fall back to a rename, which will mean that it
+ * won't be able to check collisions, but that's not a
+ * big deal.
+ *
+ * The same holds for FAT formatted media.
+ *
+ * When this succeeds, we just return 0. We have nothing
+ * left to unlink.
+ */
+ if (ret && ret != EEXIST) {
+ if (!rename(tmpfile, filename))
return 0;
+ ret = errno;
}
unlink(tmpfile);
if (ret) {
return find_sha1_file(sha1, &st) ? 1 : 0;
}
+int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)
+{
+ unsigned long size = 4096;
+ char *buf = malloc(size);
+ int iret, ret;
+ unsigned long off = 0;
+ unsigned char hdr[50];
+ int hdrlen;
+ do {
+ iret = read(fd, buf + off, size - off);
+ if (iret > 0) {
+ off += iret;
+ if (off == size) {
+ size *= 2;
+ buf = realloc(buf, size);
+ }
+ }
+ } while (iret > 0);
+ if (iret < 0) {
+ free(buf);
+ return -1;
+ }
+ if (!type)
+ type = "blob";
+ if (write_object)
+ ret = write_sha1_file(buf, off, type, sha1);
+ else {
+ write_sha1_file_prepare(buf, off, type, sha1, hdr, &hdrlen);
+ ret = 0;
+ }
+ free(buf);
+ return ret;
+}
+
int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type)
{
unsigned long size = st->st_size;