aboutsummaryrefslogtreecommitdiff
path: root/guix
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2014-01-23 22:13:27 +0100
committerLudovic Courtès <ludo@gnu.org>2014-01-24 00:01:50 +0100
commit50add47748eb40371d8b88208a13e7230d15c220 (patch)
tree50d4813ddfdb39db532335bfcd8eba0b294bdff3 /guix
parentcd4027fa478e20b59e798dd163a54e7ff9c42c98 (diff)
downloadgnu-guix-50add47748eb40371d8b88208a13e7230d15c220.tar
gnu-guix-50add47748eb40371d8b88208a13e7230d15c220.tar.gz
store: Add 'topologically-sorted'.
* guix/store.scm (topologically-sorted): New procedure. * tests/store.scm ("topologically-sorted, one item", "topologically-sorted, several items", "topologically-sorted, more difficult"): New tests.
Diffstat (limited to 'guix')
-rw-r--r--guix/store.scm35
1 files changed, 35 insertions, 0 deletions
diff --git a/guix/store.scm b/guix/store.scm
index ede64341c5..eca0de7d97 100644
--- a/guix/store.scm
+++ b/guix/store.scm
@@ -76,6 +76,7 @@
references
requisites
referrers
+ topologically-sorted
valid-derivers
query-derivation-outputs
live-paths
@@ -589,6 +590,40 @@ SEED."
references, recursively)."
(fold-path store cons '() path))
+(define (topologically-sorted store paths)
+ "Return a list containing PATHS and all their references sorted in
+topological order."
+ (define (traverse)
+ ;; Do a simple depth-first traversal of all of PATHS.
+ (let loop ((paths paths)
+ (visited vlist-null)
+ (result '()))
+ (define (visit n)
+ (vhash-cons n #t visited))
+
+ (define (visited? n)
+ (vhash-assoc n visited))
+
+ (match paths
+ ((head tail ...)
+ (if (visited? head)
+ (loop tail visited result)
+ (call-with-values
+ (lambda ()
+ (loop (references store head)
+ (visit head)
+ result))
+ (lambda (visited result)
+ (loop tail
+ visited
+ (cons head result))))))
+ (()
+ (values visited result)))))
+
+ (call-with-values traverse
+ (lambda (_ result)
+ (reverse result))))
+
(define referrers
(operation (query-referrers (store-path path))
"Return the list of path that refer to PATH."