diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2014-02-21 17:54:32 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2014-02-21 23:49:52 +0100 |
| commit | 3140f2df423d1235c3766e3478a429ac89d882ed (patch) | |
| tree | a250657c8c3682f5be9f40493d328f9c9ab83f20 | |
| parent | c1d52c71aa4fc8085a9737ad1b235ca53a854649 (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.texi | 13 | ||||
| -rw-r--r-- | guix/nar.scm | 4 | ||||
| -rw-r--r-- | guix/scripts/hash.scm | 25 | ||||
| -rw-r--r-- | tests/guix-hash.sh | 22 |
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} | |||
| 1958 | will output the hash in @code{nix-base32}. This representation is used | 1958 | will output the hash in @code{nix-base32}. This representation is used |
| 1959 | in the definitions of packages. | 1959 | in the definitions of packages. |
| 1960 | 1960 | ||
| 1961 | @item --recursive | ||
| 1962 | @itemx -r | ||
| 1963 | Compute the hash on @var{file} recursively. | ||
| 1964 | |||
| 1965 | In this case, the hash is computed on an archive containing @var{file}, | ||
| 1966 | including its children if it is a directory. Some of @var{file}'s | ||
| 1967 | meta-data is part of the archive; for instance, when @var{file} is a | ||
| 1968 | regular file, the hash is different depending on whether @var{file} is | ||
| 1969 | executable or not. Meta-data such as time stamps has no impact on the | ||
| 1970 | hash (@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 |
| 44 | Return the cryptographic hash of FILE. | 46 | Return the cryptographic hash of FILE. |
| 45 | 47 | ||
| 46 | Supported formats: 'nix-base32' (default), 'base32', and 'base16' | 48 | Supported formats: 'nix-base32' (default), 'base32', and 'base16' ('hex' |
| 47 | ('hex' and 'hexadecimal' can be used as well).\n")) | 49 | and '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 | ||
| 23 | guix hash --version | 23 | guix hash --version |
| 24 | 24 | ||
| 25 | tmpdir="guix-hash-$$" | ||
| 26 | trap 'rm -rf "$tmpdir"' EXIT | ||
| 27 | |||
| 25 | test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 | 28 | test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 |
| 26 | test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 | 29 | test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 |
| 27 | test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | 30 | test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 |
| 28 | test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq | 31 | test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq |
| 32 | |||
| 33 | mkdir "$tmpdir" | ||
| 34 | echo -n executable > "$tmpdir/exe" | ||
| 35 | chmod +x "$tmpdir/exe" | ||
| 36 | ( cd "$tmpdir" ; ln -s exe symlink ) | ||
| 37 | mkdir "$tmpdir/subdir" | ||
| 38 | |||
| 39 | test `guix hash -r "$tmpdir"` = 10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p | ||
| 40 | |||
| 41 | # Without '-r', this should fail. | ||
| 42 | if guix hash "$tmpdir" | ||
| 43 | then false; else true; fi | ||
| 44 | |||
| 45 | # This should fail because /dev/null is a character device, which | ||
| 46 | # the archive format doesn't support. | ||
| 47 | if guix hash -r /dev/null | ||
| 48 | then false; else true; fi | ||
