diff --git a/collects/meta/tree/svn-tree.ss b/collects/meta/tree/svn-tree.ss new file mode 100644 index 0000000000..ccde6b9284 --- /dev/null +++ b/collects/meta/tree/svn-tree.ss @@ -0,0 +1,88 @@ +#lang scheme/base + +(provide get-svn-tree get-plt-svn-tree) + +(require "tree.ss" scheme/system scheme/match xml) + +(define svn-exe (find-executable-path "svn")) +(define (svn . args) + ;; runs an svn command, just returns its stdout to be used to its end + (define-values [p pout pin perr] + (apply subprocess #f #f (current-error-port) svn-exe args)) + (close-output-port pin) + pout) + +;; ---------------------------------------------------------------------------- +;; Reading a tree from a subversion url + +(define ((starts-with sym) x) + (and (pair? x) (eq? sym (car x)) x)) + +(define (get-svn-tree url) + (let* ([data (read-xml (svn "ls" "-R" "--xml" url))] + [data (xml->xexpr (document-element data))] + [data (ormap (starts-with 'list) (cddr data))] + [data (filter (starts-with 'entry) (cddr data))] + [data (map (lambda (x) + (match x + [(list _ `([kind ,kind]) _ ... `(name () ,name) _ ...) + (cons (string->symbol kind) + (regexp-split #rx#"/" + (string->bytes/utf-8 name)))])) + data)]) + ;; utilities + (define (listbytes/utf-8 url) #"/")]) + (let dloop ([items '()]) + (let ([tail (and (pair? data) (subtract-prefix (cdar data) pathlist))]) + (if tail + (let* ([kind (caar data)] + [pathlist (cdar data)] + [name (if (= 1 (length tail)) + (car tail) + (error 'get-svn-tree + "got an element without parent dir: ~e" + (cdar data)))] + [name (if (eq? 'dir kind) (bytes-append name #"/") name)] + [path (bytes-append path name)]) + (pop!) + (dloop (cons (case kind + [(dir) (loop name pathlist path)] + [(file) (make-tree name #f path)] + [else (error 'get-svn-tree + "got an element with ~a: ~e" + "an unexpected kind" + kind)]) + items))) + (make-tree name (reverse items) path))))))) + +;; ---------------------------------------------------------------------------- +;; Reading the PLT tree + +(define (get-plt-svn-tree) + (get-svn-tree "http://svn.plt-scheme.org/plt/trunk/")) + + +(tree-for-each (lambda (t) (printf "~a\n" (tree-path t))) + (time (get-svn-tree "file:///home/svn/plt/trunk/")))