send-email: be explicit with SSL certificate verification
[gitweb.git] / shallow.c
index 4d90eda19efe0a80c1cb39e8897ab3ed5e6fcf56..cbe2526d8c2b2643957eea2729a16269a7a74fab 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -3,6 +3,16 @@
 #include "tag.h"
 
 static int is_shallow = -1;
+static struct stat shallow_stat;
+static char *alternate_shallow_file;
+
+void set_alternate_shallow_file(const char *path)
+{
+       if (is_shallow != -1)
+               die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
+       free(alternate_shallow_file);
+       alternate_shallow_file = path ? xstrdup(path) : NULL;
+}
 
 int register_shallow(const unsigned char *sha1)
 {
@@ -21,12 +31,21 @@ int is_repository_shallow(void)
 {
        FILE *fp;
        char buf[1024];
+       const char *path = alternate_shallow_file;
 
        if (is_shallow >= 0)
                return is_shallow;
 
-       fp = fopen(git_path("shallow"), "r");
-       if (!fp) {
+       if (!path)
+               path = git_path("shallow");
+       /*
+        * fetch-pack sets '--shallow-file ""' as an indicator that no
+        * shallow file should be used. We could just open it and it
+        * will likely fail. But let's do an explicit check instead.
+        */
+       if (!*path ||
+           stat(path, &shallow_stat) ||
+           (fp = fopen(path, "r")) == NULL) {
                is_shallow = 0;
                return is_shallow;
        }
@@ -47,7 +66,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
 {
        int i = 0, cur_depth = 0;
        struct commit_list *result = NULL;
-       struct object_array stack = {0, 0, NULL};
+       struct object_array stack = OBJECT_ARRAY_INIT;
        struct commit *commit = NULL;
 
        while (commit || i < heads->nr || stack.nr) {
@@ -72,8 +91,14 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                }
                if (parse_commit(commit))
                        die("invalid commit");
-               commit->object.flags |= not_shallow_flag;
                cur_depth++;
+               if (cur_depth >= depth) {
+                       commit_list_insert(commit, &result);
+                       commit->object.flags |= shallow_flag;
+                       commit = NULL;
+                       continue;
+               }
+               commit->object.flags |= not_shallow_flag;
                for (p = commit->parents, commit = NULL; p; p = p->next) {
                        if (!p->item->util) {
                                int *pointer = xmalloc(sizeof(int));
@@ -102,3 +127,22 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
 
        return result;
 }
+
+void check_shallow_file_for_update(void)
+{
+       struct stat st;
+
+       if (!is_shallow)
+               return;
+       else if (is_shallow == -1)
+               die("BUG: shallow must be initialized by now");
+
+       if (stat(git_path("shallow"), &st))
+               die("shallow file was removed during fetch");
+       else if (st.st_mtime != shallow_stat.st_mtime
+#ifdef USE_NSEC
+                || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
+#endif
+                  )
+               die("shallow file was changed during fetch");
+}