Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Teach revision walking machinery to walk multiple times sequencially

Previously it was not possible to iterate revisions twice using the
revision walking api. We add a reset_revision_walk() which clears the
used flags. This allows us to do multiple sequencial revision walks.

We add the appropriate calls to the existing submodule machinery doing
revision walks. This is done to avoid surprises if future code wants to
call these functions more than once during the processes lifetime.

Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information...
commit bcc0a3ea38a42a64878e11c5244ef2fcc967e05d 1 parent 6f5e880
Heiko Voigt authored gitster committed
1  .gitignore
@@ -183,6 +183,7 @@
183 183 /test-mktemp
184 184 /test-parse-options
185 185 /test-path-utils
  186 +/test-revision-walking
186 187 /test-run-command
187 188 /test-sha1
188 189 /test-sigchain
5 Documentation/technical/api-revision-walking.txt
@@ -56,6 +56,11 @@ function.
56 56 returning a `struct commit *` each time you call it. The end of the
57 57 revision list is indicated by returning a NULL pointer.
58 58
  59 +`reset_revision_walk`::
  60 +
  61 + Reset the flags used by the revision walking api. You can use
  62 + this to do multiple sequencial revision walks.
  63 +
59 64 Data structures
60 65 ---------------
61 66
1  Makefile
@@ -479,6 +479,7 @@ TEST_PROGRAMS_NEED_X += test-match-trees
479 479 TEST_PROGRAMS_NEED_X += test-mktemp
480 480 TEST_PROGRAMS_NEED_X += test-parse-options
481 481 TEST_PROGRAMS_NEED_X += test-path-utils
  482 +TEST_PROGRAMS_NEED_X += test-revision-walking
482 483 TEST_PROGRAMS_NEED_X += test-run-command
483 484 TEST_PROGRAMS_NEED_X += test-sha1
484 485 TEST_PROGRAMS_NEED_X += test-sigchain
11 object.c
@@ -275,3 +275,14 @@ void object_array_remove_duplicates(struct object_array *array)
275 275 array->nr = dst;
276 276 }
277 277 }
  278 +
  279 +void clear_object_flags(unsigned flags)
  280 +{
  281 + int i;
  282 +
  283 + for (i=0; i < obj_hash_size; i++) {
  284 + struct object *obj = obj_hash[i];
  285 + if (obj)
  286 + obj->flags &= ~flags;
  287 + }
  288 +}
2  object.h
@@ -76,4 +76,6 @@ void add_object_array(struct object *obj, const char *name, struct object_array
76 76 void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode);
77 77 void object_array_remove_duplicates(struct object_array *);
78 78
  79 +void clear_object_flags(unsigned flags);
  80 +
79 81 #endif /* OBJECT_H */
5 revision.c
@@ -2061,6 +2061,11 @@ static void set_children(struct rev_info *revs)
2061 2061 }
2062 2062 }
2063 2063
  2064 +void reset_revision_walk(void)
  2065 +{
  2066 + clear_object_flags(SEEN | ADDED | SHOWN);
  2067 +}
  2068 +
2064 2069 int prepare_revision_walk(struct rev_info *revs)
2065 2070 {
2066 2071 int nr = revs->pending.nr;
1  revision.h
@@ -192,6 +192,7 @@ extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ct
192 192 const char * const usagestr[]);
193 193 extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename);
194 194
  195 +extern void reset_revision_walk(void);
195 196 extern int prepare_revision_walk(struct rev_info *revs);
196 197 extern struct commit *get_revision(struct rev_info *revs);
197 198 extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit);
2  submodule.c
@@ -404,6 +404,7 @@ int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remote
404 404 while ((commit = get_revision(&rev)) && !needs_pushing)
405 405 commit_need_pushing(commit, &needs_pushing);
406 406
  407 + reset_revision_walk();
407 408 free(sha1_copy);
408 409 strbuf_release(&remotes_arg);
409 410
@@ -741,6 +742,7 @@ static int find_first_merges(struct object_array *result, const char *path,
741 742 if (in_merge_bases(b, &commit, 1))
742 743 add_object_array(o, NULL, &merges);
743 744 }
  745 + reset_revision_walk();
744 746
745 747 /* Now we've got all merges that contain a and b. Prune all
746 748 * merges that contain another found merge and save them in
33 t/t0062-revision-walking.sh
... ... @@ -0,0 +1,33 @@
  1 +#!/bin/sh
  2 +#
  3 +# Copyright (c) 2012 Heiko Voigt
  4 +#
  5 +
  6 +test_description='Test revision walking api'
  7 +
  8 +. ./test-lib.sh
  9 +
  10 +cat >run_twice_expected <<-EOF
  11 +1st
  12 + > add b
  13 + > add a
  14 +2nd
  15 + > add b
  16 + > add a
  17 +EOF
  18 +
  19 +test_expect_success 'setup' '
  20 + echo a > a &&
  21 + git add a &&
  22 + git commit -m "add a" &&
  23 + echo b > b &&
  24 + git add b &&
  25 + git commit -m "add b"
  26 +'
  27 +
  28 +test_expect_success 'revision walking can be done twice' '
  29 + test-revision-walking run-twice > run_twice_actual
  30 + test_cmp run_twice_expected run_twice_actual
  31 +'
  32 +
  33 +test_done
66 test-revision-walking.c
... ... @@ -0,0 +1,66 @@
  1 +/*
  2 + * test-revision-walking.c: test revision walking API.
  3 + *
  4 + * (C) 2012 Heiko Voigt <hvoigt@hvoigt.net>
  5 + *
  6 + * This code is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#include "cache.h"
  12 +#include "commit.h"
  13 +#include "diff.h"
  14 +#include "revision.h"
  15 +
  16 +static void print_commit(struct commit *commit)
  17 +{
  18 + struct strbuf sb = STRBUF_INIT;
  19 + struct pretty_print_context ctx = {0};
  20 + ctx.date_mode = DATE_NORMAL;
  21 + format_commit_message(commit, " %m %s", &sb, &ctx);
  22 + printf("%s\n", sb.buf);
  23 + strbuf_release(&sb);
  24 +}
  25 +
  26 +static int run_revision_walk(void)
  27 +{
  28 + struct rev_info rev;
  29 + struct commit *commit;
  30 + const char *argv[] = {NULL, "--all", NULL};
  31 + int argc = ARRAY_SIZE(argv) - 1;
  32 + int got_revision = 0;
  33 +
  34 + init_revisions(&rev, NULL);
  35 + setup_revisions(argc, argv, &rev, NULL);
  36 + if (prepare_revision_walk(&rev))
  37 + die("revision walk setup failed");
  38 +
  39 + while ((commit = get_revision(&rev)) != NULL) {
  40 + print_commit(commit);
  41 + got_revision = 1;
  42 + }
  43 +
  44 + reset_revision_walk();
  45 + return got_revision;
  46 +}
  47 +
  48 +int main(int argc, char **argv)
  49 +{
  50 + if (argc < 2)
  51 + return 1;
  52 +
  53 + if (!strcmp(argv[1], "run-twice")) {
  54 + printf("1st\n");
  55 + if (!run_revision_walk())
  56 + return 1;
  57 + printf("2nd\n");
  58 + if (!run_revision_walk())
  59 + return 1;
  60 +
  61 + return 0;
  62 + }
  63 +
  64 + fprintf(stderr, "check usage\n");
  65 + return 1;
  66 +}

0 comments on commit bcc0a3e

Please sign in to comment.
Something went wrong with that request. Please try again.