builtin-fsck: reports missing parent commits
[gitweb.git] / sha1_file.c
index aea10961fdd9ba6e14514701a49bd69cb594a695..0ca7f0dbc6eda54e43240a45f2cff4cf70659fbd 100644 (file)
@@ -14,7 +14,6 @@
 #include "tag.h"
 #include "tree.h"
 #include "refs.h"
-#include "strbuf.h"
 
 #ifndef O_NOATIME
 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
 
 #ifdef NO_C99_FORMAT
 #define SZ_FMT "lu"
+static unsigned long sz_fmt(size_t s) { return (unsigned long)s; }
 #else
 #define SZ_FMT "zu"
+static size_t sz_fmt(size_t s) { return s; }
 #endif
 
 const unsigned char null_sha1[20];
@@ -87,7 +88,7 @@ int safe_create_leading_directories(char *path)
        char *pos = path;
        struct stat st;
 
-       if (*pos == '/')
+       if (is_absolute_path(path))
                pos++;
 
        while (pos) {
@@ -147,7 +148,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
 
 /*
  * NOTE! This returns a statically allocated buffer, so you have to be
- * careful about using it. Do a "xstrdup()" if you need to save the
+ * careful about using it. Do an "xstrdup()" if you need to save the
  * filename.
  *
  * Also note that this returns the location for creating.  Reading
@@ -254,7 +255,7 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
        int entlen = pfxlen + 43;
        int base_len = -1;
 
-       if (*entry != '/' && relative_base) {
+       if (!is_absolute_path(entry) && relative_base) {
                /* Relative alt-odb */
                if (base_len < 0)
                        base_len = strlen(relative_base) + 1;
@@ -263,7 +264,7 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
        }
        ent = xmalloc(sizeof(*ent) + entlen);
 
-       if (*entry != '/' && relative_base) {
+       if (!is_absolute_path(entry) && relative_base) {
                memcpy(ent->base, relative_base, base_len - 1);
                ent->base[base_len - 1] = '/';
                memcpy(ent->base + base_len, entry, len);
@@ -334,7 +335,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
                while (cp < ep && *cp != sep)
                        cp++;
                if (last != cp) {
-                       if ((*last != '/') && depth) {
+                       if (!is_absolute_path(last) && depth) {
                                error("%s: ignoring relative alternate object store %s",
                                                relative_base, last);
                        } else {
@@ -424,9 +425,9 @@ void pack_report(void)
                "pack_report: getpagesize()            = %10" SZ_FMT "\n"
                "pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
                "pack_report: core.packedGitLimit      = %10" SZ_FMT "\n",
-               (size_t) getpagesize(),
-               packed_git_window_size,
-               packed_git_limit);
+               sz_fmt(getpagesize()),
+               sz_fmt(packed_git_window_size),
+               sz_fmt(packed_git_limit));
        fprintf(stderr,
                "pack_report: pack_used_ctr            = %10u\n"
                "pack_report: pack_mmap_calls          = %10u\n"
@@ -436,7 +437,7 @@ void pack_report(void)
                pack_used_ctr,
                pack_mmap_calls,
                pack_open_windows, peak_pack_open_windows,
-               pack_mapped, peak_pack_mapped);
+               sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
 }
 
 static int check_packed_git_idx(const char *path,  struct packed_git *p)
@@ -522,13 +523,15 @@ static int check_packed_git_idx(const char *path,  struct packed_git *p)
                        munmap(idx_map, idx_size);
                        return error("wrong index v2 file size in %s", path);
                }
-               if (idx_size != min_size) {
-                       /* make sure we can deal with large pack offsets */
-                       off_t x = 0x7fffffffUL, y = 0xffffffffUL;
-                       if (x > (x + 1) || y > (y + 1)) {
-                               munmap(idx_map, idx_size);
-                               return error("pack too large for current definition of off_t in %s", path);
-                       }
+               if (idx_size != min_size &&
+                   /*
+                    * make sure we can deal with large pack offsets.
+                    * 31-bit signed offset won't be enough, neither
+                    * 32-bit unsigned one will be.
+                    */
+                   (sizeof(off_t) <= 4)) {
+                       munmap(idx_map, idx_size);
+                       return error("pack too large for current definition of off_t in %s", path);
                }
        }
 
@@ -608,6 +611,22 @@ void release_pack_memory(size_t need, int fd)
                ; /* nothing */
 }
 
+void close_pack_windows(struct packed_git *p)
+{
+       while (p->windows) {
+               struct pack_window *w = p->windows;
+
+               if (w->inuse_cnt)
+                       die("pack '%s' still has open windows to it",
+                           p->pack_name);
+               munmap(w->base, w->len);
+               pack_mapped -= w->len;
+               pack_open_windows--;
+               p->windows = w->next;
+               free(w);
+       }
+}
+
 void unuse_pack(struct pack_window **w_cursor)
 {
        struct pack_window *w = *w_cursor;
@@ -1492,11 +1511,8 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
                ent->lru.next->prev = ent->lru.prev;
                ent->lru.prev->next = ent->lru.next;
                delta_base_cached -= ent->size;
-       }
-       else {
-               ret = xmalloc(ent->size + 1);
-               memcpy(ret, ent->data, ent->size);
-               ((char *)ret)[ent->size] = 0;
+       } else {
+               ret = xmemdupz(ent->data, ent->size);
        }
        *type = ent->type;
        *base_size = ent->size;
@@ -1685,22 +1701,22 @@ off_t find_pack_entry_one(const unsigned char *sha1,
        return 0;
 }
 
-static int matches_pack_name(struct packed_git *p, const char *ig)
+int matches_pack_name(struct packed_git *p, const char *name)
 {
        const char *last_c, *c;
 
-       if (!strcmp(p->pack_name, ig))
-               return 0;
+       if (!strcmp(p->pack_name, name))
+               return 1;
 
        for (c = p->pack_name, last_c = c; *c;)
                if (*c == '/')
                        last_c = ++c;
                else
                        ++c;
-       if (!strcmp(last_c, ig))
-               return 0;
+       if (!strcmp(last_c, name))
+               return 1;
 
-       return 1;
+       return 0;
 }
 
 static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed)
@@ -1718,7 +1734,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons
                if (ignore_packed) {
                        const char **ig;
                        for (ig = ignore_packed; *ig; ig++)
-                               if (!matches_pack_name(p, *ig))
+                               if (matches_pack_name(p, *ig))
                                        break;
                        if (*ig)
                                goto next;
@@ -1873,12 +1889,9 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
 
        co = find_cached_object(sha1);
        if (co) {
-               buf = xmalloc(co->size + 1);
-               memcpy(buf, co->buf, co->size);
-               ((char*)buf)[co->size] = 0;
                *type = co->type;
                *size = co->size;
-               return buf;
+               return xmemdupz(co->buf, co->size);
        }
 
        buf = read_packed_sha1(sha1, type, size);
@@ -1930,7 +1943,8 @@ void *read_object_with_reference(const unsigned char *sha1,
                }
                ref_length = strlen(ref_type);
 
-               if (memcmp(buffer, ref_type, ref_length) ||
+               if (ref_length + 40 > isize ||
+                   memcmp(buffer, ref_type, ref_length) ||
                    get_sha1_hex((char *) buffer + ref_length, actual_sha1)) {
                        free(buffer);
                        return NULL;
@@ -2343,12 +2357,11 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
         * Convert blobs to git internal format
         */
        if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
-               unsigned long nsize = size;
-               char *nbuf = convert_to_git(path, buf, &nsize);
-               if (nbuf) {
+               struct strbuf nbuf;
+               strbuf_init(&nbuf, 0);
+               if (convert_to_git(path, buf, size, &nbuf)) {
                        munmap(buf, size);
-                       size = nsize;
-                       buf = nbuf;
+                       buf = strbuf_detach(&nbuf, &size);
                        re_allocated = 1;
                }
        }