Merge branch 'lt/rev-list-gitlink'
authorJunio C Hamano <gitster@pobox.com>
Mon, 19 Nov 2007 00:16:37 +0000 (16:16 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 19 Nov 2007 00:16:37 +0000 (16:16 -0800)
* lt/rev-list-gitlink:
Fix rev-list when showing objects involving submodules

1  2 
revision.c
diff --combined revision.c
index 8f0287fcc0ff4409afa1c16774cfb6086c48ae8f,e8650c35a7e48a24d185e123eedb9b336d6bc799..2a59035192baec8265acccf8b5d00aa7b2db4dd7
@@@ -10,8 -10,6 +10,8 @@@
  #include "reflog-walk.h"
  #include "patch-ids.h"
  
 +volatile show_early_output_fn_t show_early_output;
 +
  static char *path_name(struct name_path *path, const char *name)
  {
        struct name_path *p;
@@@ -67,10 -65,17 +67,17 @@@ void mark_tree_uninteresting(struct tre
  
        init_tree_desc(&desc, tree->buffer, tree->size);
        while (tree_entry(&desc, &entry)) {
-               if (S_ISDIR(entry.mode))
+               switch (object_type(entry.mode)) {
+               case OBJ_TREE:
                        mark_tree_uninteresting(lookup_tree(entry.sha1));
-               else
+                       break;
+               case OBJ_BLOB:
                        mark_blob_uninteresting(lookup_blob(entry.sha1));
+                       break;
+               default:
+                       /* Subproject commit - not in this repository */
+                       break;
+               }
        }
  
        /*
@@@ -252,7 -257,7 +259,7 @@@ static void file_add_remove(struct diff
        }
        tree_difference = diff;
        if (tree_difference == REV_TREE_DIFFERENT)
 -              options->has_changes = 1;
 +              DIFF_OPT_SET(options, HAS_CHANGES);
  }
  
  static void file_change(struct diff_options *options,
                 const char *base, const char *path)
  {
        tree_difference = REV_TREE_DIFFERENT;
 -      options->has_changes = 1;
 +      DIFF_OPT_SET(options, HAS_CHANGES);
  }
  
  static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
        if (!t2)
                return REV_TREE_DIFFERENT;
        tree_difference = REV_TREE_SAME;
 -      revs->pruning.has_changes = 0;
 +      DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
        if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
                           &revs->pruning) < 0)
                return REV_TREE_DIFFERENT;
@@@ -296,7 -301,7 +303,7 @@@ static int rev_same_tree_as_empty(struc
        init_tree_desc(&empty, "", 0);
  
        tree_difference = REV_TREE_SAME;
 -      revs->pruning.has_changes = 0;
 +      DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
        retval = diff_tree(&empty, &real, "", &revs->pruning);
        free(tree);
  
@@@ -308,28 -313,15 +315,28 @@@ static void try_to_simplify_commit(stru
        struct commit_list **pp, *parent;
        int tree_changed = 0, tree_same = 0;
  
 +      /*
 +       * If we don't do pruning, everything is interesting
 +       */
 +      if (!revs->prune)
 +              return;
 +
        if (!commit->tree)
                return;
  
        if (!commit->parents) {
 -              if (!rev_same_tree_as_empty(revs, commit->tree))
 -                      commit->object.flags |= TREECHANGE;
 +              if (rev_same_tree_as_empty(revs, commit->tree))
 +                      commit->object.flags |= TREESAME;
                return;
        }
  
 +      /*
 +       * Normal non-merge commit? If we don't want to make the
 +       * history dense, we consider it always to be a change..
 +       */
 +      if (!revs->dense && !commit->parents->next)
 +              return;
 +
        pp = &commit->parents;
        while ((parent = *pp) != NULL) {
                struct commit *p = parent->item;
                        }
                        parent->next = NULL;
                        commit->parents = parent;
 +                      commit->object.flags |= TREESAME;
                        return;
  
                case REV_TREE_NEW:
                die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
        }
        if (tree_changed && !tree_same)
 -              commit->object.flags |= TREECHANGE;
 +              return;
 +      commit->object.flags |= TREESAME;
  }
  
  static int add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
         * simplify the commit history and find the parent
         * that has no differences in the path set if one exists.
         */
 -      if (revs->prune_fn)
 -              revs->prune_fn(revs, commit);
 +      try_to_simplify_commit(revs, commit);
  
        if (revs->no_walk)
                return 0;
@@@ -549,7 -540,6 +556,7 @@@ static int limit_list(struct rev_info *
                struct commit_list *entry = list;
                struct commit *commit = list->item;
                struct object *obj = &commit->object;
 +              show_early_output_fn_t show;
  
                list = list->next;
                free(entry);
                if (revs->min_age != -1 && (commit->date > revs->min_age))
                        continue;
                p = &commit_list_insert(commit, p)->next;
 +
 +              show = show_early_output;
 +              if (!show)
 +                      continue;
 +
 +              show(revs, newlist);
 +              show_early_output = NULL;
        }
        if (revs->cherry_pick)
                cherry_pick_list(newlist, revs);
@@@ -686,8 -669,8 +693,8 @@@ void init_revisions(struct rev_info *re
        revs->abbrev = DEFAULT_ABBREV;
        revs->ignore_merges = 1;
        revs->simplify_history = 1;
 -      revs->pruning.recursive = 1;
 -      revs->pruning.quiet = 1;
 +      DIFF_OPT_SET(&revs->pruning, RECURSIVE);
 +      DIFF_OPT_SET(&revs->pruning, QUIET);
        revs->pruning.add_remove = file_add_remove;
        revs->pruning.change = file_change;
        revs->lifo = 1;
        revs->skip_count = -1;
        revs->max_count = -1;
  
 -      revs->prune_fn = NULL;
 -      revs->prune_data = NULL;
 -
 -      revs->topo_setter = topo_sort_default_setter;
 -      revs->topo_getter = topo_sort_default_getter;
 -
        revs->commit_format = CMIT_FMT_DEFAULT;
  
        diff_setup(&revs->diffopt);
@@@ -1012,18 -1001,6 +1019,18 @@@ int setup_revisions(int argc, const cha
                                revs->topo_order = 1;
                                continue;
                        }
 +                      if (!prefixcmp(arg, "--early-output")) {
 +                              int count = 100;
 +                              switch (arg[14]) {
 +                              case '=':
 +                                      count = atoi(arg+15);
 +                                      /* Fallthrough */
 +                              case 0:
 +                                      revs->topo_order = 1;
 +                                      revs->early_output = count;
 +                                      continue;
 +                              }
 +                      }
                        if (!strcmp(arg, "--parents")) {
                                revs->parents = 1;
                                continue;
                        }
                        if (!strcmp(arg, "-r")) {
                                revs->diff = 1;
 -                              revs->diffopt.recursive = 1;
 +                              DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
                                continue;
                        }
                        if (!strcmp(arg, "-t")) {
                                revs->diff = 1;
 -                              revs->diffopt.recursive = 1;
 -                              revs->diffopt.tree_in_recursive = 1;
 +                              DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
 +                              DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
                                continue;
                        }
                        if (!strcmp(arg, "-m")) {
                revs->diff = 1;
  
        /* Pickaxe and rename following needs diffs */
 -      if (revs->diffopt.pickaxe || revs->diffopt.follow_renames)
 +      if (revs->diffopt.pickaxe || DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
                revs->diff = 1;
  
        if (revs->topo_order)
        if (revs->prune_data) {
                diff_tree_setup_paths(revs->prune_data, &revs->pruning);
                /* Can't prune commits with rename following: the paths change.. */
 -              if (!revs->diffopt.follow_renames)
 -                      revs->prune_fn = try_to_simplify_commit;
 +              if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
 +                      revs->prune = 1;
                if (!revs->full_diff)
                        diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
        }
@@@ -1333,7 -1310,9 +1340,7 @@@ int prepare_revision_walk(struct rev_in
                if (limit_list(revs) < 0)
                        return -1;
        if (revs->topo_order)
 -              sort_in_topological_order_fn(&revs->commits, revs->lifo,
 -                                           revs->topo_setter,
 -                                           revs->topo_getter);
 +              sort_in_topological_order(&revs->commits, revs->lifo);
        return 0;
  }
  
@@@ -1352,9 -1331,7 +1359,9 @@@ static enum rewrite_result rewrite_one(
                                return rewrite_one_error;
                if (p->parents && p->parents->next)
                        return rewrite_one_ok;
 -              if (p->object.flags & (TREECHANGE | UNINTERESTING))
 +              if (p->object.flags & UNINTERESTING)
 +                      return rewrite_one_ok;
 +              if (!(p->object.flags & TREESAME))
                        return rewrite_one_ok;
                if (!p->parents)
                        return rewrite_one_noparents;
@@@ -1411,36 -1388,6 +1418,36 @@@ static int commit_match(struct commit *
                           commit->buffer, strlen(commit->buffer));
  }
  
 +enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 +{
 +      if (commit->object.flags & SHOWN)
 +              return commit_ignore;
 +      if (revs->unpacked && has_sha1_pack(commit->object.sha1, revs->ignore_packed))
 +              return commit_ignore;
 +      if (commit->object.flags & UNINTERESTING)
 +              return commit_ignore;
 +      if (revs->min_age != -1 && (commit->date > revs->min_age))
 +              return commit_ignore;
 +      if (revs->no_merges && commit->parents && commit->parents->next)
 +              return commit_ignore;
 +      if (!commit_match(commit, revs))
 +              return commit_ignore;
 +      if (revs->prune && revs->dense) {
 +              /* Commit without changes? */
 +              if (commit->object.flags & TREESAME) {
 +                      /* drop merges unless we want parenthood */
 +                      if (!revs->parents)
 +                              return commit_ignore;
 +                      /* non-merge - always ignore it */
 +                      if (!commit->parents || !commit->parents->next)
 +                              return commit_ignore;
 +              }
 +              if (revs->parents && rewrite_parents(revs, commit) < 0)
 +                      return commit_error;
 +      }
 +      return commit_show;
 +}
 +
  static struct commit *get_revision_1(struct rev_info *revs)
  {
        if (!revs->commits)
                        if (add_parents_to_list(revs, commit, &revs->commits) < 0)
                                return NULL;
                }
 -              if (commit->object.flags & SHOWN)
 -                      continue;
  
 -              if (revs->unpacked && has_sha1_pack(commit->object.sha1,
 -                                                  revs->ignore_packed))
 -                  continue;
 -
 -              if (commit->object.flags & UNINTERESTING)
 -                      continue;
 -              if (revs->min_age != -1 && (commit->date > revs->min_age))
 +              switch (simplify_commit(revs, commit)) {
 +              case commit_ignore:
                        continue;
 -              if (revs->no_merges &&
 -                  commit->parents && commit->parents->next)
 -                      continue;
 -              if (!commit_match(commit, revs))
 -                      continue;
 -              if (revs->prune_fn && revs->dense) {
 -                      /* Commit without changes? */
 -                      if (!(commit->object.flags & TREECHANGE)) {
 -                              /* drop merges unless we want parenthood */
 -                              if (!revs->parents)
 -                                      continue;
 -                              /* non-merge - always ignore it */
 -                              if (!commit->parents || !commit->parents->next)
 -                                      continue;
 -                      }
 -                      if (revs->parents && rewrite_parents(revs, commit) < 0)
 -                              return NULL;
 +              case commit_error:
 +                      return NULL;
 +              default:
 +                      return commit;
                }
 -              return commit;
        } while (revs->commits);
        return NULL;
  }