summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2014-02-21 17:54:32 +0100
committerLudovic Courtès <ludo@gnu.org>2014-02-21 23:49:52 +0100
commit3140f2df423d1235c3766e3478a429ac89d882ed (patch)
treea250657c8c3682f5be9f40493d328f9c9ab83f20
parentc1d52c71aa4fc8085a9737ad1b235ca53a854649 (diff)
guix hash: Add '--recursive'.
* guix/scripts/hash.scm (show-help): Add --recursive. (%options): Likewise. (guix-hash)[file-hash]: New procedure. Honor --recursive. Use it. * guix/nar.scm (write-file): Add missing field to the &nar-error condition raised upon unsupported file type; change its message to be more descriptive. * tests/guix-hash.sh: Add tests with -r. * doc/guix.texi (Invoking guix hash): Document --recursive.
-rw-r--r--doc/guix.texi13
-rw-r--r--guix/nar.scm4
-rw-r--r--guix/scripts/hash.scm25
-rw-r--r--tests/guix-hash.sh22
4 files changed, 57 insertions, 7 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 34f6810f346..ce011959add 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -1958,6 +1958,19 @@ If the @option{--format} option is not specified, @command{guix hash}
1958will output the hash in @code{nix-base32}. This representation is used 1958will output the hash in @code{nix-base32}. This representation is used
1959in the definitions of packages. 1959in the definitions of packages.
1960 1960
1961@item --recursive
1962@itemx -r
1963Compute the hash on @var{file} recursively.
1964
1965In this case, the hash is computed on an archive containing @var{file},
1966including its children if it is a directory. Some of @var{file}'s
1967meta-data is part of the archive; for instance, when @var{file} is a
1968regular file, the hash is different depending on whether @var{file} is
1969executable or not. Meta-data such as time stamps has no impact on the
1970hash (@pxref{Invoking guix archive}).
1971@c FIXME: Replace xref above with xref to an ``Archive'' section when
1972@c it exists.
1973
1961@end table 1974@end table
1962 1975
1963@node Invoking guix refresh 1976@node Invoking guix refresh
diff --git a/guix/nar.scm b/guix/nar.scm
index 89a71302e0d..9ba6e4ce2c6 100644
--- a/guix/nar.scm
+++ b/guix/nar.scm
@@ -195,8 +195,8 @@ sub-directories of FILE as needed."
195 (write-string "target" p) 195 (write-string "target" p)
196 (write-string (readlink f) p)) 196 (write-string (readlink f) p))
197 (else 197 (else
198 (raise (condition (&message (message "ENOSYS")) 198 (raise (condition (&message (message "unsupported file type"))
199 (&nar-error))))) 199 (&nar-error (file f) (port port))))))
200 (write-string ")" p)))) 200 (write-string ")" p))))
201 201
202(define (restore-file port file) 202(define (restore-file port file)
diff --git a/guix/scripts/hash.scm b/guix/scripts/hash.scm
index 4e66aa0f3e4..ea8c2ada6b6 100644
--- a/guix/scripts/hash.scm
+++ b/guix/scripts/hash.scm
@@ -20,12 +20,14 @@
20(define-module (guix scripts hash) 20(define-module (guix scripts hash)
21 #:use-module (guix base32) 21 #:use-module (guix base32)
22 #:use-module (guix hash) 22 #:use-module (guix hash)
23 #:use-module (guix nar)
23 #:use-module (guix ui) 24 #:use-module (guix ui)
24 #:use-module (guix utils) 25 #:use-module (guix utils)
25 #:use-module (rnrs io ports) 26 #:use-module (rnrs io ports)
26 #:use-module (rnrs files) 27 #:use-module (rnrs files)
27 #:use-module (ice-9 match) 28 #:use-module (ice-9 match)
28 #:use-module (srfi srfi-1) 29 #:use-module (srfi srfi-1)
30 #:use-module (srfi srfi-11)
29 #:use-module (srfi srfi-26) 31 #:use-module (srfi srfi-26)
30 #:use-module (srfi srfi-37) 32 #:use-module (srfi srfi-37)
31 #:export (guix-hash)) 33 #:export (guix-hash))
@@ -43,10 +45,12 @@
43 (display (_ "Usage: guix hash [OPTION] FILE 45 (display (_ "Usage: guix hash [OPTION] FILE
44Return the cryptographic hash of FILE. 46Return the cryptographic hash of FILE.
45 47
46Supported formats: 'nix-base32' (default), 'base32', and 'base16' 48Supported formats: 'nix-base32' (default), 'base32', and 'base16' ('hex'
47('hex' and 'hexadecimal' can be used as well).\n")) 49and 'hexadecimal' can be used as well).\n"))
48 (format #t (_ " 50 (format #t (_ "
49 -f, --format=FMT write the hash in the given format")) 51 -f, --format=FMT write the hash in the given format"))
52 (format #t (_ "
53 -r, --recursive compute the hash on FILE recursively"))
50 (newline) 54 (newline)
51 (display (_ " 55 (display (_ "
52 -h, --help display this help and exit")) 56 -h, --help display this help and exit"))
@@ -73,6 +77,9 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16'
73 77
74 (alist-cons 'format fmt-proc 78 (alist-cons 'format fmt-proc
75 (alist-delete 'format result)))) 79 (alist-delete 'format result))))
80 (option '(#\r "recursive") #f #f
81 (lambda (opt name arg result)
82 (alist-cons 'recursive? #t result)))
76 83
77 (option '(#\h "help") #f #f 84 (option '(#\h "help") #f #f
78 (lambda args 85 (lambda args
@@ -107,12 +114,22 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16'
107 (reverse opts))) 114 (reverse opts)))
108 (fmt (assq-ref opts 'format))) 115 (fmt (assq-ref opts 'format)))
109 116
117 (define (file-hash file)
118 ;; Compute the hash of FILE.
119 ;; Catch and gracefully report possible '&nar-error' conditions.
120 (with-error-handling
121 (if (assoc-ref opts 'recursive?)
122 (let-values (((port get-hash) (open-sha256-port)))
123 (write-file file port)
124 (flush-output-port port)
125 (get-hash))
126 (call-with-input-file file port-sha256))))
127
110 (match args 128 (match args
111 ((file) 129 ((file)
112 (catch 'system-error 130 (catch 'system-error
113 (lambda () 131 (lambda ()
114 (format #t "~a~%" 132 (format #t "~a~%" (fmt (file-hash file))))
115 (fmt (call-with-input-file file port-sha256))))
116 (lambda args 133 (lambda args
117 (leave (_ "~a~%") 134 (leave (_ "~a~%")
118 (strerror (system-error-errno args)))))) 135 (strerror (system-error-errno args))))))
diff --git a/tests/guix-hash.sh b/tests/guix-hash.sh
index 53325ce1f45..23df01d417c 100644
--- a/tests/guix-hash.sh
+++ b/tests/guix-hash.sh
@@ -1,5 +1,5 @@
1# GNU Guix --- Functional package management for GNU 1# GNU Guix --- Functional package management for GNU
2# Copyright © 2013 Ludovic Courtès <ludo@gnu.org> 2# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
3# 3#
4# This file is part of GNU Guix. 4# This file is part of GNU Guix.
5# 5#
@@ -22,7 +22,27 @@
22 22
23guix hash --version 23guix hash --version
24 24
25tmpdir="guix-hash-$$"
26trap 'rm -rf "$tmpdir"' EXIT
27
25test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 28test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
26test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 29test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
27test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 30test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
28test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq 31test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq
32
33mkdir "$tmpdir"
34echo -n executable > "$tmpdir/exe"
35chmod +x "$tmpdir/exe"
36( cd "$tmpdir" ; ln -s exe symlink )
37mkdir "$tmpdir/subdir"
38
39test `guix hash -r "$tmpdir"` = 10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p
40
41# Without '-r', this should fail.
42if guix hash "$tmpdir"
43then false; else true; fi
44
45# This should fail because /dev/null is a character device, which
46# the archive format doesn't support.
47if guix hash -r /dev/null
48then false; else true; fi