attr.c: update a stale comment on "struct match_attr"
[gitweb.git] / sha1_file.c
index 64e1a21fc61ed24a0b33c12578eab50546ec6270..1eb47f61131a81b587dc4fe80e1b175f37ba0540 100644 (file)
 #include "mru.h"
 #include "list.h"
 #include "mergesort.h"
-
-#ifndef O_NOATIME
-#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
-#define O_NOATIME 01000000
-#else
-#define O_NOATIME 0
-#endif
-#endif
+#include "quote.h"
 
 #define SZ_FMT PRIuMAX
 static inline uintmax_t sz_fmt(size_t s) { return s; }
@@ -296,7 +289,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
        }
        strbuf_addstr(&pathbuf, entry);
 
-       if (strbuf_normalize_path(&pathbuf) < 0) {
+       if (strbuf_normalize_path(&pathbuf) < 0 && relative_base) {
                error("unable to normalize alternate object path: %s",
                      pathbuf.buf);
                strbuf_release(&pathbuf);
@@ -329,13 +322,40 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
        return 0;
 }
 
+static const char *parse_alt_odb_entry(const char *string,
+                                      int sep,
+                                      struct strbuf *out)
+{
+       const char *end;
+
+       strbuf_reset(out);
+
+       if (*string == '#') {
+               /* comment; consume up to next separator */
+               end = strchrnul(string, sep);
+       } else if (*string == '"' && !unquote_c_style(out, string, &end)) {
+               /*
+                * quoted path; unquote_c_style has copied the
+                * data for us and set "end". Broken quoting (e.g.,
+                * an entry that doesn't end with a quote) falls
+                * back to the unquoted case below.
+                */
+       } else {
+               /* normal, unquoted path */
+               end = strchrnul(string, sep);
+               strbuf_add(out, string, end - string);
+       }
+
+       if (*end)
+               end++;
+       return end;
+}
+
 static void link_alt_odb_entries(const char *alt, int len, int sep,
                                 const char *relative_base, int depth)
 {
-       struct string_list entries = STRING_LIST_INIT_NODUP;
-       char *alt_copy;
-       int i;
        struct strbuf objdirbuf = STRBUF_INIT;
+       struct strbuf entry = STRBUF_INIT;
 
        if (depth > 5) {
                error("%s: ignoring alternate object stores, nesting too deep.",
@@ -348,16 +368,13 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
                die("unable to normalize object directory: %s",
                    objdirbuf.buf);
 
-       alt_copy = xmemdupz(alt, len);
-       string_list_split_in_place(&entries, alt_copy, sep, -1);
-       for (i = 0; i < entries.nr; i++) {
-               const char *entry = entries.items[i].string;
-               if (entry[0] == '\0' || entry[0] == '#')
+       while (*alt) {
+               alt = parse_alt_odb_entry(alt, sep, &entry);
+               if (!entry.len)
                        continue;
-               link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf);
+               link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf);
        }
-       string_list_clear(&entries, 0);
-       free(alt_copy);
+       strbuf_release(&entry);
        strbuf_release(&objdirbuf);
 }
 
@@ -1410,6 +1427,32 @@ static void prepare_packed_git_one(char *objdir, int local)
        strbuf_release(&path);
 }
 
+static int approximate_object_count_valid;
+
+/*
+ * Give a fast, rough count of the number of objects in the repository. This
+ * ignores loose objects completely. If you have a lot of them, then either
+ * you should repack because your performance will be awful, or they are
+ * all unreachable objects about to be pruned, in which case they're not really
+ * interesting as a measure of repo size in the first place.
+ */
+unsigned long approximate_object_count(void)
+{
+       static unsigned long count;
+       if (!approximate_object_count_valid) {
+               struct packed_git *p;
+
+               prepare_packed_git();
+               count = 0;
+               for (p = packed_git; p; p = p->next) {
+                       if (open_pack_index(p))
+                               continue;
+                       count += p->num_objects;
+               }
+       }
+       return count;
+}
+
 static void *get_next_packed_git(const void *p)
 {
        return ((const struct packed_git *)p)->next;
@@ -1481,6 +1524,7 @@ void prepare_packed_git(void)
 
 void reprepare_packed_git(void)
 {
+       approximate_object_count_valid = 0;
        prepare_packed_git_run_once = 0;
        prepare_packed_git();
 }
@@ -1586,19 +1630,6 @@ int git_open_cloexec(const char *name, int flags)
        return fd;
 }
 
-int git_open(const char *name)
-{
-       static int noatime = O_NOATIME;
-       int fd = git_open_cloexec(name, O_RDONLY);
-
-       if (0 <= fd && (noatime & O_NOATIME)) {
-               int flags = fcntl(fd, F_GETFL);
-               if (fcntl(fd, F_SETFL, flags | noatime))
-                       noatime = 0;
-       }
-       return fd;
-}
-
 static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
 {
        struct alternate_object_database *alt;
@@ -3353,6 +3384,11 @@ int has_object_file(const struct object_id *oid)
        return has_sha1_file(oid->hash);
 }
 
+int has_object_file_with_flags(const struct object_id *oid, int flags)
+{
+       return has_sha1_file_with_flags(oid->hash, flags);
+}
+
 static void check_tree(const void *buf, size_t size)
 {
        struct tree_desc desc;