Merge branch 'ja/i18n-fix'
[gitweb.git] / shallow.c
index 9f6ee3513199a1814e5e7f511036126e7a684580..02fdbfc554c462c1eecdf1ddc6d17edbc1d8d853 100644 (file)
--- a/shallow.c
+++ b/shallow.c
 #include "commit-slab.h"
 #include "revision.h"
 #include "list-objects.h"
+#include "commit-slab.h"
 #include "repository.h"
+#include "commit-reach.h"
 
 void set_alternate_shallow_file(struct repository *r, const char *path, int override)
 {
        if (r->parsed_objects->is_shallow != -1)
-               die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
+               BUG("is_repository_shallow must not be called before set_alternate_shallow_file");
        if (r->parsed_objects->alternate_shallow_file && !override)
                return;
        free(r->parsed_objects->alternate_shallow_file);
@@ -30,7 +32,7 @@ int register_shallow(struct repository *r, const struct object_id *oid)
 {
        struct commit_graft *graft =
                xmalloc(sizeof(struct commit_graft));
-       struct commit *commit = lookup_commit(oid);
+       struct commit *commit = lookup_commit(the_repository, oid);
 
        oidcpy(&graft->oid, oid);
        graft->nr_parent = -1;
@@ -73,6 +75,11 @@ int is_repository_shallow(struct repository *r)
        return r->parsed_objects->is_shallow;
 }
 
+/*
+ * TODO: use "int" elemtype instead of "int *" when/if commit-slab
+ * supports a "valid" flag.
+ */
+define_commit_slab(commit_depth, int *);
 struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                int shallow_flag, int not_shallow_flag)
 {
@@ -81,25 +88,31 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
        struct object_array stack = OBJECT_ARRAY_INIT;
        struct commit *commit = NULL;
        struct commit_graft *graft;
+       struct commit_depth depths;
 
+       init_commit_depth(&depths);
        while (commit || i < heads->nr || stack.nr) {
                struct commit_list *p;
                if (!commit) {
                        if (i < heads->nr) {
+                               int **depth_slot;
                                commit = (struct commit *)
-                                       deref_tag(heads->objects[i++].item, NULL, 0);
+                                       deref_tag(the_repository,
+                                                 heads->objects[i++].item,
+                                                 NULL, 0);
                                if (!commit || commit->object.type != OBJ_COMMIT) {
                                        commit = NULL;
                                        continue;
                                }
-                               if (!commit->util)
-                                       commit->util = xmalloc(sizeof(int));
-                               *(int *)commit->util = 0;
+                               depth_slot = commit_depth_at(&depths, commit);
+                               if (!*depth_slot)
+                                       *depth_slot = xmalloc(sizeof(int));
+                               **depth_slot = 0;
                                cur_depth = 0;
                        } else {
                                commit = (struct commit *)
                                        object_array_pop(&stack);
-                               cur_depth = *(int *)commit->util;
+                               cur_depth = **commit_depth_at(&depths, commit);
                        }
                }
                parse_commit_or_die(commit);
@@ -115,25 +128,31 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                }
                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));
-                               p->item->util = pointer;
-                               *pointer =  cur_depth;
+                       int **depth_slot = commit_depth_at(&depths, p->item);
+                       if (!*depth_slot) {
+                               *depth_slot = xmalloc(sizeof(int));
+                               **depth_slot = cur_depth;
                        } else {
-                               int *pointer = p->item->util;
-                               if (cur_depth >= *pointer)
+                               if (cur_depth >= **depth_slot)
                                        continue;
-                               *pointer = cur_depth;
+                               **depth_slot = cur_depth;
                        }
                        if (p->next)
                                add_object_array(&p->item->object,
                                                NULL, &stack);
                        else {
                                commit = p->item;
-                               cur_depth = *(int *)commit->util;
+                               cur_depth = **commit_depth_at(&depths, commit);
                        }
                }
        }
+       for (i = 0; i < depths.slab_count; i++) {
+               int j;
+
+               for (j = 0; j < depths.slab_size; j++)
+                       free(depths.slab[i][j]);
+       }
+       clear_commit_depth(&depths);
 
        return result;
 }
@@ -166,7 +185,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
 
        is_repository_shallow(the_repository); /* make sure shallows are read */
 
-       init_revisions(&revs, NULL);
+       repo_init_revisions(the_repository, &revs, NULL);
        save_commit_buffer = 0;
        setup_revisions(ac, av, &revs, NULL);
 
@@ -174,6 +193,9 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
                die("revision walk setup failed");
        traverse_commit_list(&revs, show_commit, NULL, &not_shallow_list);
 
+       if (!not_shallow_list)
+               die("no commits selected for shallow requests");
+
        /* Mark all reachable commits as NOT_SHALLOW */
        for (p = not_shallow_list; p; p = p->next)
                p->item->object.flags |= not_shallow_flag;
@@ -217,7 +239,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av,
 static void check_shallow_file_for_update(struct repository *r)
 {
        if (r->parsed_objects->is_shallow == -1)
-               die("BUG: shallow must be initialized by now");
+               BUG("shallow must be initialized by now");
 
        if (!stat_validity_check(r->parsed_objects->shallow_stat, git_path_shallow(the_repository)))
                die("shallow file has changed since we read it");
@@ -225,6 +247,7 @@ static void check_shallow_file_for_update(struct repository *r)
 
 #define SEEN_ONLY 1
 #define VERBOSE   2
+#define QUICK 4
 
 struct write_shallow_data {
        struct strbuf *out;
@@ -239,8 +262,11 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
        const char *hex = oid_to_hex(&graft->oid);
        if (graft->nr_parent != -1)
                return 0;
-       if (data->flags & SEEN_ONLY) {
-               struct commit *c = lookup_commit(&graft->oid);
+       if (data->flags & QUICK) {
+               if (!has_object_file(&graft->oid))
+                       return 0;
+       } else if (data->flags & SEEN_ONLY) {
+               struct commit *c = lookup_commit(the_repository, &graft->oid);
                if (!c || !(c->object.flags & SEEN)) {
                        if (data->flags & VERBOSE)
                                printf("Removing %s from .git/shallow\n",
@@ -349,16 +375,23 @@ void advertise_shallow_grafts(int fd)
 
 /*
  * mark_reachable_objects() should have been run prior to this and all
- * reachable commits marked as "SEEN".
+ * reachable commits marked as "SEEN", except when quick_prune is non-zero,
+ * in which case lines are excised from the shallow file if they refer to
+ * commits that do not exist (any longer).
  */
-void prune_shallow(int show_only)
+void prune_shallow(unsigned options)
 {
-       static struct lock_file shallow_lock;
+       struct lock_file shallow_lock = LOCK_INIT;
        struct strbuf sb = STRBUF_INIT;
+       unsigned flags = SEEN_ONLY;
        int fd;
 
-       if (show_only) {
-               write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY | VERBOSE);
+       if (options & PRUNE_QUICK)
+               flags |= QUICK;
+
+       if (options & PRUNE_SHOW_ONLY) {
+               flags |= VERBOSE;
+               write_shallow_commits_1(&sb, 0, NULL, flags);
                strbuf_release(&sb);
                return;
        }
@@ -366,7 +399,7 @@ void prune_shallow(int show_only)
                                       git_path_shallow(the_repository),
                                       LOCK_DIE_ON_ERROR);
        check_shallow_file_for_update(the_repository);
-       if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
+       if (write_shallow_commits_1(&sb, 0, NULL, flags)) {
                if (write_in_full(fd, sb.buf, sb.len) < 0)
                        die_errno("failed to write to %s",
                                  get_lock_file_path(&shallow_lock));
@@ -448,7 +481,7 @@ static uint32_t *paint_alloc(struct paint_info *info)
        void *p;
        if (!info->pool_count || size > info->end - info->free) {
                if (size > POOL_SIZE)
-                       die("BUG: pool size too small for %d in paint_alloc()",
+                       BUG("pool size too small for %d in paint_alloc()",
                            size);
                info->pool_count++;
                REALLOC_ARRAY(info->pools, info->pool_count);
@@ -473,7 +506,8 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
        struct commit_list *head = NULL;
        int bitmap_nr = DIV_ROUND_UP(info->nr_bits, 32);
        size_t bitmap_size = st_mult(sizeof(uint32_t), bitmap_nr);
-       struct commit *c = lookup_commit_reference_gently(oid, 1);
+       struct commit *c = lookup_commit_reference_gently(the_repository, oid,
+                                                         1);
        uint32_t *tmp; /* to be freed before return */
        uint32_t *bitmap;
 
@@ -535,7 +569,8 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
 static int mark_uninteresting(const char *refname, const struct object_id *oid,
                              int flags, void *cb_data)
 {
-       struct commit *commit = lookup_commit_reference_gently(oid, 1);
+       struct commit *commit = lookup_commit_reference_gently(the_repository,
+                                                              oid, 1);
        if (!commit)
                return 0;
        commit->object.flags |= UNINTERESTING;
@@ -603,7 +638,8 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,
 
        /* Mark potential bottoms so we won't go out of bound */
        for (i = 0; i < nr_shallow; i++) {
-               struct commit *c = lookup_commit(&oid[shallow[i]]);
+               struct commit *c = lookup_commit(the_repository,
+                                                &oid[shallow[i]]);
                c->object.flags |= BOTTOM;
        }
 
@@ -614,7 +650,8 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,
                int bitmap_size = DIV_ROUND_UP(pi.nr_bits, 32) * sizeof(uint32_t);
                memset(used, 0, sizeof(*used) * info->shallow->nr);
                for (i = 0; i < nr_shallow; i++) {
-                       const struct commit *c = lookup_commit(&oid[shallow[i]]);
+                       const struct commit *c = lookup_commit(the_repository,
+                                                              &oid[shallow[i]]);
                        uint32_t **map = ref_bitmap_at(&pi.ref_bitmap, c);
                        if (*map)
                                used[shallow[i]] = xmemdupz(*map, bitmap_size);
@@ -645,7 +682,8 @@ static int add_ref(const char *refname, const struct object_id *oid,
 {
        struct commit_array *ca = cb_data;
        ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);
-       ca->commits[ca->nr] = lookup_commit_reference_gently(oid, 1);
+       ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,
+                                                            oid, 1);
        if (ca->commits[ca->nr])
                ca->nr++;
        return 0;
@@ -683,7 +721,7 @@ static void post_assign_shallow(struct shallow_info *info,
        for (i = dst = 0; i < info->nr_theirs; i++) {
                if (i != dst)
                        info->theirs[dst] = info->theirs[i];
-               c = lookup_commit(&oid[info->theirs[i]]);
+               c = lookup_commit(the_repository, &oid[info->theirs[i]]);
                bitmap = ref_bitmap_at(ref_bitmap, c);
                if (!*bitmap)
                        continue;
@@ -704,7 +742,7 @@ static void post_assign_shallow(struct shallow_info *info,
        for (i = dst = 0; i < info->nr_ours; i++) {
                if (i != dst)
                        info->ours[dst] = info->ours[i];
-               c = lookup_commit(&oid[info->ours[i]]);
+               c = lookup_commit(the_repository, &oid[info->ours[i]]);
                bitmap = ref_bitmap_at(ref_bitmap, c);
                if (!*bitmap)
                        continue;
@@ -726,7 +764,8 @@ static void post_assign_shallow(struct shallow_info *info,
 int delayed_reachability_test(struct shallow_info *si, int c)
 {
        if (si->need_reachability_test[c]) {
-               struct commit *commit = lookup_commit(&si->shallow->oid[c]);
+               struct commit *commit = lookup_commit(the_repository,
+                                                     &si->shallow->oid[c]);
 
                if (!si->commits) {
                        struct commit_array ca;