[fr] update french translation 2210/2210
[gitweb.git] / sha1_file.c
index f80bbe467437a4ffc161a4cdd09f97cf5436d4f9..e13bd2c3ee7edb4d157e499fbcea80535ec5752f 100644 (file)
@@ -807,15 +807,38 @@ void free_pack_by_name(const char *pack_name)
 static unsigned int get_max_fd_limit(void)
 {
 #ifdef RLIMIT_NOFILE
-       struct rlimit lim;
+       {
+               struct rlimit lim;
 
-       if (getrlimit(RLIMIT_NOFILE, &lim))
-               die_errno("cannot get RLIMIT_NOFILE");
+               if (!getrlimit(RLIMIT_NOFILE, &lim))
+                       return lim.rlim_cur;
+       }
+#endif
+
+#ifdef _SC_OPEN_MAX
+       {
+               long open_max = sysconf(_SC_OPEN_MAX);
+               if (0 < open_max)
+                       return open_max;
+               /*
+                * Otherwise, we got -1 for one of the two
+                * reasons:
+                *
+                * (1) sysconf() did not understand _SC_OPEN_MAX
+                *     and signaled an error with -1; or
+                * (2) sysconf() said there is no limit.
+                *
+                * We _could_ clear errno before calling sysconf() to
+                * tell these two cases apart and return a huge number
+                * in the latter case to let the caller cap it to a
+                * value that is not so selfish, but letting the
+                * fallback OPEN_MAX codepath take care of these cases
+                * is a lot simpler.
+                */
+       }
+#endif
 
-       return lim.rlim_cur;
-#elif defined(_SC_OPEN_MAX)
-       return sysconf(_SC_OPEN_MAX);
-#elif defined(OPEN_MAX)
+#ifdef OPEN_MAX
        return OPEN_MAX;
 #else
        return 1; /* see the caller ;-) */
@@ -1442,51 +1465,6 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
        return map;
 }
 
-/*
- * There used to be a second loose object header format which
- * was meant to mimic the in-pack format, allowing for direct
- * copy of the object data.  This format turned up not to be
- * really worth it and we no longer write loose objects in that
- * format.
- */
-static int experimental_loose_object(unsigned char *map)
-{
-       unsigned int word;
-
-       /*
-        * We must determine if the buffer contains the standard
-        * zlib-deflated stream or the experimental format based
-        * on the in-pack object format. Compare the header byte
-        * for each format:
-        *
-        * RFC1950 zlib w/ deflate : 0www1000 : 0 <= www <= 7
-        * Experimental pack-based : Stttssss : ttt = 1,2,3,4
-        *
-        * If bit 7 is clear and bits 0-3 equal 8, the buffer MUST be
-        * in standard loose-object format, UNLESS it is a Git-pack
-        * format object *exactly* 8 bytes in size when inflated.
-        *
-        * However, RFC1950 also specifies that the 1st 16-bit word
-        * must be divisible by 31 - this checksum tells us our buffer
-        * is in the standard format, giving a false positive only if
-        * the 1st word of the Git-pack format object happens to be
-        * divisible by 31, ie:
-        *      ((byte0 * 256) + byte1) % 31 = 0
-        *   =>        0ttt10000www1000 % 31 = 0
-        *
-        * As it happens, this case can only arise for www=3 & ttt=1
-        * - ie, a Commit object, which would have to be 8 bytes in
-        * size. As no Commit can be that small, we find that the
-        * combination of these two criteria (bitmask & checksum)
-        * can always correctly determine the buffer format.
-        */
-       word = (map[0] << 8) + map[1];
-       if ((map[0] & 0x8F) == 0x08 && !(word % 31))
-               return 0;
-       else
-               return 1;
-}
-
 unsigned long unpack_object_header_buffer(const unsigned char *buf,
                unsigned long len, enum object_type *type, unsigned long *sizep)
 {
@@ -1514,14 +1492,6 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
 
 int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
 {
-       unsigned long size, used;
-       static const char valid_loose_object_type[8] = {
-               0, /* OBJ_EXT */
-               1, 1, 1, 1, /* "commit", "tree", "blob", "tag" */
-               0, /* "delta" and others are invalid in a loose object */
-       };
-       enum object_type type;
-
        /* Get the data stream */
        memset(stream, 0, sizeof(*stream));
        stream->next_in = map;
@@ -1529,27 +1499,6 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma
        stream->next_out = buffer;
        stream->avail_out = bufsiz;
 
-       if (experimental_loose_object(map)) {
-               /*
-                * The old experimental format we no longer produce;
-                * we can still read it.
-                */
-               used = unpack_object_header_buffer(map, mapsize, &type, &size);
-               if (!used || !valid_loose_object_type[type])
-                       return -1;
-               map += used;
-               mapsize -= used;
-
-               /* Set up the stream for the rest.. */
-               stream->next_in = map;
-               stream->avail_in = mapsize;
-               git_inflate_init(stream);
-
-               /* And generate the fake traditional header */
-               stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
-                                                typename(type), size);
-               return 0;
-       }
        git_inflate_init(stream);
        return git_inflate(stream, 0);
 }
@@ -1741,6 +1690,38 @@ static off_t get_delta_base(struct packed_git *p,
        return base_offset;
 }
 
+/*
+ * Like get_delta_base above, but we return the sha1 instead of the pack
+ * offset. This means it is cheaper for REF deltas (we do not have to do
+ * the final object lookup), but more expensive for OFS deltas (we
+ * have to load the revidx to convert the offset back into a sha1).
+ */
+static const unsigned char *get_delta_base_sha1(struct packed_git *p,
+                                               struct pack_window **w_curs,
+                                               off_t curpos,
+                                               enum object_type type,
+                                               off_t delta_obj_offset)
+{
+       if (type == OBJ_REF_DELTA) {
+               unsigned char *base = use_pack(p, w_curs, curpos, NULL);
+               return base;
+       } else if (type == OBJ_OFS_DELTA) {
+               struct revindex_entry *revidx;
+               off_t base_offset = get_delta_base(p, w_curs, &curpos,
+                                                  type, delta_obj_offset);
+
+               if (!base_offset)
+                       return NULL;
+
+               revidx = find_pack_revindex(p, base_offset);
+               if (!revidx)
+                       return NULL;
+
+               return nth_packed_object_sha1(p, revidx->nr);
+       } else
+               return NULL;
+}
+
 int unpack_object_header(struct packed_git *p,
                         struct pack_window **w_curs,
                         off_t *curpos,
@@ -1898,6 +1879,22 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
                }
        }
 
+       if (oi->delta_base_sha1) {
+               if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
+                       const unsigned char *base;
+
+                       base = get_delta_base_sha1(p, &w_curs, curpos,
+                                                  type, obj_offset);
+                       if (!base) {
+                               type = OBJ_BAD;
+                               goto out;
+                       }
+
+                       hashcpy(oi->delta_base_sha1, base);
+               } else
+                       hashclr(oi->delta_base_sha1);
+       }
+
 out:
        unuse_pack(&w_curs);
        return type;
@@ -2481,17 +2478,23 @@ static int sha1_loose_object_info(const unsigned char *sha1,
        git_zstream stream;
        char hdr[32];
 
+       if (oi->delta_base_sha1)
+               hashclr(oi->delta_base_sha1);
+
        /*
         * If we don't care about type or size, then we don't
-        * need to look inside the object at all.
+        * need to look inside the object at all. Note that we
+        * do not optimize out the stat call, even if the
+        * caller doesn't care about the disk-size, since our
+        * return value implicitly indicates whether the
+        * object even exists.
         */
        if (!oi->typep && !oi->sizep) {
-               if (oi->disk_sizep) {
-                       struct stat st;
-                       if (stat_sha1_file(sha1, &st) < 0)
-                               return -1;
+               struct stat st;
+               if (stat_sha1_file(sha1, &st) < 0)
+                       return -1;
+               if (oi->disk_sizep)
                        *oi->disk_sizep = st.st_size;
-               }
                return 0;
        }
 
@@ -2514,14 +2517,14 @@ static int sha1_loose_object_info(const unsigned char *sha1,
        return 0;
 }
 
-/* returns enum object_type or negative */
-int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
+int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
 {
        struct cached_object *co;
        struct pack_entry e;
        int rtype;
+       const unsigned char *real = lookup_replace_object_extended(sha1, flags);
 
-       co = find_cached_object(sha1);
+       co = find_cached_object(real);
        if (co) {
                if (oi->typep)
                        *(oi->typep) = co->type;
@@ -2529,27 +2532,29 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
                        *(oi->sizep) = co->size;
                if (oi->disk_sizep)
                        *(oi->disk_sizep) = 0;
+               if (oi->delta_base_sha1)
+                       hashclr(oi->delta_base_sha1);
                oi->whence = OI_CACHED;
                return 0;
        }
 
-       if (!find_pack_entry(sha1, &e)) {
+       if (!find_pack_entry(real, &e)) {
                /* Most likely it's a loose object. */
-               if (!sha1_loose_object_info(sha1, oi)) {
+               if (!sha1_loose_object_info(real, oi)) {
                        oi->whence = OI_LOOSE;
                        return 0;
                }
 
                /* Not a loose object; someone else may have just packed it. */
                reprepare_packed_git();
-               if (!find_pack_entry(sha1, &e))
+               if (!find_pack_entry(real, &e))
                        return -1;
        }
 
        rtype = packed_object_info(e.p, e.offset, oi);
        if (rtype < 0) {
-               mark_bad_packed_object(e.p, sha1);
-               return sha1_object_info_extended(sha1, oi);
+               mark_bad_packed_object(e.p, real);
+               return sha1_object_info_extended(real, oi, 0);
        } else if (in_delta_base_cache(e.p, e.offset)) {
                oi->whence = OI_DBCACHED;
        } else {
@@ -2563,6 +2568,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
        return 0;
 }
 
+/* returns enum object_type or negative */
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
        enum object_type type;
@@ -2570,7 +2576,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 
        oi.typep = &type;
        oi.sizep = sizep;
-       if (sha1_object_info_extended(sha1, &oi) < 0)
+       if (sha1_object_info_extended(sha1, &oi, LOOKUP_REPLACE_OBJECT) < 0)
                return -1;
        return type;
 }
@@ -2662,8 +2668,7 @@ void *read_sha1_file_extended(const unsigned char *sha1,
        void *data;
        char *path;
        const struct packed_git *p;
-       const unsigned char *repl = (flag & READ_SHA1_FILE_REPLACE)
-               ? lookup_replace_object(sha1) : sha1;
+       const unsigned char *repl = lookup_replace_object_extended(sha1, flag);
 
        errno = 0;
        data = read_object(repl, type, size);
@@ -2857,7 +2862,9 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
                /* Make sure the directory exists */
                memcpy(buffer, filename, dirlen);
                buffer[dirlen-1] = 0;
-               if (mkdir(buffer, 0777) || adjust_shared_perm(buffer))
+               if (mkdir(buffer, 0777) && errno != EEXIST)
+                       return -1;
+               if (adjust_shared_perm(buffer))
                        return -1;
 
                /* Try again */