Skip to content

Commit 27ac121

Browse files
committed
fix the "compute" phase for certain oldest-relevant commits
When the oldest relevant commit is not on every path from the initial commit to the head commit, then it's possible for a merge to retain commits that we don't want. Starting from the oldest relevant commit, find the newest older commit that is on every path. Also, fix adjusting the oldest-relevant commit to a selected main path, finding the closest older commit, instead of the closest newer commit.
1 parent c17ac76 commit 27ac121

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

compute.rkt

+37-6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
[(c) (in-list v)])
3232
(hash-update ht c (lambda (p) (cons k p)) null)))
3333

34+
;; One particular path that we sync forks to:
3435
(define main-line-commits
3536
(let loop ([a head-commit])
3637
(cons a
@@ -43,11 +44,37 @@
4344
(for/hash ([f (in-list main-line-commits)])
4445
(values f #t)))
4546

46-
(define (advance-to-main commit)
47+
;; To find a commit that is on all paths from head to the initial
48+
;; commit:
49+
(define (find-newest-older-cut p)
50+
(define (can-reach-root-without? without)
51+
(define seen (make-hash))
52+
(let loop ([p head-commit])
53+
(cond
54+
[(hash-ref seen p #f)
55+
#f]
56+
[else
57+
(hash-set! seen p #t)
58+
(define ps (hash-ref commit->parents p))
59+
(or (null? ps)
60+
(for/or ([p (in-list ps)])
61+
(and (not (equal? p without))
62+
(loop p))))])))
63+
(let loop ([p p])
64+
(if (can-reach-root-without? p)
65+
(loop (car (hash-ref commit->parents p)))
66+
p)))
67+
68+
(define (advance-to-main/newer commit)
4769
(if (hash-ref commit->main? commit #f)
4870
commit
49-
(advance-to-main (car (hash-ref commit->children commit)))))
50-
71+
(advance-to-main/newer (car (hash-ref commit->children commit)))))
72+
73+
(define (advance-to-main/older commit)
74+
(if (hash-ref commit->main? commit #f)
75+
commit
76+
(advance-to-main/older (car (hash-ref commit->parents commit)))))
77+
5178
(define files
5279
(for/list ([f (in-directory subdir)]
5380
#:when (file-exists? f))
@@ -86,7 +113,7 @@
86113
(when (and in-commit prev-name)
87114
(printf "~a : ~a...~a^\n" prev-name start-commit in-commit)
88115
(hash-set! lifetimes prev-name (cons start-commit in-commit))
89-
(find-lifetime! current-name (advance-to-main in-commit))
116+
(find-lifetime! current-name (advance-to-main/newer in-commit))
90117
(set! done? #t)))
91118
(void
92119
(filter-input
@@ -165,16 +192,20 @@
165192
(write (for/hash ([(k v) (in-hash commit->actions)])
166193
(values (string->bytes/utf-8 k) v)))))
167194

168-
(define oldest-relevant
195+
(define oldest-relevant-commit
169196
(let ([advanced-relevants
170197
(for/hash ([c (in-hash-keys relevants)])
171-
(values (advance-to-main c) #t))])
198+
(values (advance-to-main/older c) #t))])
172199
(let loop ([cs main-line-commits] [c head-commit])
173200
(cond
174201
[(null? cs) c]
175202
[(hash-ref advanced-relevants (car cs) #f)
176203
(loop (cdr cs) (car cs))]
177204
[else (loop (cdr cs) c)]))))
205+
(printf "Looking for cut older than ~a...\n" oldest-relevant-commit)
206+
(define oldest-relevant
207+
(find-newest-older-cut oldest-relevant-commit))
208+
178209
(printf "relevant commits bounded by ~a\n" oldest-relevant)
179210
(hash-set! relevants oldest-relevant #t)
180211

0 commit comments

Comments
 (0)