union: Add 'relative-file-name'.
* guix/build/union.scm (%not-slash): New variable. (relative-file-name): New procedure. * tests/union.scm (test-relative-file-name): New macro and tests.
This commit is contained in:
parent
8584965b79
commit
dac1c97d13
|
@ -27,7 +27,9 @@
|
|||
#:use-module (rnrs io ports)
|
||||
#:export (union-build
|
||||
|
||||
warn-about-collision))
|
||||
warn-about-collision
|
||||
|
||||
relative-file-name))
|
||||
|
||||
;;; Commentary:
|
||||
;;;
|
||||
|
@ -174,4 +176,41 @@ returns #f, skip the faulty file altogether."
|
|||
|
||||
(union-of-directories output (delete-duplicates inputs)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Relative symlinks.
|
||||
;;;
|
||||
|
||||
(define %not-slash
|
||||
(char-set-complement (char-set #\/)))
|
||||
|
||||
(define (relative-file-name reference file)
|
||||
"Given REFERENCE and FILE, both of which are absolute file names, return the
|
||||
file name of FILE relative to REFERENCE.
|
||||
|
||||
(relative-file-name \"/gnu/store/foo\" \"/gnu/store/bin/bar\")
|
||||
=> \"../bin/bar\"
|
||||
|
||||
Note that this is from a purely lexical standpoint; conversely, \"..\" is
|
||||
*not* resolved lexically on POSIX in the presence of symlinks."
|
||||
(if (and (string-prefix? "/" file) (string-prefix? "/" reference))
|
||||
(let loop ((reference (string-tokenize reference %not-slash))
|
||||
(file (string-tokenize file %not-slash)))
|
||||
(define (finish)
|
||||
(string-join (append (make-list (length reference) "..") file)
|
||||
"/"))
|
||||
|
||||
(match reference
|
||||
(()
|
||||
(finish))
|
||||
((head . tail)
|
||||
(match file
|
||||
(()
|
||||
(finish))
|
||||
((head* . tail*)
|
||||
(if (string=? head head*)
|
||||
(loop tail tail*)
|
||||
(finish)))))))
|
||||
file))
|
||||
|
||||
;;; union.scm ends here
|
||||
|
|
|
@ -184,4 +184,22 @@
|
|||
(file-is-directory? "bin")
|
||||
(eq? 'symlink (stat:type (lstat "bin/guile"))))))))
|
||||
|
||||
(letrec-syntax ((test-relative-file-name
|
||||
(syntax-rules (=>)
|
||||
((_ (reference file => expected) rest ...)
|
||||
(begin
|
||||
(test-equal (string-append "relative-file-name "
|
||||
reference " " file)
|
||||
expected
|
||||
(relative-file-name reference file))
|
||||
(test-relative-file-name rest ...)))
|
||||
((_)
|
||||
#t))))
|
||||
(test-relative-file-name
|
||||
("/a/b" "/a/c/d" => "../c/d")
|
||||
("/a/b" "/a/b" => "")
|
||||
("/a/b" "/a" => "..")
|
||||
("/a/b" "/a/b/c/d" => "c/d")
|
||||
("/a/b/c" "/a/d/e/f" => "../../d/e/f")))
|
||||
|
||||
(test-end)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
|
||||
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
|
||||
;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||
;;;
|
||||
|
|
Loading…
Reference in New Issue