shallow.con commit rev-list --exclude: tests (751a2ac)
   1#include "cache.h"
   2#include "commit.h"
   3#include "tag.h"
   4
   5static int is_shallow = -1;
   6static struct stat shallow_stat;
   7static char *alternate_shallow_file;
   8
   9void set_alternate_shallow_file(const char *path)
  10{
  11        if (is_shallow != -1)
  12                die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
  13        free(alternate_shallow_file);
  14        alternate_shallow_file = path ? xstrdup(path) : NULL;
  15}
  16
  17int register_shallow(const unsigned char *sha1)
  18{
  19        struct commit_graft *graft =
  20                xmalloc(sizeof(struct commit_graft));
  21        struct commit *commit = lookup_commit(sha1);
  22
  23        hashcpy(graft->sha1, sha1);
  24        graft->nr_parent = -1;
  25        if (commit && commit->object.parsed)
  26                commit->parents = NULL;
  27        return register_commit_graft(graft, 0);
  28}
  29
  30int is_repository_shallow(void)
  31{
  32        FILE *fp;
  33        char buf[1024];
  34        const char *path = alternate_shallow_file;
  35
  36        if (is_shallow >= 0)
  37                return is_shallow;
  38
  39        if (!path)
  40                path = git_path("shallow");
  41        /*
  42         * fetch-pack sets '--shallow-file ""' as an indicator that no
  43         * shallow file should be used. We could just open it and it
  44         * will likely fail. But let's do an explicit check instead.
  45         */
  46        if (!*path ||
  47            stat(path, &shallow_stat) ||
  48            (fp = fopen(path, "r")) == NULL) {
  49                is_shallow = 0;
  50                return is_shallow;
  51        }
  52        is_shallow = 1;
  53
  54        while (fgets(buf, sizeof(buf), fp)) {
  55                unsigned char sha1[20];
  56                if (get_sha1_hex(buf, sha1))
  57                        die("bad shallow line: %s", buf);
  58                register_shallow(sha1);
  59        }
  60        fclose(fp);
  61        return is_shallow;
  62}
  63
  64struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
  65                int shallow_flag, int not_shallow_flag)
  66{
  67        int i = 0, cur_depth = 0;
  68        struct commit_list *result = NULL;
  69        struct object_array stack = OBJECT_ARRAY_INIT;
  70        struct commit *commit = NULL;
  71
  72        while (commit || i < heads->nr || stack.nr) {
  73                struct commit_list *p;
  74                if (!commit) {
  75                        if (i < heads->nr) {
  76                                commit = (struct commit *)
  77                                        deref_tag(heads->objects[i++].item, NULL, 0);
  78                                if (!commit || commit->object.type != OBJ_COMMIT) {
  79                                        commit = NULL;
  80                                        continue;
  81                                }
  82                                if (!commit->util)
  83                                        commit->util = xmalloc(sizeof(int));
  84                                *(int *)commit->util = 0;
  85                                cur_depth = 0;
  86                        } else {
  87                                commit = (struct commit *)
  88                                        stack.objects[--stack.nr].item;
  89                                cur_depth = *(int *)commit->util;
  90                        }
  91                }
  92                if (parse_commit(commit))
  93                        die("invalid commit");
  94                cur_depth++;
  95                if (cur_depth >= depth) {
  96                        commit_list_insert(commit, &result);
  97                        commit->object.flags |= shallow_flag;
  98                        commit = NULL;
  99                        continue;
 100                }
 101                commit->object.flags |= not_shallow_flag;
 102                for (p = commit->parents, commit = NULL; p; p = p->next) {
 103                        if (!p->item->util) {
 104                                int *pointer = xmalloc(sizeof(int));
 105                                p->item->util = pointer;
 106                                *pointer =  cur_depth;
 107                        } else {
 108                                int *pointer = p->item->util;
 109                                if (cur_depth >= *pointer)
 110                                        continue;
 111                                *pointer = cur_depth;
 112                        }
 113                        if (p->next)
 114                                add_object_array(&p->item->object,
 115                                                NULL, &stack);
 116                        else {
 117                                commit = p->item;
 118                                cur_depth = *(int *)commit->util;
 119                        }
 120                }
 121        }
 122
 123        return result;
 124}
 125
 126void check_shallow_file_for_update(void)
 127{
 128        struct stat st;
 129
 130        if (!is_shallow)
 131                return;
 132        else if (is_shallow == -1)
 133                die("BUG: shallow must be initialized by now");
 134
 135        if (stat(git_path("shallow"), &st))
 136                die("shallow file was removed during fetch");
 137        else if (st.st_mtime != shallow_stat.st_mtime
 138#ifdef USE_NSEC
 139                 || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
 140#endif
 141                   )
 142                die("shallow file was changed during fetch");
 143}