Skip to content

Commit ba3ca1e

Browse files
derrickstoleegitster
authored andcommitted
commit-reach: move can_all_from_reach_with_flags
There are several commit walks in the codebase. Group them together into a new commit-reach.c file and corresponding header. After we group these walks into one place, we can reduce duplicate logic by calling equivalent methods. The can_all_from_reach_with_flags method is used in a stateful way by upload-pack.c. The parameters are very flexible, so we will be able to use its commit walking logic for many other callers. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 118be57 commit ba3ca1e

File tree

4 files changed

+80
-71
lines changed

4 files changed

+80
-71
lines changed

commit-reach.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "commit-reach.h"
1111

1212
/* Remember to update object flag allocation in object.h */
13+
#define REACHABLE (1u<<15)
1314
#define PARENT1 (1u<<16)
1415
#define PARENT2 (1u<<17)
1516
#define STALE (1u<<18)
@@ -532,3 +533,65 @@ int commit_contains(struct ref_filter *filter, struct commit *commit,
532533
return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
533534
return is_descendant_of(commit, list);
534535
}
536+
537+
int reachable(struct commit *from, unsigned int with_flag,
538+
unsigned int assign_flag, time_t min_commit_date)
539+
{
540+
struct prio_queue work = { compare_commits_by_commit_date };
541+
542+
prio_queue_put(&work, from);
543+
while (work.nr) {
544+
struct commit_list *list;
545+
struct commit *commit = prio_queue_get(&work);
546+
547+
if (commit->object.flags & with_flag) {
548+
from->object.flags |= assign_flag;
549+
break;
550+
}
551+
if (!commit->object.parsed)
552+
parse_object(the_repository, &commit->object.oid);
553+
if (commit->object.flags & REACHABLE)
554+
continue;
555+
commit->object.flags |= REACHABLE;
556+
if (commit->date < min_commit_date)
557+
continue;
558+
for (list = commit->parents; list; list = list->next) {
559+
struct commit *parent = list->item;
560+
if (!(parent->object.flags & REACHABLE))
561+
prio_queue_put(&work, parent);
562+
}
563+
}
564+
from->object.flags |= REACHABLE;
565+
clear_commit_marks(from, REACHABLE);
566+
clear_prio_queue(&work);
567+
return (from->object.flags & assign_flag);
568+
}
569+
570+
int can_all_from_reach_with_flag(struct object_array *from,
571+
unsigned int with_flag,
572+
unsigned int assign_flag,
573+
time_t min_commit_date)
574+
{
575+
int i;
576+
577+
for (i = 0; i < from->nr; i++) {
578+
struct object *from_one = from->objects[i].item;
579+
580+
if (from_one->flags & assign_flag)
581+
continue;
582+
from_one = deref_tag(the_repository, from_one, "a from object", 0);
583+
if (!from_one || from_one->type != OBJ_COMMIT) {
584+
/* no way to tell if this is reachable by
585+
* looking at the ancestry chain alone, so
586+
* leave a note to ourselves not to worry about
587+
* this object anymore.
588+
*/
589+
from->objects[i].item->flags |= assign_flag;
590+
continue;
591+
}
592+
if (!reachable((struct commit *)from_one, with_flag, assign_flag,
593+
min_commit_date))
594+
return 0;
595+
}
596+
return 1;
597+
}

commit-reach.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,18 @@ define_commit_slab(contains_cache, enum contains_result);
5959
int commit_contains(struct ref_filter *filter, struct commit *commit,
6060
struct commit_list *list, struct contains_cache *cache);
6161

62+
int reachable(struct commit *from, unsigned int with_flag,
63+
unsigned int assign_flag, time_t min_commit_date);
64+
65+
/*
66+
* Determine if every commit in 'from' can reach at least one commit
67+
* that is marked with 'with_flag'. As we traverse, use 'assign_flag'
68+
* as a marker for commits that are already visited. Do not walk
69+
* commits with date below 'min_commit_date'.
70+
*/
71+
int can_all_from_reach_with_flag(struct object_array *from,
72+
unsigned int with_flag,
73+
unsigned int assign_flag,
74+
time_t min_commit_date);
75+
6276
#endif

object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ struct object_array {
6060
* revision.h: 0---------10 26
6161
* fetch-pack.c: 0----5
6262
* walker.c: 0-2
63-
* upload-pack.c: 4 11----------------19
63+
* upload-pack.c: 4 11-----14 16-----19
6464
* builtin/blame.c: 12-13
6565
* bisect.c: 16
6666
* bundle.c: 16
6767
* http-push.c: 16-----19
68-
* commit-reach.c: 16-----19
68+
* commit-reach.c: 15-------19
6969
* sha1-name.c: 20
7070
* list-objects-filter.c: 21
7171
* builtin/fsck.c: 0--3

upload-pack.c

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424
#include "quote.h"
2525
#include "upload-pack.h"
2626
#include "serve.h"
27+
#include "commit-reach.h"
2728

2829
/* Remember to update object flag allocation in object.h */
2930
#define THEY_HAVE (1u << 11)
3031
#define OUR_REF (1u << 12)
3132
#define WANTED (1u << 13)
3233
#define COMMON_KNOWN (1u << 14)
33-
#define REACHABLE (1u << 15)
3434

3535
#define SHALLOW (1u << 16)
3636
#define NOT_SHALLOW (1u << 17)
@@ -336,74 +336,6 @@ static int got_oid(const char *hex, struct object_id *oid)
336336
return 0;
337337
}
338338

339-
static int reachable(struct commit *from, unsigned int with_flag,
340-
unsigned int assign_flag, time_t min_commit_date)
341-
{
342-
struct prio_queue work = { compare_commits_by_commit_date };
343-
344-
prio_queue_put(&work, from);
345-
while (work.nr) {
346-
struct commit_list *list;
347-
struct commit *commit = prio_queue_get(&work);
348-
349-
if (commit->object.flags & with_flag) {
350-
from->object.flags |= assign_flag;
351-
break;
352-
}
353-
if (!commit->object.parsed)
354-
parse_object(the_repository, &commit->object.oid);
355-
if (commit->object.flags & REACHABLE)
356-
continue;
357-
commit->object.flags |= REACHABLE;
358-
if (commit->date < min_commit_date)
359-
continue;
360-
for (list = commit->parents; list; list = list->next) {
361-
struct commit *parent = list->item;
362-
if (!(parent->object.flags & REACHABLE))
363-
prio_queue_put(&work, parent);
364-
}
365-
}
366-
from->object.flags |= REACHABLE;
367-
clear_commit_marks(from, REACHABLE);
368-
clear_prio_queue(&work);
369-
return (from->object.flags & assign_flag);
370-
}
371-
372-
/*
373-
* Determine if every commit in 'from' can reach at least one commit
374-
* that is marked with 'with_flag'. As we traverse, use 'assign_flag'
375-
* as a marker for commits that are already visited. Do not walk
376-
* commits with date below 'min_commit_date'.
377-
*/
378-
static int can_all_from_reach_with_flag(struct object_array *from,
379-
unsigned int with_flag,
380-
unsigned int assign_flag,
381-
time_t min_commit_date)
382-
{
383-
int i;
384-
385-
for (i = 0; i < from->nr; i++) {
386-
struct object *from_one = from->objects[i].item;
387-
388-
if (from_one->flags & assign_flag)
389-
continue;
390-
from_one = deref_tag(the_repository, from_one, "a from object", 0);
391-
if (!from_one || from_one->type != OBJ_COMMIT) {
392-
/* no way to tell if this is reachable by
393-
* looking at the ancestry chain alone, so
394-
* leave a note to ourselves not to worry about
395-
* this object anymore.
396-
*/
397-
from->objects[i].item->flags |= assign_flag;
398-
continue;
399-
}
400-
if (!reachable((struct commit *)from_one, with_flag, assign_flag,
401-
min_commit_date))
402-
return 0;
403-
}
404-
return 1;
405-
}
406-
407339
static int ok_to_give_up(void)
408340
{
409341
if (!have_obj.nr)

0 commit comments

Comments
 (0)