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.
This commit is contained in:
parent
c1d52c71aa
commit
3140f2df42
|
@ -1958,6 +1958,19 @@ If the @option{--format} option is not specified, @command{guix hash}
|
||||||
will output the hash in @code{nix-base32}. This representation is used
|
will output the hash in @code{nix-base32}. This representation is used
|
||||||
in the definitions of packages.
|
in the definitions of packages.
|
||||||
|
|
||||||
|
@item --recursive
|
||||||
|
@itemx -r
|
||||||
|
Compute the hash on @var{file} recursively.
|
||||||
|
|
||||||
|
In this case, the hash is computed on an archive containing @var{file},
|
||||||
|
including its children if it is a directory. Some of @var{file}'s
|
||||||
|
meta-data is part of the archive; for instance, when @var{file} is a
|
||||||
|
regular file, the hash is different depending on whether @var{file} is
|
||||||
|
executable or not. Meta-data such as time stamps has no impact on the
|
||||||
|
hash (@pxref{Invoking guix archive}).
|
||||||
|
@c FIXME: Replace xref above with xref to an ``Archive'' section when
|
||||||
|
@c it exists.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@node Invoking guix refresh
|
@node Invoking guix refresh
|
||||||
|
|
|
@ -195,8 +195,8 @@ sub-directories of FILE as needed."
|
||||||
(write-string "target" p)
|
(write-string "target" p)
|
||||||
(write-string (readlink f) p))
|
(write-string (readlink f) p))
|
||||||
(else
|
(else
|
||||||
(raise (condition (&message (message "ENOSYS"))
|
(raise (condition (&message (message "unsupported file type"))
|
||||||
(&nar-error)))))
|
(&nar-error (file f) (port port))))))
|
||||||
(write-string ")" p))))
|
(write-string ")" p))))
|
||||||
|
|
||||||
(define (restore-file port file)
|
(define (restore-file port file)
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
(define-module (guix scripts hash)
|
(define-module (guix scripts hash)
|
||||||
#:use-module (guix base32)
|
#:use-module (guix base32)
|
||||||
#:use-module (guix hash)
|
#:use-module (guix hash)
|
||||||
|
#:use-module (guix nar)
|
||||||
#:use-module (guix ui)
|
#:use-module (guix ui)
|
||||||
#:use-module (guix utils)
|
#:use-module (guix utils)
|
||||||
#:use-module (rnrs io ports)
|
#:use-module (rnrs io ports)
|
||||||
#:use-module (rnrs files)
|
#:use-module (rnrs files)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (srfi srfi-37)
|
#:use-module (srfi srfi-37)
|
||||||
#:export (guix-hash))
|
#:export (guix-hash))
|
||||||
|
@ -43,10 +45,12 @@
|
||||||
(display (_ "Usage: guix hash [OPTION] FILE
|
(display (_ "Usage: guix hash [OPTION] FILE
|
||||||
Return the cryptographic hash of FILE.
|
Return the cryptographic hash of FILE.
|
||||||
|
|
||||||
Supported formats: 'nix-base32' (default), 'base32', and 'base16'
|
Supported formats: 'nix-base32' (default), 'base32', and 'base16' ('hex'
|
||||||
('hex' and 'hexadecimal' can be used as well).\n"))
|
and 'hexadecimal' can be used as well).\n"))
|
||||||
(format #t (_ "
|
(format #t (_ "
|
||||||
-f, --format=FMT write the hash in the given format"))
|
-f, --format=FMT write the hash in the given format"))
|
||||||
|
(format #t (_ "
|
||||||
|
-r, --recursive compute the hash on FILE recursively"))
|
||||||
(newline)
|
(newline)
|
||||||
(display (_ "
|
(display (_ "
|
||||||
-h, --help display this help and exit"))
|
-h, --help display this help and exit"))
|
||||||
|
@ -73,6 +77,9 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16'
|
||||||
|
|
||||||
(alist-cons 'format fmt-proc
|
(alist-cons 'format fmt-proc
|
||||||
(alist-delete 'format result))))
|
(alist-delete 'format result))))
|
||||||
|
(option '(#\r "recursive") #f #f
|
||||||
|
(lambda (opt name arg result)
|
||||||
|
(alist-cons 'recursive? #t result)))
|
||||||
|
|
||||||
(option '(#\h "help") #f #f
|
(option '(#\h "help") #f #f
|
||||||
(lambda args
|
(lambda args
|
||||||
|
@ -107,12 +114,22 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16'
|
||||||
(reverse opts)))
|
(reverse opts)))
|
||||||
(fmt (assq-ref opts 'format)))
|
(fmt (assq-ref opts 'format)))
|
||||||
|
|
||||||
|
(define (file-hash file)
|
||||||
|
;; Compute the hash of FILE.
|
||||||
|
;; Catch and gracefully report possible '&nar-error' conditions.
|
||||||
|
(with-error-handling
|
||||||
|
(if (assoc-ref opts 'recursive?)
|
||||||
|
(let-values (((port get-hash) (open-sha256-port)))
|
||||||
|
(write-file file port)
|
||||||
|
(flush-output-port port)
|
||||||
|
(get-hash))
|
||||||
|
(call-with-input-file file port-sha256))))
|
||||||
|
|
||||||
(match args
|
(match args
|
||||||
((file)
|
((file)
|
||||||
(catch 'system-error
|
(catch 'system-error
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(format #t "~a~%"
|
(format #t "~a~%" (fmt (file-hash file))))
|
||||||
(fmt (call-with-input-file file port-sha256))))
|
|
||||||
(lambda args
|
(lambda args
|
||||||
(leave (_ "~a~%")
|
(leave (_ "~a~%")
|
||||||
(strerror (system-error-errno args))))))
|
(strerror (system-error-errno args))))))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# GNU Guix --- Functional package management for GNU
|
# GNU Guix --- Functional package management for GNU
|
||||||
# Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
|
# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
|
||||||
#
|
#
|
||||||
# This file is part of GNU Guix.
|
# This file is part of GNU Guix.
|
||||||
#
|
#
|
||||||
|
@ -22,7 +22,27 @@
|
||||||
|
|
||||||
guix hash --version
|
guix hash --version
|
||||||
|
|
||||||
|
tmpdir="guix-hash-$$"
|
||||||
|
trap 'rm -rf "$tmpdir"' EXIT
|
||||||
|
|
||||||
test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
||||||
test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
|
||||||
test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||||
test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq
|
test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq
|
||||||
|
|
||||||
|
mkdir "$tmpdir"
|
||||||
|
echo -n executable > "$tmpdir/exe"
|
||||||
|
chmod +x "$tmpdir/exe"
|
||||||
|
( cd "$tmpdir" ; ln -s exe symlink )
|
||||||
|
mkdir "$tmpdir/subdir"
|
||||||
|
|
||||||
|
test `guix hash -r "$tmpdir"` = 10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p
|
||||||
|
|
||||||
|
# Without '-r', this should fail.
|
||||||
|
if guix hash "$tmpdir"
|
||||||
|
then false; else true; fi
|
||||||
|
|
||||||
|
# This should fail because /dev/null is a character device, which
|
||||||
|
# the archive format doesn't support.
|
||||||
|
if guix hash -r /dev/null
|
||||||
|
then false; else true; fi
|
||||||
|
|
Loading…
Reference in New Issue