X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=sha1_file.c;h=e6ce455ae90bd430f2128f454bdb6e0575412486;hb=03d791ff117dfdca610a7bfe9ba12dddda504b94;hp=e1ee0ad349497d6470bc00aa7f1085d9d1b83b43;hpb=35ad33823e90fb166a6480cdc9195051535e9788;p=git.git diff --git a/sha1_file.c b/sha1_file.c index e1ee0ad3..e6ce455a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -60,37 +60,6 @@ int get_sha1_file(const char *path, unsigned char *result) return get_sha1_hex(buffer, result); } -static int get_parent(int index, const char *str, unsigned char *result) -{ - unsigned char sha1[20]; - char *buffer; - unsigned long size, offset; - int ret; - - if (get_sha1(str, sha1) < 0) - return -1; - buffer = read_object_with_reference(sha1, "commit", &size, NULL); - if (!buffer) - return -1; - ret = -1; - offset = 46; - for (;;) { - if (offset + 48 > size) - break; - if (memcmp(buffer + offset, "parent ", 7)) - break; - if (index > 0) { - offset += 48; - index--; - continue; - } - ret = get_sha1_hex(buffer + offset + 7, result); - break; - } - free(buffer); - return ret; -} - int get_sha1(const char *str, unsigned char *sha1) { static char pathname[PATH_MAX]; @@ -108,19 +77,6 @@ int get_sha1(const char *str, unsigned char *sha1) if (!get_sha1_hex(str, sha1)) return 0; - switch (*str) { - case '/': - if (!get_sha1_file(str, sha1)) - return 0; - break; - case '-': - return get_parent(0, str+1, sha1); - case '0' ... '9': - if (str[1] == '-') - return get_parent(*str - '0', str+2, sha1); - break; - } - gitdir = ".git"; for (p = prefix; *p; p++) { snprintf(pathname, sizeof(pathname), "%s/%s/%s", gitdir, *p, str); @@ -328,8 +284,9 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha unsigned char sha1[20]; SHA_CTX c; char *filename; + static char tmpfile[PATH_MAX]; char hdr[50]; - int fd, hdrlen; + int fd, hdrlen, ret; /* Generate the header */ hdrlen = sprintf(hdr, "%s %lu", type, len)+1; @@ -344,18 +301,28 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha memcpy(returnsha1, sha1, 20); filename = sha1_file_name(sha1); - fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (fd < 0) { - if (errno != EEXIST) - return -1; - + fd = open(filename, O_RDONLY); + if (fd >= 0) { /* - * We might do collision checking here, but we'd need to - * uncompress the old file and check it. Later. + * FIXME!!! We might do collision checking here, but we'd + * need to uncompress the old file and check it. Later. */ + close(fd); return 0; } + if (errno != ENOENT) { + fprintf(stderr, "sha1 file %s: %s", filename, strerror(errno)); + return -1; + } + + snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + fd = mkstemp(tmpfile); + if (fd < 0) { + fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno)); + return -1; + } + /* Set it up */ memset(&stream, 0, sizeof(stream)); deflateInit(&stream, Z_BEST_COMPRESSION); @@ -382,54 +349,34 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha if (write(fd, compressed, size) != size) die("unable to write file"); + fchmod(fd, 0444); close(fd); - - return 0; -} -static inline int collision_check(char *filename, void *buf, unsigned int size) -{ -#ifdef COLLISION_CHECK - void *map; - int fd = open(filename, O_RDONLY); - struct stat st; - int cmp; + ret = link(tmpfile, filename); + if (ret < 0) { + ret = errno; - /* Unreadable object, or object went away? Strange. */ - if (fd < 0) - return -1; - - if (fstat(fd, &st) < 0 || size != st.st_size) - return -1; - - map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - if (map == MAP_FAILED) - return -1; - cmp = memcmp(buf, map, size); - munmap(map, size); - if (cmp) - return -1; -#endif - return 0; -} - -int write_sha1_buffer(const unsigned char *sha1, void *buf, unsigned int size) -{ - char *filename = sha1_file_name(sha1); - int fd; - - fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (fd < 0) { - if (errno != EEXIST) + /* + * 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)) + return 0; + } + unlink(tmpfile); + if (ret) { + if (ret != EEXIST) { + fprintf(stderr, "unable to write sha1 filename %s: %s", filename, strerror(ret)); return -1; - if (collision_check(filename, buf, size)) - return error("SHA1 collision detected!" - " This is bad, bad, BAD!\a\n"); - return 0; + } + /* FIXME!!! Collision check here ? */ } - write(fd, buf, size); - close(fd); + return 0; } @@ -504,3 +451,22 @@ int has_sha1_file(const unsigned char *sha1) return 1; return 0; } + +int index_fd(unsigned char *sha1, int fd, struct stat *st) +{ + unsigned long size = st->st_size; + void *buf; + int ret; + + buf = ""; + if (size) + buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + if ((int)(long)buf == -1) + return -1; + + ret = write_sha1_file(buf, size, "blob", sha1); + if (size) + munmap(buf, size); + return ret; +}