Skip to content

Commit bcc0a3e

Browse files
hvoigtgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6f5e880 commit bcc0a3e

File tree

10 files changed

+127
-0
lines changed

10 files changed

+127
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
/test-mktemp
184184
/test-parse-options
185185
/test-path-utils
186+
/test-revision-walking
186187
/test-run-command
187188
/test-sha1
188189
/test-sigchain

Documentation/technical/api-revision-walking.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ function.
5656
returning a `struct commit *` each time you call it. The end of the
5757
revision list is indicated by returning a NULL pointer.
5858

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+
5964
Data structures
6065
---------------
6166

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ TEST_PROGRAMS_NEED_X += test-match-trees
479479
TEST_PROGRAMS_NEED_X += test-mktemp
480480
TEST_PROGRAMS_NEED_X += test-parse-options
481481
TEST_PROGRAMS_NEED_X += test-path-utils
482+
TEST_PROGRAMS_NEED_X += test-revision-walking
482483
TEST_PROGRAMS_NEED_X += test-run-command
483484
TEST_PROGRAMS_NEED_X += test-sha1
484485
TEST_PROGRAMS_NEED_X += test-sigchain

object.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,14 @@ void object_array_remove_duplicates(struct object_array *array)
275275
array->nr = dst;
276276
}
277277
}
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+
}

object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,6 @@ void add_object_array(struct object *obj, const char *name, struct object_array
7676
void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode);
7777
void object_array_remove_duplicates(struct object_array *);
7878

79+
void clear_object_flags(unsigned flags);
80+
7981
#endif /* OBJECT_H */

revision.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,11 @@ static void set_children(struct rev_info *revs)
20612061
}
20622062
}
20632063

2064+
void reset_revision_walk(void)
2065+
{
2066+
clear_object_flags(SEEN | ADDED | SHOWN);
2067+
}
2068+
20642069
int prepare_revision_walk(struct rev_info *revs)
20652070
{
20662071
int nr = revs->pending.nr;

revision.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ct
192192
const char * const usagestr[]);
193193
extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename);
194194

195+
extern void reset_revision_walk(void);
195196
extern int prepare_revision_walk(struct rev_info *revs);
196197
extern struct commit *get_revision(struct rev_info *revs);
197198
extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit);

submodule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remote
404404
while ((commit = get_revision(&rev)) && !needs_pushing)
405405
commit_need_pushing(commit, &needs_pushing);
406406

407+
reset_revision_walk();
407408
free(sha1_copy);
408409
strbuf_release(&remotes_arg);
409410

@@ -741,6 +742,7 @@ static int find_first_merges(struct object_array *result, const char *path,
741742
if (in_merge_bases(b, &commit, 1))
742743
add_object_array(o, NULL, &merges);
743744
}
745+
reset_revision_walk();
744746

745747
/* Now we've got all merges that contain a and b. Prune all
746748
* merges that contain another found merge and save them in

t/t0062-revision-walking.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test-revision-walking.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* test-revision-walking.c: test revision walking API.
3+
*
4+
* (C) 2012 Heiko Voigt <[email protected]>
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 commit comments

Comments
 (0)