Merge branch 'master' into core-updates

This commit is contained in:
Leo Famulari 2016-10-29 21:44:39 -04:00
commit 062c7e43ed
No known key found for this signature in database
GPG key ID: 2646FA30BACA7F08
30 changed files with 2567 additions and 1314 deletions

View file

@ -4791,7 +4791,9 @@ The general syntax is:
guix hash @var{option} @var{file}
@end example
@command{guix hash} has the following options:
When @var{file} is @code{-} (a hyphen), @command{guix hash} computes the
hash of data read from standard input. @command{guix hash} has the
following options:
@table @code
@ -12240,6 +12242,58 @@ which may be insufficient for some operations.
The file name of the qcow2 image.
@end table
The default @command{run-vm.sh} script that is returned by an invokation of
@command{guix system vm} does not add a @command{-net user} flag by default.
To get network access from within the vm add the @code{(dhcp-client-service)}
to your system definition and start the VM using
@command{`guix system vm config.scm` -net user}. An important caveat of using
@command{-net user} for networking is that @command{ping} will not work, because
it uses the ICMP protocol. You'll have to use a different command to check for
network connectivity, like for example @command{curl}.
@subsubsection Connecting Through SSH
To enable SSH inside a VM you need to add a SSH server like @code{(dropbear-service)}
or @code{(lsh-service)} to your VM. The @code{(lsh-service}) doesn't currently
boot unsupervised. It requires you to type some characters to initialize the
randomness generator. In addition you need to forward the SSH port, 22 by
default, to the host. You can do this with
@example
`guix system vm config.scm` -net user,hostfwd=tcp::10022-:22
@end example
To connect to the VM you can run
@example
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 10022
@end example
The @command{-p} tells @command{ssh} the port you want to connect to.
@command{-o UserKnownHostsFile=/dev/null} prevents @command{ssh} from complaining
every time you modify your @command{config.scm} file and the
@command{-o StrictHostKeyChecking=no} prevents you from having to allow a
connection to an unknown host every time you connect.
@subsubsection Using @command{virt-viewer} with Spice
As an alternative to the default @command{qemu} graphical client you can
use the @command{remote-viewer} from the @command{virt-viewer} package. To
connect pass the @command{-spice port=5930,disable-ticketing} flag to
@command{qemu}. See previous section for further information on how to do this.
Spice also allows you to do some nice stuff like share your clipboard with your
VM. To enable that you'll also have to pass the following flags to @command{qemu}:
@example
-device virtio-serial-pci,id=virtio-serial0,max_ports=16,bus=pci.0,addr=0x5
-chardev spicevmc,name=vdagent,id=vdagent
-device virtserialport,nr=1,bus=virtio-serial0.0,chardev=vdagent,
name=com.redhat.spice.0
@end example
You'll also need to add the @pxref{Miscellaneous Services, Spice service}.
@node Defining Services
@subsection Defining Services

View file

@ -734,6 +734,7 @@ dist_patch_DATA = \
%D%/packages/patches/openjpeg-CVE-2016-5157.patch \
%D%/packages/patches/openjpeg-CVE-2016-7163.patch \
%D%/packages/patches/openjpeg-use-after-free-fix.patch \
%D%/packages/patches/openocd-nrf52.patch \
%D%/packages/patches/openssh-memory-exhaustion.patch \
%D%/packages/patches/openssl-runpath.patch \
%D%/packages/patches/openssl-1.1.0-c-rehash-in.patch \

View file

@ -406,13 +406,13 @@ (define-public libchop
(define-public borg
(package
(name "borg")
(version "1.0.7")
(version "1.0.8")
(source (origin
(method url-fetch)
(uri (pypi-uri "borgbackup" version))
(sha256
(base32
"1l9iw55w5x51yxl3q89cf6avg80lajxvc8qz584hrsmnk6i56cr0"))
"1fdfi0yzzdrrlml6780n4fh61sqm7pw6fcd1y67kfkvw8hy5c0k9"))
(modules '((guix build utils)))
(snippet
'(for-each

View file

@ -29,7 +29,7 @@ (define-module (gnu packages ccache)
(define-public ccache
(package
(name "ccache")
(version "3.3.2")
(version "3.3.3")
(source
(origin
(method url-fetch)
@ -37,7 +37,7 @@ (define-public ccache
version ".tar.xz"))
(sha256
(base32
"0c25l78hi36682l9cyxca78i8sdkmgmv9afip1s21y6q4g5qaxlh"))))
"1v04ky2mhvx8gnqfbs9x2vvf4i9mzph4fwdg72s9xyhwv92sf0iv"))))
(build-system gnu-build-system)
(native-inputs `(("perl" ,perl) ;for test.sh
("which" ,(@ (gnu packages base) which))))

View file

@ -320,14 +320,14 @@ (define-public cups
(define-public hplip
(package
(name "hplip")
(version "3.16.8")
(version "3.16.10")
(source (origin
(method url-fetch)
(uri (string-append "mirror://sourceforge/hplip/hplip/" version
"/hplip-" version ".tar.gz"))
(sha256
(base32
"1svcalf2nc7mvxndp9zz3xp43w66z45rrsr5syl8fx61a6p6gnm9"))))
"117f1p0splg51ljn4nn97c0mbl0jba440ahb3d8njq7p6h1lxd25"))))
(build-system gnu-build-system)
(home-page "http://hplipopensource.com/")
(synopsis "HP Printer Drivers")

View file

@ -5,6 +5,7 @@
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 John Darrington <jmd@gnu.org>
;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
;;; Copyright © 2016 Tobias Geerinckx-Rice <me@tobias.gr>
;;;
;;; This file is part of GNU Guix.
;;;
@ -23,6 +24,7 @@
(define-module (gnu packages dns)
#:use-module (gnu packages autotools)
#:use-module (gnu packages base)
#:use-module (gnu packages databases)
#:use-module (gnu packages groff)
#:use-module (gnu packages linux)
@ -161,3 +163,40 @@ (define-public libasr
license:bsd-3
(license:non-copyleft "file://LICENSE") ; includes.h
license:openssl))))
(define-public yadifa
(package
(name "yadifa")
(version "2.2.1-6281")
(source
(origin
(method url-fetch)
(uri (string-append "http://cdn.yadifa.eu/sites/default/files/releases/"
name "-" version ".tar.gz"))
(sha256
(base32
"0vj71z7i9lfbnp93k28aplwldp5mfli0kvrbwmha6fjha6kcr910"))))
(build-system gnu-build-system)
(native-inputs
`(("which" ,which)))
(inputs
`(("openssl" ,openssl)))
(arguments
`(#:phases (modify-phases %standard-phases
(add-before 'configure 'omit-example-configurations
(lambda _ (substitute* "Makefile.in"
((" (etc|var)") "")))))
#:configure-flags (list "--sysconfdir=/etc" "--localstatedir=/var"
"--enable-shared" "--disable-static"
"--enable-messages" "--enable-ctrl"
;; NSID is a rarely-used debugging aid, that also
;; causes the build to fail. Just disable it.
"--disable-nsid")))
(home-page "http://www.yadifa.eu/")
(synopsis "Authoritative DNS name server")
(description "YADIFA is an authorative name server for the Domain Name
System (DNS). It aims for both higher performance and a smaller memory
footprint than other implementations, while remaining fully RFC-compliant.
YADIFA supports dynamic record updates and the Domain Name System Security
Extensions (DNSSEC).")
(license license:bsd-3)))

View file

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2016 Theodoros Foradis <theodoros.for@openmailbox.org>
;;; Copyright © 2016 David Craven <david@craven.ch>
;;;
;;; This file is part of GNU Guix.
;;;
@ -28,10 +29,15 @@ (define-module (gnu packages embedded)
#:use-module (guix build-system trivial)
#:use-module (guix build utils)
#:use-module (gnu packages)
#:use-module (gnu packages autotools)
#:use-module (gnu packages cross-base)
#:use-module (gnu packages flex)
#:use-module (gnu packages gcc)
#:use-module (gnu packages gdb)
#:use-module (gnu packages libftdi)
#:use-module (gnu packages libusb)
#:use-module (gnu packages perl)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages texinfo))
;; We must not use the released GCC sources here, because the cross-compiler
@ -223,3 +229,136 @@ (define-public arm-none-eabi-toolchain-6
(define-public arm-none-eabi-nano-toolchain-6
(arm-none-eabi-toolchain gcc-arm-none-eabi-6
newlib-nano-arm-none-eabi))
(define-public gdb-arm-none-eabi
(package
(inherit gdb)
(name "gdb-arm-none-eabi")
(arguments
`(#:configure-flags '("--target=arm-none-eabi"
"--enable-multilib"
"--enable-interwork"
"--enable-languages=c,c++"
"--disable-nls")
,@(package-arguments gdb)))))
(define-public libjaylink
;; No release tarballs available.
(let ((commit "faa2a433fdd3de211728f3da5921133214af9dd3")
(revision "1"))
(package
(name "libjaylink")
(version (string-append "0.1.0-" revision "."
(string-take commit 7)))
(source (origin
(method git-fetch)
(uri (git-reference
(url "git://git.zapb.de/libjaylink.git")
(commit commit)))
(file-name (string-append name "-" version "-checkout"))
(sha256
(base32
"02crr56csz8whq3q4mrmdzzgwp5b0qvxm0fb18drclc3zj44yxl2"))))
(build-system gnu-build-system)
(native-inputs
`(("autoconf" ,autoconf)
("automake" ,automake)
("libtool" ,libtool)
("pkg-config" ,pkg-config)))
(inputs
`(("libusb" ,libusb)))
(arguments
`(#:phases
(modify-phases %standard-phases
(add-before 'configure 'autoreconf
(lambda _
(zero? (system* "autoreconf" "-vfi")))))))
(home-page "http://repo.or.cz/w/libjaylink.git")
(synopsis "Library to interface Segger J-Link devices")
(description "libjaylink is a shared library written in C to access
SEGGER J-Link and compatible devices.")
(license license:gpl2+))))
(define-public jimtcl
(package
(name "jimtcl")
(version "0.77")
(source (origin
(method url-fetch)
(uri (string-append
"https://github.com/msteveb/jimtcl"
"/archive/" version ".tar.gz"))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"1cmk3qscqckg70chjyimzxa2qcka4qac0j4wq908kiijp45cax08"))))
(build-system gnu-build-system)
(arguments
`(#:phases
(modify-phases %standard-phases
;; Doesn't use autoconf.
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(zero? (system* "./configure"
(string-append "--prefix=" out)))))))))
(home-page "http://jim.tcl.tk")
(synopsis "Small footprint Tcl implementation")
(description "Jim is a small footprint implementation of the Tcl programming
language.")
(license license:bsd-2)))
(define-public openocd
;; FIXME: Use tarball release after nrf52 patch is merged.
(let ((commit "674141e8a7a6413cb803d90c2a20150260015f81")
(revision "1"))
(package
(name "openocd")
(version (string-append "0.9.0-" revision "."
(string-take commit 7)))
(source (origin
(method git-fetch)
(uri (git-reference
(url "git://git.code.sf.net/p/openocd/code.git")
(commit commit)))
(sha256
(base32
"1i86jp0wawq78d73z8hp7q1pn7lmlvhjjr19f7299h4w40a5jf8j"))
(file-name (string-append name "-" version "-checkout"))
(patches
(search-patches "openocd-nrf52.patch"))))
(build-system gnu-build-system)
(native-inputs
`(("autoconf" ,autoconf)
("automake" ,automake)
("libtool" ,libtool)
("pkg-config" ,pkg-config)))
(inputs
`(("hidapi" ,hidapi)
("jimtcl" ,jimtcl)
("libftdi" ,libftdi)
("libjaylink" ,libjaylink)
("libusb-compat" ,libusb-compat)))
(arguments
'(#:configure-flags
(append (list "--disable-werror"
"--disable-internal-jimtcl"
"--disable-internal-libjaylink")
(map (lambda (programmer)
(string-append "--enable-" programmer))
'("amtjtagaccel" "armjtagew" "buspirate" "ftdi"
"gw16012" "jlink" "oocd_trace" "opendous" "osbdm"
"parport" "aice" "cmsis-dap" "dummy" "jtag_vpi"
"remote-bitbang" "rlink" "stlink" "ti-icdi" "ulink"
"usbprog" "vsllink" "usb-blaster-2" "usb_blaster"
"presto" "openjtag")))
#:phases
(modify-phases %standard-phases
(add-before 'configure 'autoreconf
(lambda _
(zero? (system* "autoreconf" "-vfi")))))))
(home-page "http://openocd.org")
(synopsis "On-Chip Debugger")
(description "OpenOCD provides on-chip programming and debugging support
with a layered architecture of JTAG interface and TAP support.")
(license license:gpl2))))

View file

@ -79,3 +79,22 @@ (define-public flex
executes the corresponding C code.")
(license (non-copyleft "file://COPYING"
"See COPYING in the distribution."))))
(define-public flex-2.6.1
;; The kservice and solid packages use flex. extra-cmake-modules
;; forces C89 for all C files for compatibility with windows.
;; Flex 2.6.0 generates a lexer containing a single line comment. Single
;; line comments are part of the C99 standard, so the lexer won't compile
;; if C89 is used.
(package
(inherit flex)
(version "2.6.1")
(source (origin
(method url-fetch)
(uri (string-append
"https://github.com/westes/flex"
"/releases/download/v" version "/"
"flex-" version ".tar.gz"))
(sha256
(base32
"0fy14c35yz2m1n1m4f02by3501fn0cca37zn7jp8lpp4b3kgjhrw"))))))

View file

@ -329,7 +329,7 @@ (define-public cmatrix
(define-public chess
(package
(name "chess")
(version "6.2.3")
(version "6.2.4")
(source
(origin
(method url-fetch)
@ -337,9 +337,9 @@ (define-public chess
".tar.gz"))
(sha256
(base32
"10hvnfhj9bkpz80x20jgxyqvgvrcgfdp8sfcbcrf1dgjn9v936bq"))))
"1vw2w3jwnmn44d5vsw47f8y70xvxcsz9m5msq9fgqlzjch15qhiw"))))
(build-system gnu-build-system)
(home-page "http://www.gnu.org/software/chess")
(home-page "https://www.gnu.org/software/chess")
(synopsis "Full chess implementation")
(description "GNU Chess is a chess engine. It allows you to compete
against the computer in a game of chess, either through the default terminal

View file

@ -410,7 +410,8 @@ (define-public icecat
("glib" ,glib)
("gstreamer" ,gstreamer)
("gst-plugins-base" ,gst-plugins-base)
("gtk+" ,gtk+-2)
("gtk+" ,gtk+)
("gtk+-2" ,gtk+-2)
("pango" ,pango)
("freetype" ,freetype)
("hunspell" ,hunspell)
@ -454,7 +455,7 @@ (define-public icecat
;; practice somehow. See <http://hydra.gnu.org/build/378133>.
#:validate-runpath? #f
#:configure-flags '("--enable-default-toolkit=cairo-gtk2"
#:configure-flags '("--enable-default-toolkit=cairo-gtk3"
"--enable-pango"
"--enable-gio"
"--enable-svg"

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@
;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Theodoros Foradis <theodoros.for@openmailbox.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -29,6 +30,7 @@ (define-module (gnu packages libusb)
#:use-module (guix build-system gnu)
#:use-module (guix build-system glib-or-gtk)
#:use-module (guix build-system python)
#:use-module (gnu packages autotools)
#:use-module (gnu packages gnupg)
#:use-module (gnu packages gtk)
#:use-module (gnu packages linux)
@ -201,3 +203,39 @@ (define-public gmtp
(MTP), which allows media files to be transferred to and from many portable
devices.")
(license bsd-3)))
(define-public hidapi
(package
(name "hidapi")
(version "0.8.0-rc1")
(source (origin
(method url-fetch)
(uri (string-append "https://github.com/signal11/hidapi/archive/hidapi-"
version ".tar.gz"))
(sha256
(base32
"0qdgyj9rgb7n0nk3ghfswrhzzknxqn4ibn3wj8g4r828pw07451w"))))
(build-system gnu-build-system)
(arguments
'(#:phases
(modify-phases %standard-phases
(add-before 'configure 'bootstrap
(lambda _
(zero? (system* "autoreconf" "-vfi")))))))
(inputs
`(("libusb" ,libusb)
("udev" ,eudev)))
(native-inputs
`(("autoconf" ,autoconf)
("automake" ,automake)
("libtool" ,libtool)
("pkg-config" ,pkg-config)))
(home-page "http://www.signal11.us/oss/hidapi/")
(synopsis "HID API library")
(description
"HIDAPI is a library which allows an application to interface with USB and Bluetooth
HID-Class devices.")
;; HIDAPI can be used under one of three licenses.
(license (list gpl3
bsd-3
non-copyleft "file://LICENSE-orig.txt"))))

View file

@ -71,6 +71,8 @@ (define-module (gnu packages linux)
#:use-module (gnu packages texinfo)
#:use-module (gnu packages tls)
#:use-module (gnu packages xml)
#:use-module (gnu packages xdisorg)
#:use-module (gnu packages xorg)
#:use-module (guix build-system cmake)
#:use-module (guix build-system gnu)
#:use-module (guix build-system python)
@ -323,14 +325,14 @@ (define* (make-linux-libre version hash supported-systems
(define %intel-compatible-systems '("x86_64-linux" "i686-linux"))
(define-public linux-libre
(make-linux-libre "4.8.4"
"06fb2b1y7w0ixq4savn3hddp326mmzmg3400dpr8lyg919bwck3x"
(make-linux-libre "4.8.5"
"124sf2jvckn0afy1zfyaqgr1679qsx3fnylw1wpl7p5298hwyf9m"
%intel-compatible-systems
#:configuration-file kernel-config))
(define-public linux-libre-4.4
(make-linux-libre "4.4.27"
"07g0y8zbspw8d65386llcsnqlbv2s24dxvvbwm9kwm87rk3vin1r"
(make-linux-libre "4.4.28"
"1yn74vci0bygn5bi9mcgx1zz8xw9m3jb6j260wqsgkv1hbksa2yp"
%intel-compatible-systems
#:configuration-file kernel-config))
@ -341,8 +343,8 @@ (define-public linux-libre-4.1
#:configuration-file kernel-config))
;; Avoid rebuilding kernel variants when there is a minor version bump.
(define %linux-libre-version "4.8.4")
(define %linux-libre-hash "06fb2b1y7w0ixq4savn3hddp326mmzmg3400dpr8lyg919bwck3x")
(define %linux-libre-version "4.8.5")
(define %linux-libre-hash "124sf2jvckn0afy1zfyaqgr1679qsx3fnylw1wpl7p5298hwyf9m")
(define-public linux-libre-arm-generic
(make-linux-libre %linux-libre-version
@ -3095,3 +3097,44 @@ (define-public libseccomp
developers.")
(home-page "https://github.com/seccomp/libseccomp")
(license license:lgpl2.1)))
(define-public radeontop
(package
(name "radeontop")
(version "0.9")
(home-page "https://github.com/clbr/radeontop/")
(source (origin
(method url-fetch)
(uri (string-append home-page "/archive/v" version ".tar.gz"))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"07fnimn6wwablmdjw0av11hk9a6xilbryh09izq4b2ic4b8md2p7"))))
(build-system gnu-build-system)
(arguments
`(#:phases (modify-phases %standard-phases
;; getver.sh uses git --describe, isn't worth an extra git
;; dependency, and doesn't even work on release(!) tarballs.
(add-after 'unpack 'report-correct-version
(lambda _ (substitute* "getver.sh"
(("ver=unknown")
(string-append "ver=" ,version)))))
(delete 'configure)) ; no configure script
#:make-flags (list "CC=gcc"
(string-append "PREFIX=" %output))
#:tests? #f)) ; no tests
(native-inputs
`(("gnu-gettext" ,gnu-gettext)
("pkg-config" ,pkg-config)))
(inputs
`(("libdrm" ,libdrm)
("libpciaccess" ,libpciaccess)
("ncurses" ,ncurses)))
(synopsis "Usage monitor for AMD Radeon graphics")
(description "RadeonTop monitors resource consumption on supported AMD
Radeon Graphics Processing Units (GPUs), either in real time as bar graphs on
a terminal or saved to a file for further processing. It measures both the
activity of the GPU as a whole, which is also accurate during OpenCL
computations, as well as separate component statistics that are only meaningful
under OpenGL graphics workloads.")
(license license:gpl3)))

View file

@ -311,7 +311,7 @@ (define-public bogofilter
(define-public offlineimap
(package
(name "offlineimap")
(version "7.0.8")
(version "7.0.9")
(source (origin
(method url-fetch)
(uri (string-append "https://github.com/OfflineIMAP/offlineimap/"
@ -319,7 +319,7 @@ (define-public offlineimap
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"0smxh5ag3cbn92kp49jq950j5m2pivs9kr04prpd1lw62hy7gnhr"))))
"04kapx0ddz7ccwhcjshkml2y916wcan3rl28mpmq25p4gywlkhxf"))))
(build-system python-build-system)
(native-inputs
`(("asciidoc" ,asciidoc)

View file

@ -1225,7 +1225,7 @@ (define-public slepc-complex-openmpi
(define-public mumps
(package
(name "mumps")
(version "5.0.1")
(version "5.0.2")
(source
(origin
(method url-fetch)
@ -1233,7 +1233,7 @@ (define-public mumps
version ".tar.gz"))
(sha256
(base32
"1820jfp3mbl7n85765v5mp6p0gzqpgr4d2lrnhwj4gl7cwp5ndah"))
"0igyc1pfzxdhpbad3v3lb86ixkdbqa1a8gbs15b04r2294h2nabp"))
(patches (search-patches "mumps-build-parallelism.patch"))))
(build-system gnu-build-system)
(inputs
@ -1250,8 +1250,7 @@ (define-public mumps
,@%gnu-build-system-modules)
#:phases
(modify-phases %standard-phases
(replace
'configure
(replace 'configure
(lambda* (#:key inputs #:allow-other-keys)
(call-with-output-file "Makefile.inc"
(lambda (port)
@ -1312,15 +1311,13 @@ (define-public mumps
`((,ptscotch
"-lptesmumps -lptscotch -lptscotcherr "
"-Dptscotch")))))))))
(replace
'build
(replace 'build
;; By default only the d-precision library is built. Make with "all"
;; target so that all precision libraries and examples are built.
(lambda _
(zero? (system* "make" "all"
(format #f "-j~a" (parallel-job-count))))))
(replace
'check
(replace 'check
;; Run the simple test drivers, which read test input from stdin:
;; from the "real" input for the single- and double-precision
;; testers, and from the "cmplx" input for complex-precision
@ -1343,15 +1340,15 @@ (define-public mumps
(zero? (close-pipe tester)))))
'("s" "d" "c" "z")
'("real" "real" "cmplx" "cmplx")))))
(replace
'install
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(copy-recursively "lib" (string-append out "/lib"))
(copy-recursively "include" (string-append out "/include"))
(when (file-exists? "libseq/libmpiseq.a")
(copy-file "libseq/libmpiseq.a"
(string-append out "/lib/libmpiseq.a")))))))))
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(libdir (string-append out "/lib")))
(copy-recursively "lib" libdir)
(copy-recursively "include" (string-append out "/include"))
(when (file-exists? "libseq/libmpiseq.a")
(install-file "libseq/libmpiseq.a" libdir))
#t))))))
(home-page "http://mumps.enseeiht.fr")
(synopsis "Multifrontal sparse direct solver")
(description

View file

@ -1772,9 +1772,9 @@ (define-public python-musicbrainzngs
(define-public python2-musicbrainzngs
(package-with-python2 python-musicbrainzngs))
(define-public python-pyechonest
(define-public python2-pyechonest
(package
(name "python-pyechonest")
(name "python2-pyechonest")
(version "9.0.0")
(source (origin
(method url-fetch)
@ -1783,6 +1783,11 @@ (define-public python-pyechonest
(base32
"1584nira3rkiman9dm81kdshihmkj21s8navndz2l8spnjwb790x"))))
(build-system python-build-system)
(arguments
`(;; Python 3 is not supported:
;; https://github.com/echonest/pyechonest/issues/42
#:python ,python-2))
(native-inputs `(("python2-setuptools" ,python2-setuptools)))
(home-page "https://github.com/echonest/pyechonest")
(synopsis "Python interface to The Echo Nest APIs")
(description "Pyechonest is a Python library for the Echo Nest API. With
@ -1799,13 +1804,7 @@ (define-public python-pyechonest
about the track including key, duration, mode, tempo, time signature along with
detailed track info including timbre, pitch, rhythm and loudness information.
@end enumerate\n")
(license license:bsd-3)
(properties `((python2-variant . ,(delay python2-pyechonest))))))
(define-public python2-pyechonest
(package (inherit (package-with-python2
(strip-python2-variant python-pyechonest)))
(native-inputs `(("python2-setuptools" ,python2-setuptools)))))
(license license:bsd-3)))
(define-public python-pylast
(package

View file

@ -0,0 +1,843 @@
This patch adds support for nRF52 series devices. It is patchset 7 from
<http://openocd.zylin.com/#/c/3511/>, which has been tested, but not
merged yet in master.
From: Michael Dietz <mjdietzx@gmail.com>
Date: Mon, 30 May 2016 12:50:44 +0000 (-0700)
Subject: Added support for nRF52 Series Devices.
X-Git-Url: http://openocd.zylin.com/gitweb?p=openocd.git;a=commitdiff_plain;h=9ba15633e221d9d72e320372ba8f49d3f30d4bce
Added support for nRF52 Series Devices.
Both nrf52.c and nrf52.cfg are based off of previous nRF51 files.
- Some possible race conditions with NVMC have been fixed in nRF52.c
- Removed nrf51_get_probed_chip_if_halted() as the core does not have to be halted to perform operations where it is called.
- Only registers that are needed by openOCD are defined, some registers in nRF51 don't exist in nRF52 and are removed.
- Some all around cleanup has been done.
- The protection mechanism is completely different on nRF52 and this has not been implemented yet - just prints a warning and returns for now.
Change-Id: I4dd42c86f33f450709bb981806c2655f04aa6201
Signed-off-by: Michael Dietz <mjdietzx@gmail.com>
---
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index c167e8f..b6a2be3 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -37,6 +37,7 @@ NOR_DRIVERS = \
niietcm4.c \
non_cfi.c \
nrf51.c \
+ nrf52.c \
numicro.c \
ocl.c \
pic32mx.c \
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 56a5cb2..3e071bd 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -48,6 +48,7 @@ extern struct flash_driver mdr_flash;
extern struct flash_driver mrvlqspi_flash;
extern struct flash_driver niietcm4_flash;
extern struct flash_driver nrf51_flash;
+extern struct flash_driver nrf52_flash;
extern struct flash_driver numicro_flash;
extern struct flash_driver ocl_flash;
extern struct flash_driver pic32mx_flash;
@@ -100,6 +101,7 @@ static struct flash_driver *flash_drivers[] = {
&mrvlqspi_flash,
&niietcm4_flash,
&nrf51_flash,
+ &nrf52_flash,
&numicro_flash,
&ocl_flash,
&pic32mx_flash,
diff --git a/src/flash/nor/nrf52.c b/src/flash/nor/nrf52.c
new file mode 100644
index 0000000..7f2bd35
--- /dev/null
+++ b/src/flash/nor/nrf52.c
@@ -0,0 +1,733 @@
+/***************************************************************************
+ * Copyright (C) 2013 Synapse Product Development *
+ * Andrey Smirnov <andrew.smironv@gmail.com> *
+ * Angus Gratton <gus@projectgus.com> *
+ * Erdem U. Altunyurt <spamjunkeater@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include "imp.h"
+#include <target/algorithm.h>
+#include <target/armv7m.h>
+#include <helper/types.h>
+
+/* nRF52 Register addresses used by openOCD. */
+#define NRF52_FLASH_BASE_ADDR (0x0)
+
+#define NRF52_FICR_BASE_ADDR (0x10000000)
+#define NRF52_FICR_CODEPAGESIZE_ADDR (NRF52_FICR_BASE_ADDR | 0x010)
+#define NRF52_FICR_CODESIZE_ADDR (NRF52_FICR_BASE_ADDR | 0x014)
+
+#define NRF52_UICR_BASE_ADDR (0x10001000)
+
+#define NRF52_NVMC_BASE_ADDR (0x4001E000)
+#define NRF52_NVMC_READY_ADDR (NRF52_NVMC_BASE_ADDR | 0x400)
+#define NRF52_NVMC_CONFIG_ADDR (NRF52_NVMC_BASE_ADDR | 0x504)
+#define NRF52_NVMC_ERASEPAGE_ADDR (NRF52_NVMC_BASE_ADDR | 0x508)
+#define NRF52_NVMC_ERASEALL_ADDR (NRF52_NVMC_BASE_ADDR | 0x50C)
+#define NRF52_NVMC_ERASEUICR_ADDR (NRF52_NVMC_BASE_ADDR | 0x514)
+
+/* nRF52 bit fields. */
+enum nrf52_nvmc_config_bits {
+ NRF52_NVMC_CONFIG_REN = 0x0,
+ NRF52_NVMC_CONFIG_WEN = 0x01,
+ NRF52_NVMC_CONFIG_EEN = 0x02
+};
+
+enum nrf52_nvmc_ready_bits {
+ NRF52_NVMC_BUSY = 0x0,
+ NRF52_NVMC_READY = 0x01
+};
+
+/* nRF52 state information. */
+struct nrf52_info {
+ uint32_t code_page_size; /* Size of FLASH page in bytes. */
+ uint32_t code_memory_size; /* Size of Code FLASH region in bytes. */
+
+ struct {
+ bool probed;
+ int (*write) (struct flash_bank *bank,
+ struct nrf52_info *chip,
+ const uint8_t *buffer, uint32_t offset, uint32_t count);
+ } bank[2]; /* There are two regions in nRF52 FLASH - Code and UICR. */
+ struct target *target;
+};
+
+static int nrf52_protect_check(struct flash_bank *bank);
+
+static int nrf52_probe(struct flash_bank *bank)
+{
+ int res;
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ res = target_read_u32(chip->target,
+ NRF52_FICR_CODEPAGESIZE_ADDR,
+ &chip->code_page_size);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Couldn't read code page size");
+ return res;
+ }
+
+ res = target_read_u32(chip->target,
+ NRF52_FICR_CODESIZE_ADDR,
+ &chip->code_memory_size);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Couldn't read code memory size");
+ return res;
+ }
+
+ chip->code_memory_size = chip->code_memory_size * chip->code_page_size;
+
+ if (bank->base == NRF52_FLASH_BASE_ADDR) {
+ bank->size = chip->code_memory_size;
+ bank->num_sectors = bank->size / chip->code_page_size;
+ bank->sectors = calloc(bank->num_sectors,
+ sizeof((bank->sectors)[0]));
+ if (!bank->sectors)
+ return ERROR_FLASH_BANK_NOT_PROBED;
+
+ /* Fill out the sector information: All nRF51 sectors are the same size. */
+ for (int i = 0; i < bank->num_sectors; i++) {
+ bank->sectors[i].size = chip->code_page_size;
+ bank->sectors[i].offset = i * chip->code_page_size;
+
+ /* Mark as unknown. */
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = -1;
+ }
+
+ nrf52_protect_check(bank);
+
+ chip->bank[0].probed = true;
+ } else { /* This is the UICR bank. */
+ bank->size = chip->code_page_size;
+ bank->num_sectors = 1;
+ bank->sectors = calloc(bank->num_sectors,
+ sizeof((bank->sectors)[0]));
+ if (!bank->sectors)
+ return ERROR_FLASH_BANK_NOT_PROBED;
+
+ bank->sectors[0].size = bank->size;
+ bank->sectors[0].offset = 0;
+
+ bank->sectors[0].is_erased = -1;
+ bank->sectors[0].is_protected = -1;
+
+ chip->bank[1].probed = true;
+ }
+
+ return ERROR_OK;
+}
+
+static int nrf52_bank_is_probed(struct flash_bank *bank)
+{
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ return chip->bank[bank->bank_number].probed;
+}
+
+static int nrf52_auto_probe(struct flash_bank *bank)
+{
+ if (!nrf52_bank_is_probed(bank))
+ return nrf52_probe(bank);
+ else
+ return ERROR_OK;
+}
+
+static int nrf52_wait_for_nvmc(struct nrf52_info *chip)
+{
+ int res;
+ uint32_t ready;
+ int timeout = 100;
+
+ do {
+ res = target_read_u32(chip->target, NRF52_NVMC_READY_ADDR, &ready);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Couldn't read NVMC_READY register");
+ return res;
+ }
+
+ if (ready == NRF52_NVMC_READY)
+ return ERROR_OK;
+
+ alive_sleep(1);
+ } while (timeout--);
+
+ LOG_DEBUG("Timed out waiting for the NVMC to be ready");
+ return ERROR_FLASH_BUSY;
+}
+
+static int nrf52_nvmc_erase_enable(struct nrf52_info *chip)
+{
+ int res;
+
+ res = nrf52_wait_for_nvmc(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = target_write_u32(chip->target,
+ NRF52_NVMC_CONFIG_ADDR,
+ NRF52_NVMC_CONFIG_EEN);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to configure the NVMC for erasing");
+ return res;
+ }
+
+ return res;
+}
+
+static int nrf52_nvmc_write_enable(struct nrf52_info *chip)
+{
+ int res;
+
+ res = nrf52_wait_for_nvmc(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = target_write_u32(chip->target,
+ NRF52_NVMC_CONFIG_ADDR,
+ NRF52_NVMC_CONFIG_WEN);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to configure the NVMC for writing");
+ return res;
+ }
+
+ return res;
+}
+
+static int nrf52_nvmc_read_only(struct nrf52_info *chip)
+{
+ int res;
+
+ res = nrf52_wait_for_nvmc(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = target_write_u32(chip->target,
+ NRF52_NVMC_CONFIG_ADDR,
+ NRF52_NVMC_CONFIG_REN);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to configure the NVMC for read-only");
+ return res;
+ }
+
+ return res;
+}
+
+static int nrf52_nvmc_generic_erase(struct nrf52_info *chip,
+ uint32_t erase_register,
+ uint32_t erase_value)
+{
+ int res;
+
+ res = nrf52_nvmc_erase_enable(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = target_write_u32(chip->target,
+ erase_register,
+ erase_value);
+ if (res != ERROR_OK)
+ LOG_ERROR("Failed to write NVMC erase register");
+
+ return nrf52_nvmc_read_only(chip);
+}
+
+static int nrf52_protect_check(struct flash_bank *bank)
+{
+ LOG_WARNING("nrf52_protect_check() is not implemented for nRF52 series devices yet");
+ return ERROR_OK;
+}
+
+static int nrf52_protect(struct flash_bank *bank, int set, int first, int last)
+{
+ LOG_WARNING("nrf52_protect() is not implemented for nRF52 series devices yet");
+ return ERROR_OK;
+}
+
+static struct flash_sector *nrf52_find_sector_by_address(struct flash_bank *bank, uint32_t address)
+{
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ for (int i = 0; i < bank->num_sectors; i++)
+ if (bank->sectors[i].offset <= address &&
+ address < (bank->sectors[i].offset + chip->code_page_size)) {
+ return &bank->sectors[i];
+ }
+
+ return NULL;
+}
+
+static int nrf52_erase_all(struct nrf52_info *chip)
+{
+ LOG_DEBUG("Erasing all non-volatile memory");
+ return nrf52_nvmc_generic_erase(chip,
+ NRF52_NVMC_ERASEALL_ADDR,
+ 0x01);
+}
+
+static int nrf52_erase_page(struct flash_bank *bank,
+ struct nrf52_info *chip,
+ struct flash_sector *sector)
+{
+ int res;
+
+ LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
+ if (sector->is_protected == 1) {
+ LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, sector->offset);
+ return ERROR_FAIL;
+ }
+
+ if (bank->base == NRF52_UICR_BASE_ADDR) {
+ res = nrf52_nvmc_generic_erase(chip,
+ NRF52_NVMC_ERASEUICR_ADDR,
+ 0x00000001);
+ } else {
+ res = nrf52_nvmc_generic_erase(chip,
+ NRF52_NVMC_ERASEPAGE_ADDR,
+ sector->offset);
+ }
+
+ if (res == ERROR_OK)
+ sector->is_erased = 1;
+ return res;
+}
+
+static const uint8_t nrf52_flash_write_code[] = {
+ /* See contrib/loaders/flash/cortex-m0.S */
+ /* <wait_fifo>: */
+ 0x0d, 0x68, /* ldr r5, [r1, #0] */
+ 0x00, 0x2d, /* cmp r5, #0 */
+ 0x0b, 0xd0, /* beq.n 1e <exit> */
+ 0x4c, 0x68, /* ldr r4, [r1, #4] */
+ 0xac, 0x42, /* cmp r4, r5 */
+ 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
+ 0x20, 0xcc, /* ldmia r4!, {r5} */
+ 0x20, 0xc3, /* stmia r3!, {r5} */
+ 0x94, 0x42, /* cmp r4, r2 */
+ 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
+ 0x0c, 0x46, /* mov r4, r1 */
+ 0x08, 0x34, /* adds r4, #8 */
+ /* <no_wrap>: */
+ 0x4c, 0x60, /* str r4, [r1, #4] */
+ 0x04, 0x38, /* subs r0, #4 */
+ 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
+ /* <exit>: */
+ 0x00, 0xbe /* bkpt 0x0000 */
+};
+
+
+/* Start a low level flash write for the specified region */
+static int nrf52_ll_flash_write(struct nrf52_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes)
+{
+ struct target *target = chip->target;
+ uint32_t buffer_size = 8192;
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ uint32_t address = NRF52_FLASH_BASE_ADDR + offset;
+ struct reg_param reg_params[4];
+ struct armv7m_algorithm armv7m_info;
+ int retval = ERROR_OK;
+
+ LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes);
+ assert(bytes % 4 == 0);
+
+ /* allocate working area with flash programming code */
+ if (target_alloc_working_area(target, sizeof(nrf52_flash_write_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, falling back to slow memory writes");
+
+ for (; bytes > 0; bytes -= 4) {
+ retval = target_write_memory(chip->target,
+ offset, 4, 1, buffer);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = nrf52_wait_for_nvmc(chip);
+ if (retval != ERROR_OK)
+ return retval;
+
+ offset += 4;
+ buffer += 4;
+ }
+
+ return ERROR_OK;
+ }
+
+ LOG_WARNING("using fast async flash loader. This is currently supported");
+ LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add");
+ LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf52.cfg to disable it");
+
+ retval = target_write_buffer(target, write_algorithm->address,
+ sizeof(nrf52_flash_write_code),
+ nrf52_flash_write_code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* memory buffer */
+ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
+ buffer_size /= 2;
+ buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
+ if (buffer_size <= 256) {
+ /* free working area, write algorithm already allocated */
+ target_free_working_area(target, write_algorithm);
+
+ LOG_WARNING("No large enough working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ }
+
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* byte count */
+ init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* buffer start */
+ init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer end */
+ init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT); /* target address */
+
+ buf_set_u32(reg_params[0].value, 0, 32, bytes);
+ buf_set_u32(reg_params[1].value, 0, 32, source->address);
+ buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
+ buf_set_u32(reg_params[3].value, 0, 32, address);
+
+ retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
+ 0, NULL,
+ 4, reg_params,
+ source->address, source->size,
+ write_algorithm->address, 0,
+ &armv7m_info);
+
+ target_free_working_area(target, source);
+ target_free_working_area(target, write_algorithm);
+
+ destroy_reg_param(&reg_params[0]);
+ destroy_reg_param(&reg_params[1]);
+ destroy_reg_param(&reg_params[2]);
+ destroy_reg_param(&reg_params[3]);
+
+ return retval;
+}
+
+/* Check and erase flash sectors in specified range, then start a low level page write.
+ start/end must be sector aligned.
+*/
+static int nrf52_write_pages(struct flash_bank *bank, uint32_t start, uint32_t end, const uint8_t *buffer)
+{
+ int res;
+ uint32_t offset;
+ struct flash_sector *sector;
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ assert(start % chip->code_page_size == 0);
+ assert(end % chip->code_page_size == 0);
+
+ /* Erase all sectors */
+ for (offset = start; offset < end; offset += chip->code_page_size) {
+ sector = nrf52_find_sector_by_address(bank, offset);
+
+ if (sector == NULL) {
+ LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset);
+ return ERROR_FLASH_SECTOR_INVALID;
+ }
+
+ if (sector->is_protected == 1) {
+ LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset);
+ return ERROR_FAIL;
+ }
+
+ if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */
+ res = nrf52_erase_page(bank, chip, sector);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset);
+ return res;
+ }
+ }
+ sector->is_erased = 1;
+ }
+
+ res = nrf52_nvmc_write_enable(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = nrf52_ll_flash_write(chip, start, buffer, (end - start));
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH");
+ nrf52_nvmc_read_only(chip);
+ return res;
+ }
+
+ return nrf52_nvmc_read_only(chip);
+}
+
+static int nrf52_erase(struct flash_bank *bank, int first, int last)
+{
+ int res = ERROR_OK;
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ /* For each sector to be erased */
+ for (int s = first; s <= last && res == ERROR_OK; s++)
+ res = nrf52_erase_page(bank, chip, &bank->sectors[s]);
+
+ return res;
+}
+
+static int nrf52_code_flash_write(struct flash_bank *bank,
+ struct nrf52_info *chip,
+ const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ int res;
+ /* Need to perform reads to fill any gaps we need to preserve in the first page,
+ before the start of buffer, or in the last page, after the end of buffer */
+ uint32_t first_page = offset / chip->code_page_size;
+ uint32_t last_page = DIV_ROUND_UP(offset+count, chip->code_page_size);
+
+ uint32_t first_page_offset = first_page * chip->code_page_size;
+ uint32_t last_page_offset = last_page * chip->code_page_size;
+
+ LOG_DEBUG("Padding write from 0x%08"PRIx32"-0x%08"PRIx32" as 0x%08"PRIx32"-0x%08"PRIx32,
+ offset, offset+count, first_page_offset, last_page_offset);
+
+ uint32_t page_cnt = last_page - first_page;
+ uint8_t buffer_to_flash[page_cnt * chip->code_page_size];
+
+ /* Fill in any space between start of first page and start of buffer */
+ uint32_t pre = offset - first_page_offset;
+ if (pre > 0) {
+ res = target_read_memory(bank->target, first_page_offset, 1, pre, buffer_to_flash);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ /* Fill in main contents of buffer */
+ memcpy(buffer_to_flash + pre, buffer, count);
+
+ /* Fill in any space between end of buffer and end of last page */
+ uint32_t post = last_page_offset - (offset + count);
+ if (post > 0) {
+ /* Retrieve the full row contents from Flash */
+ res = target_read_memory(bank->target, offset + count, 1, post, buffer_to_flash + pre + count);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ return nrf52_write_pages(bank, first_page_offset, last_page_offset, buffer_to_flash);
+}
+
+static int nrf52_uicr_flash_write(struct flash_bank *bank,
+ struct nrf52_info *chip,
+ const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ int res;
+ uint32_t nrf52_uicr_size = chip->code_page_size;
+ uint8_t uicr[nrf52_uicr_size];
+ struct flash_sector *sector = &bank->sectors[0];
+
+ if ((offset + count) > nrf52_uicr_size)
+ return ERROR_FAIL;
+
+ res = target_read_memory(bank->target, NRF52_UICR_BASE_ADDR, 1, nrf52_uicr_size, uicr);
+
+ if (res != ERROR_OK)
+ return res;
+
+ if (sector->is_erased != 1) {
+ res = nrf52_erase_page(bank, chip, sector);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ memcpy(&uicr[offset], buffer, count);
+
+ res = nrf52_nvmc_write_enable(chip);
+ if (res != ERROR_OK)
+ return res;
+
+ res = nrf52_ll_flash_write(chip, NRF52_UICR_BASE_ADDR, uicr, nrf52_uicr_size);
+ if (res != ERROR_OK) {
+ nrf52_nvmc_read_only(chip);
+ return res;
+ }
+
+ return nrf52_nvmc_read_only(chip);
+}
+
+
+static int nrf52_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count);
+}
+
+
+FLASH_BANK_COMMAND_HANDLER(nrf52_flash_bank_command)
+{
+ static struct nrf52_info *chip;
+
+ assert(bank != NULL);
+
+ switch (bank->base) {
+ case NRF52_FLASH_BASE_ADDR:
+ bank->bank_number = 0;
+ break;
+ case NRF52_UICR_BASE_ADDR:
+ bank->bank_number = 1;
+ break;
+ default:
+ LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base);
+ return ERROR_FAIL;
+ }
+
+ if (!chip) {
+ /* Create a new chip */
+ chip = calloc(1, sizeof(*chip));
+ assert(chip != NULL);
+
+ chip->target = bank->target;
+ }
+
+ switch (bank->base) {
+ case NRF52_FLASH_BASE_ADDR:
+ chip->bank[bank->bank_number].write = nrf52_code_flash_write;
+ break;
+ case NRF52_UICR_BASE_ADDR:
+ chip->bank[bank->bank_number].write = nrf52_uicr_flash_write;
+ break;
+ }
+
+ chip->bank[bank->bank_number].probed = false;
+ bank->driver_priv = chip;
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(nrf52_handle_mass_erase_command)
+{
+ int res;
+ struct flash_bank *bank = NULL;
+ struct target *target = get_current_target(CMD_CTX);
+
+ res = get_flash_bank_by_addr(target, NRF52_FLASH_BASE_ADDR, true, &bank);
+ if (res != ERROR_OK)
+ return res;
+
+ assert(bank != NULL);
+
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ res = nrf52_erase_all(chip);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to erase the chip");
+ nrf52_protect_check(bank);
+ return res;
+ }
+
+ for (int i = 0; i < bank->num_sectors; i++)
+ bank->sectors[i].is_erased = 1;
+
+ res = nrf52_protect_check(bank);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Failed to check chip's write protection");
+ return res;
+ }
+
+ res = get_flash_bank_by_addr(target, NRF52_UICR_BASE_ADDR, true, &bank);
+ if (res != ERROR_OK)
+ return res;
+
+ bank->sectors[0].is_erased = 1;
+
+ return ERROR_OK;
+}
+
+static int nrf52_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+ int res;
+ uint32_t ficr[2];
+ struct nrf52_info *chip = bank->driver_priv;
+ assert(chip != NULL);
+
+ res = target_read_u32(chip->target, NRF52_FICR_CODEPAGESIZE_ADDR, &ficr[0]);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Couldn't read NVMC_READY register");
+ return res;
+ }
+
+ res = target_read_u32(chip->target, NRF52_FICR_CODESIZE_ADDR, &ficr[1]);
+ if (res != ERROR_OK) {
+ LOG_ERROR("Couldn't read NVMC_READY register");
+ return res;
+ }
+
+ snprintf(buf, buf_size,
+ "\n--------nRF52 Series Device--------\n\n"
+ "\n[factory information control block]\n"
+ "code page size: %"PRIu32"B\n"
+ "code memory size: %"PRIu32"kB\n",
+ ficr[0],
+ (ficr[1] * ficr[0]) / 1024);
+
+ return ERROR_OK;
+}
+
+static const struct command_registration nrf52_exec_command_handlers[] = {
+ {
+ .name = "mass_erase",
+ .handler = nrf52_handle_mass_erase_command,
+ .mode = COMMAND_EXEC,
+ .help = "Erase all flash contents of the chip.",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration nrf52_command_handlers[] = {
+ {
+ .name = "nrf52",
+ .mode = COMMAND_ANY,
+ .help = "nrf52 flash command group",
+ .usage = "",
+ .chain = nrf52_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver nrf52_flash = {
+ .name = "nrf52",
+ .commands = nrf52_command_handlers,
+ .flash_bank_command = nrf52_flash_bank_command,
+ .info = nrf52_info,
+ .erase = nrf52_erase,
+ .protect = nrf52_protect,
+ .write = nrf52_write,
+ .read = default_flash_read,
+ .probe = nrf52_probe,
+ .auto_probe = nrf52_auto_probe,
+ .erase_check = default_flash_blank_check,
+ .protect_check = nrf52_protect_check,
+};
diff --git a/tcl/target/nrf52.cfg b/tcl/target/nrf52.cfg
index c1cbf1a..a2567ff 100644
--- a/tcl/target/nrf52.cfg
+++ b/tcl/target/nrf52.cfg
@@ -5,15 +5,22 @@
source [find target/swj-dp.tcl]
if { [info exists CHIPNAME] } {
- set _CHIPNAME $CHIPNAME
+ set _CHIPNAME $CHIPNAME
} else {
- set _CHIPNAME nrf52
+ set _CHIPNAME nrf52
+}
+
+# Work-area is a space in RAM used for flash programming, by default use 16kB.
+if { [info exists WORKAREASIZE] } {
+ set _WORKAREASIZE $WORKAREASIZE
+} else {
+ set _WORKAREASIZE 0x4000
}
if { [info exists CPUTAPID] } {
- set _CPUTAPID $CPUTAPID
+ set _CPUTAPID $CPUTAPID
} else {
- set _CPUTAPID 0x2ba01477
+ set _CPUTAPID 0x2ba01477
}
swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
@@ -21,8 +28,15 @@ swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME
-adapter_khz 10000
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
-if { ![using_hla] } {
- cortex_m reset_config sysresetreq
+if {![using_hla]} {
+ cortex_m reset_config sysresetreq
}
+
+flash bank $_CHIPNAME.flash nrf52 0x00000000 0 1 1 $_TARGETNAME
+flash bank $_CHIPNAME.uicr nrf52 0x10001000 0 1 1 $_TARGETNAME
+
+adapter_khz 1000
+
+$_TARGETNAME configure -event reset-end {}

View file

@ -29,6 +29,7 @@
;;; Copyright © 2016 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2016 Stefan Reichoer <stefan@xsteve.at>
;;; Copyright © 2016 Dylan Jeffers <sapientech@sapientech@openmailbox.org>
;;; Copyright © 2016 Alex Vong <alexvong1995@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@ -3172,6 +3173,30 @@ (define-public python2-cython
(inputs
`(("python-2" ,python-2))))) ; this is not automatically changed
;; The RPython toolchain currently does not support Python 3.
(define-public python2-rpython
(package
(name "python2-rpython")
(version "0.1.4")
(source
(origin
(method url-fetch)
(uri (pypi-uri "rpython" version))
(sha256
(base32
"07pps06fq4c4wmi5ii0sgh9zgwniz5y7frqhm28g3a154l163fxc"))))
(build-system python-build-system)
(arguments `(#:python ,python-2))
(native-inputs
`(("python2-pytest" ,python2-pytest) ; needed for running tests
("python2-setuptools" ,python2-setuptools)))
(home-page "https://rpython.readthedocs.org")
(synopsis "Framework for implementing interpreters and virtual machines")
(description "RPython is a translation and support framework for
producing implementations of dynamic languages, emphasizing a clean separation
between language specification and implementation aspects.")
(license license:expat)))
;; This version of numpy is missing the documentation and is only used to
;; build matplotlib which is required to build numpy's documentation.
(define python-numpy-bootstrap
@ -5258,30 +5283,28 @@ (define-public python2-backports-abc
(define-public python-waf
(package
(name "python-waf")
(version "1.9.1")
(version "1.9.5")
(source (origin
(method url-fetch)
(uri (string-append "https://waf.io/"
(uri (string-append "http://waf.io/"
"waf-" version ".tar.bz2"))
(sha256
(base32
"1nc4qaqx2vsanlpp9mcwvf91xjqpkvcc6fcxd5sb4fwvaxamw5v6"))))
"1sl3ipi2czds57rlzjnpdzqa0skx8asfvmh3qmibpvdwf15rpppg"))))
(build-system python-build-system)
(arguments
'(#:phases
(modify-phases %standard-phases
(replace 'build
(lambda _
(zero? (begin
(system* "python" "waf-light" "configure")
(system* "python" "waf-light" "build")))))
(lambda _
(zero? (system* "python" "waf-light" "configure" "build"))))
(replace 'check
(lambda _
(zero? (system* "python" "waf" "--version"))))
(lambda _
(zero? (system* "python" "waf" "--version"))))
(replace 'install
(lambda _
(copy-file "waf" %output))))))
(home-page "https://waf.io/")
(lambda _
(copy-file "waf" %output))))))
(home-page "http://waf.io/")
(synopsis "Python-based build system")
(description
"Waf is a Python-based framework for configuring, compiling and installing
@ -9652,7 +9675,9 @@ (define-public python-pika
"0nb4h08di432lv7dy2v9kpwgk0w92f24sqc2hw2s9vwr5b8v8xvj"))))
(build-system python-build-system)
(native-inputs
`(("python-twisted" ,python-twisted)))
`(("python-pyev" ,python-pyev)
("python-tornado" ,python-tornado)
("python-twisted" ,python-twisted)))
(home-page "https://pika.readthedocs.org")
(synopsis "Pure Python AMQP Client Library")
(description
@ -10214,6 +10239,8 @@ (define-public python-prompt-toolkit
(base32
"1vyjd0b7wciv55i19l44zy0adx8q7ss79lhy2r9d1rwz2y4822zg"))))
(build-system python-build-system)
(arguments
'(#:tests? #f)) ; The test suite uses some Windows-specific data types.
(inputs `(("python-wcwidth" ,python-wcwidth)
("python-pygments" ,python-pygments)))
(native-inputs `(("python-six" ,python-six)))
@ -10681,6 +10708,8 @@ (define-public python-publicsuffix2
(base32
"06lx603gdwad5hc3hmn763ngq0rq9bzz1ni3ga72nzk5n872arkd"))))
(build-system python-build-system)
(arguments
'(#:tests? #f)) ; The test suite requires network access.
(home-page "https://github.com/pombredanne/python-publicsuffix2")
(synopsis "Get a public suffix for a domain name using the Public Suffix List")
(description "Get a public suffix for a domain name using the Public Suffix
@ -11477,3 +11506,36 @@ (define-public python-flask-sqlalchemy
(description
"This package adds SQLAlchemy support to your Flask application.")
(license license:bsd-3)))
(define-public python-pyev
(package
(name "python-pyev")
(version "0.9.0")
(source
(origin
(method url-fetch)
(uri (pypi-uri "pyev" version))
(sha256
(base32
"0rf603lc0s6zpa1nb25vhd8g4y337wg2wyz56i0agsdh7jchl0sx"))))
(build-system python-build-system)
(arguments
`(#:tests? #f ; no test suite
#:phases
(modify-phases %standard-phases
(add-after 'unpack 'patch
(lambda* (#:key inputs #:allow-other-keys)
(let ((libev (string-append (assoc-ref inputs "libev")
"/lib/libev.so.4")))
(substitute* "setup.py"
(("libev_dll_name = find_library\\(\\\"ev\\\"\\)")
(string-append "libev_dll_name = \"" libev "\"")))))))))
(inputs
`(("libev" ,libev)))
(home-page "http://pythonhosted.org/pyev/")
(synopsis "Python libev interface")
(description "Pyev provides a Python interface to libev.")
(license license:gpl3)))
(define-public python2-pyev
(package-with-python2 python-pyev))

View file

@ -49,7 +49,7 @@ (define-public sdcc
(arguments
`(;; gputils is required for PIC ports
#:configure-flags
'("--disable-pic14-port" "--disable-pic16-port")
'("--disable-pic14-port" "--disable-pic16-port" "--enable-ucsim")
#:phases
(modify-phases %standard-phases
(add-after 'unpack 'patch-makefile

View file

@ -434,14 +434,14 @@ (define-public libva
(define-public ffmpeg
(package
(name "ffmpeg")
(version "3.1.5")
(version "3.2")
(source (origin
(method url-fetch)
(uri (string-append "https://ffmpeg.org/releases/ffmpeg-"
version ".tar.xz"))
(sha256
(base32
"16mqb1fs6ahqqv6a64dk4d8rp75ixdsipfzsz0vmc749yw2k3k29"))))
"1nnmd3h9pr2zic08isjcm1cmvcyd0aimpayb9r4qy45bihdhrxw8"))))
(build-system gnu-build-system)
(inputs
`(("fontconfig" ,fontconfig)
@ -1287,16 +1287,16 @@ (define-public avidemux
(define-public vapoursynth
(package
(name "vapoursynth")
(version "34")
(version "35")
(source (origin
(method url-fetch)
(uri (string-append
"https://github.com/vapoursynth/vapoursynth/archive/R"
version ".tar.gz"))
(file-name (string-append name "-" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"0rfldphg4gy3sdfffi5yzklqz93vsj2j6nny8snjbavnf161blyi"))))
"0629ys2lf618n9cc644xlvx0vx52v2fp3sx14p4mx5rg9nlasb3n"))))
(build-system gnu-build-system)
(native-inputs
`(("autoconf" ,autoconf)

View file

@ -48,14 +48,15 @@ (define-module (gnu packages vim)
(define-public vim
(package
(name "vim")
(version "8.0")
(version "8.0.0054")
(source (origin
(method url-fetch)
(uri (string-append "ftp://ftp.vim.org/pub/vim/unix/vim-"
version ".tar.bz2"))
(uri (string-append "https://github.com/vim/vim/archive/v"
version ".tar.gz"))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"1s34rf8089klsbdx5l0iw7vjymir0kzfrx8wb30s31wygnq29axc"))))
"018my9vmvflww9yzrrzgdbja8j075yxqj0czg351r6wrndqiv9vq"))))
(build-system gnu-build-system)
(arguments
`(#:test-target "test"

View file

@ -139,7 +139,9 @@ (define (file-hash file)
(write-file file port #:select? select?)
(force-output port)
(get-hash))
(call-with-input-file file port-sha256))))
(match file
("-" (port-sha256 (current-input-port)))
(_ (call-with-input-file file port-sha256))))))
(match args
((file)

View file

@ -40,171 +40,6 @@
namespace nix {
MakeError(SQLiteError, Error);
MakeError(SQLiteBusy, SQLiteError);
static void throwSQLiteError(sqlite3 * db, const format & f)
__attribute__ ((noreturn));
static void throwSQLiteError(sqlite3 * db, const format & f)
{
int err = sqlite3_errcode(db);
if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
if (err == SQLITE_PROTOCOL)
printMsg(lvlError, "warning: SQLite database is busy (SQLITE_PROTOCOL)");
else {
static bool warned = false;
if (!warned) {
printMsg(lvlError, "warning: SQLite database is busy");
warned = true;
}
}
/* Sleep for a while since retrying the transaction right away
is likely to fail again. */
#if HAVE_NANOSLEEP
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
nanosleep(&t, 0);
#else
sleep(1);
#endif
throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
}
else
throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
}
/* Convenience macros for retrying a SQLite transaction. */
#define retry_sqlite while (1) { try {
#define end_retry_sqlite break; } catch (SQLiteBusy & e) { } }
SQLite::~SQLite()
{
try {
if (db && sqlite3_close(db) != SQLITE_OK)
throwSQLiteError(db, "closing database");
} catch (...) {
ignoreException();
}
}
void SQLiteStmt::create(sqlite3 * db, const string & s)
{
checkInterrupt();
assert(!stmt);
if (sqlite3_prepare_v2(db, s.c_str(), -1, &stmt, 0) != SQLITE_OK)
throwSQLiteError(db, "creating statement");
this->db = db;
}
void SQLiteStmt::reset()
{
assert(stmt);
/* Note: sqlite3_reset() returns the error code for the most
recent call to sqlite3_step(). So ignore it. */
sqlite3_reset(stmt);
curArg = 1;
}
SQLiteStmt::~SQLiteStmt()
{
try {
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
throwSQLiteError(db, "finalizing statement");
} catch (...) {
ignoreException();
}
}
void SQLiteStmt::bind(const string & value)
{
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
throwSQLiteError(db, "binding argument");
}
void SQLiteStmt::bind(int value)
{
if (sqlite3_bind_int(stmt, curArg++, value) != SQLITE_OK)
throwSQLiteError(db, "binding argument");
}
void SQLiteStmt::bind64(long long value)
{
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
throwSQLiteError(db, "binding argument");
}
void SQLiteStmt::bind()
{
if (sqlite3_bind_null(stmt, curArg++) != SQLITE_OK)
throwSQLiteError(db, "binding argument");
}
/* Helper class to ensure that prepared statements are reset when
leaving the scope that uses them. Unfinished prepared statements
prevent transactions from being aborted, and can cause locks to be
kept when they should be released. */
struct SQLiteStmtUse
{
SQLiteStmt & stmt;
SQLiteStmtUse(SQLiteStmt & stmt) : stmt(stmt)
{
stmt.reset();
}
~SQLiteStmtUse()
{
try {
stmt.reset();
} catch (...) {
ignoreException();
}
}
};
struct SQLiteTxn
{
bool active;
sqlite3 * db;
SQLiteTxn(sqlite3 * db) : active(false) {
this->db = db;
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "starting transaction");
active = true;
}
void commit()
{
if (sqlite3_exec(db, "commit;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "committing transaction");
active = false;
}
~SQLiteTxn()
{
try {
if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "aborting transaction");
} catch (...) {
ignoreException();
}
}
};
void checkStoreNotSymlink()
{
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
@ -494,6 +329,7 @@ void LocalStore::openDB(bool create)
// ensure efficient lookup.
stmtQueryPathFromHashPart.create(db,
"select path from ValidPaths where path >= ? limit 1;");
stmtQueryValidPaths.create(db, "select path from ValidPaths");
}
@ -688,23 +524,16 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
}
unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool checkOutputs)
uint64_t LocalStore::addValidPath(const ValidPathInfo & info, bool checkOutputs)
{
SQLiteStmtUse use(stmtRegisterValidPath);
stmtRegisterValidPath.bind(info.path);
stmtRegisterValidPath.bind("sha256:" + printHash(info.hash));
stmtRegisterValidPath.bind(info.registrationTime == 0 ? time(0) : info.registrationTime);
if (info.deriver != "")
stmtRegisterValidPath.bind(info.deriver);
else
stmtRegisterValidPath.bind(); // null
if (info.narSize != 0)
stmtRegisterValidPath.bind64(info.narSize);
else
stmtRegisterValidPath.bind(); // null
if (sqlite3_step(stmtRegisterValidPath) != SQLITE_DONE)
throwSQLiteError(db, format("registering valid path `%1%' in database") % info.path);
unsigned long long id = sqlite3_last_insert_rowid(db);
stmtRegisterValidPath.use()
(info.path)
("sha256:" + printHash(info.hash))
(info.registrationTime == 0 ? time(0) : info.registrationTime)
(info.deriver, info.deriver != "")
(info.narSize, info.narSize != 0)
.exec();
uint64_t id = sqlite3_last_insert_rowid(db);
/* If this is a derivation, then store the derivation outputs in
the database. This is useful for the garbage collector: it can
@ -720,13 +549,12 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
registration above is undone. */
if (checkOutputs) checkDerivationOutputs(info.path, drv);
foreach (DerivationOutputs::iterator, i, drv.outputs) {
SQLiteStmtUse use(stmtAddDerivationOutput);
stmtAddDerivationOutput.bind(id);
stmtAddDerivationOutput.bind(i->first);
stmtAddDerivationOutput.bind(i->second.path);
if (sqlite3_step(stmtAddDerivationOutput) != SQLITE_DONE)
throwSQLiteError(db, format("adding derivation output for `%1%' in database") % info.path);
for (auto & i : drv.outputs) {
stmtAddDerivationOutput.use()
(id)
(i.first)
(i.second.path)
.exec();
}
}
@ -734,76 +562,52 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
}
void LocalStore::addReference(unsigned long long referrer, unsigned long long reference)
void LocalStore::addReference(uint64_t referrer, uint64_t reference)
{
SQLiteStmtUse use(stmtAddReference);
stmtAddReference.bind(referrer);
stmtAddReference.bind(reference);
if (sqlite3_step(stmtAddReference) != SQLITE_DONE)
throwSQLiteError(db, "adding reference to database");
stmtAddReference.use()(referrer)(reference).exec();
}
void LocalStore::registerFailedPath(const Path & path)
{
retry_sqlite {
SQLiteStmtUse use(stmtRegisterFailedPath);
stmtRegisterFailedPath.bind(path);
stmtRegisterFailedPath.bind(time(0));
if (sqlite3_step(stmtRegisterFailedPath) != SQLITE_DONE)
throwSQLiteError(db, format("registering failed path `%1%'") % path);
} end_retry_sqlite;
retrySQLite<void>([&]() {
stmtRegisterFailedPath.use()(path)(time(0)).step();
});
}
bool LocalStore::hasPathFailed(const Path & path)
{
retry_sqlite {
SQLiteStmtUse use(stmtHasPathFailed);
stmtHasPathFailed.bind(path);
int res = sqlite3_step(stmtHasPathFailed);
if (res != SQLITE_DONE && res != SQLITE_ROW)
throwSQLiteError(db, "querying whether path failed");
return res == SQLITE_ROW;
} end_retry_sqlite;
return retrySQLite<bool>([&]() {
return stmtHasPathFailed.use()(path).next();
});
}
PathSet LocalStore::queryFailedPaths()
{
retry_sqlite {
SQLiteStmtUse use(stmtQueryFailedPaths);
return retrySQLite<PathSet>([&]() {
auto useQueryFailedPaths(stmtQueryFailedPaths.use());
PathSet res;
int r;
while ((r = sqlite3_step(stmtQueryFailedPaths)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmtQueryFailedPaths, 0);
assert(s);
res.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, "error querying failed paths");
while (useQueryFailedPaths.next())
res.insert(useQueryFailedPaths.getStr(0));
return res;
} end_retry_sqlite;
});
}
void LocalStore::clearFailedPaths(const PathSet & paths)
{
retry_sqlite {
retrySQLite<void>([&]() {
SQLiteTxn txn(db);
foreach (PathSet::const_iterator, i, paths) {
SQLiteStmtUse use(stmtClearFailedPath);
stmtClearFailedPath.bind(*i);
if (sqlite3_step(stmtClearFailedPath) != SQLITE_DONE)
throwSQLiteError(db, format("clearing failed path `%1%' in database") % *i);
}
for (auto & path : paths)
stmtClearFailedPath.use()(path).exec();
txn.commit();
} end_retry_sqlite;
});
}
@ -828,47 +632,34 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
assertStorePath(path);
retry_sqlite {
return retrySQLite<ValidPathInfo>([&]() {
/* Get the path info. */
SQLiteStmtUse use1(stmtQueryPathInfo);
auto useQueryPathInfo(stmtQueryPathInfo.use()(path));
stmtQueryPathInfo.bind(path);
if (!useQueryPathInfo.next())
throw Error(format("path `%1%' is not valid") % path);
int r = sqlite3_step(stmtQueryPathInfo);
if (r == SQLITE_DONE) throw Error(format("path `%1%' is not valid") % path);
if (r != SQLITE_ROW) throwSQLiteError(db, "querying path in database");
info.id = useQueryPathInfo.getInt(0);
info.id = sqlite3_column_int(stmtQueryPathInfo, 0);
info.hash = parseHashField(path, useQueryPathInfo.getStr(1));
const char * s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 1);
assert(s);
info.hash = parseHashField(path, s);
info.registrationTime = useQueryPathInfo.getInt(2);
info.registrationTime = sqlite3_column_int(stmtQueryPathInfo, 2);
s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 3);
auto s = (const char *) sqlite3_column_text(stmtQueryPathInfo, 3);
if (s) info.deriver = s;
/* Note that narSize = NULL yields 0. */
info.narSize = sqlite3_column_int64(stmtQueryPathInfo, 4);
info.narSize = useQueryPathInfo.getInt(4);
/* Get the references. */
SQLiteStmtUse use2(stmtQueryReferences);
auto useQueryReferences(stmtQueryReferences.use()(info.id));
stmtQueryReferences.bind(info.id);
while ((r = sqlite3_step(stmtQueryReferences)) == SQLITE_ROW) {
s = (const char *) sqlite3_column_text(stmtQueryReferences, 0);
assert(s);
info.references.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, format("error getting references of `%1%'") % path);
while (useQueryReferences.next())
info.references.insert(useQueryReferences.getStr(0));
return info;
} end_retry_sqlite;
});
}
@ -876,78 +667,56 @@ ValidPathInfo LocalStore::queryPathInfo(const Path & path)
narSize field. */
void LocalStore::updatePathInfo(const ValidPathInfo & info)
{
SQLiteStmtUse use(stmtUpdatePathInfo);
if (info.narSize != 0)
stmtUpdatePathInfo.bind64(info.narSize);
else
stmtUpdatePathInfo.bind(); // null
stmtUpdatePathInfo.bind("sha256:" + printHash(info.hash));
stmtUpdatePathInfo.bind(info.path);
if (sqlite3_step(stmtUpdatePathInfo) != SQLITE_DONE)
throwSQLiteError(db, format("updating info of path `%1%' in database") % info.path);
stmtUpdatePathInfo.use()
(info.narSize, info.narSize != 0)
("sha256:" + printHash(info.hash))
(info.path)
.exec();
}
unsigned long long LocalStore::queryValidPathId(const Path & path)
uint64_t LocalStore::queryValidPathId(const Path & path)
{
SQLiteStmtUse use(stmtQueryPathInfo);
stmtQueryPathInfo.bind(path);
int res = sqlite3_step(stmtQueryPathInfo);
if (res == SQLITE_ROW) return sqlite3_column_int(stmtQueryPathInfo, 0);
if (res == SQLITE_DONE) throw Error(format("path `%1%' is not valid") % path);
throwSQLiteError(db, "querying path in database");
auto use(stmtQueryPathInfo.use()(path));
if (!use.next())
throw Error(format("path %1% is not valid") % path);
return use.getInt(0);
}
bool LocalStore::isValidPath_(const Path & path)
{
SQLiteStmtUse use(stmtQueryPathInfo);
stmtQueryPathInfo.bind(path);
int res = sqlite3_step(stmtQueryPathInfo);
if (res != SQLITE_DONE && res != SQLITE_ROW)
throwSQLiteError(db, "querying path in database");
return res == SQLITE_ROW;
return stmtQueryPathInfo.use()(path).next();
}
bool LocalStore::isValidPath(const Path & path)
{
retry_sqlite {
return retrySQLite<bool>([&]() {
return isValidPath_(path);
} end_retry_sqlite;
});
}
PathSet LocalStore::queryValidPaths(const PathSet & paths)
{
retry_sqlite {
return retrySQLite<PathSet>([&]() {
PathSet res;
foreach (PathSet::const_iterator, i, paths)
if (isValidPath_(*i)) res.insert(*i);
return res;
} end_retry_sqlite;
});
}
PathSet LocalStore::queryAllValidPaths()
{
retry_sqlite {
SQLiteStmt stmt;
stmt.create(db, "select path from ValidPaths");
return retrySQLite<PathSet>([&]() {
auto use(stmtQueryValidPaths.use());
PathSet res;
int r;
while ((r = sqlite3_step(stmt)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmt, 0);
assert(s);
res.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, "error getting valid paths");
while (use.next()) res.insert(use.getStr(0));
return res;
} end_retry_sqlite;
});
}
@ -961,28 +730,19 @@ void LocalStore::queryReferences(const Path & path,
void LocalStore::queryReferrers_(const Path & path, PathSet & referrers)
{
SQLiteStmtUse use(stmtQueryReferrers);
auto useQueryReferrers(stmtQueryReferrers.use()(path));
stmtQueryReferrers.bind(path);
int r;
while ((r = sqlite3_step(stmtQueryReferrers)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmtQueryReferrers, 0);
assert(s);
referrers.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, format("error getting references of `%1%'") % path);
while (useQueryReferrers.next())
referrers.insert(useQueryReferrers.getStr(0));
}
void LocalStore::queryReferrers(const Path & path, PathSet & referrers)
{
assertStorePath(path);
retry_sqlite {
return retrySQLite<void>([&]() {
queryReferrers_(path, referrers);
} end_retry_sqlite;
});
}
@ -996,67 +756,43 @@ PathSet LocalStore::queryValidDerivers(const Path & path)
{
assertStorePath(path);
retry_sqlite {
SQLiteStmtUse use(stmtQueryValidDerivers);
stmtQueryValidDerivers.bind(path);
return retrySQLite<PathSet>([&]() {
auto useQueryValidDerivers(stmtQueryValidDerivers.use()(path));
PathSet derivers;
int r;
while ((r = sqlite3_step(stmtQueryValidDerivers)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmtQueryValidDerivers, 1);
assert(s);
derivers.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, format("error getting valid derivers of `%1%'") % path);
while (useQueryValidDerivers.next())
derivers.insert(useQueryValidDerivers.getStr(1));
return derivers;
} end_retry_sqlite;
});
}
PathSet LocalStore::queryDerivationOutputs(const Path & path)
{
retry_sqlite {
SQLiteStmtUse use(stmtQueryDerivationOutputs);
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
return retrySQLite<PathSet>([&]() {
auto useQueryDerivationOutputs(stmtQueryDerivationOutputs.use()(queryValidPathId(path)));
PathSet outputs;
int r;
while ((r = sqlite3_step(stmtQueryDerivationOutputs)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmtQueryDerivationOutputs, 1);
assert(s);
outputs.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, format("error getting outputs of `%1%'") % path);
while (useQueryDerivationOutputs.next())
outputs.insert(useQueryDerivationOutputs.getStr(1));
return outputs;
} end_retry_sqlite;
});
}
StringSet LocalStore::queryDerivationOutputNames(const Path & path)
{
retry_sqlite {
SQLiteStmtUse use(stmtQueryDerivationOutputs);
stmtQueryDerivationOutputs.bind(queryValidPathId(path));
return retrySQLite<StringSet>([&]() {
auto useQueryDerivationOutputs(stmtQueryDerivationOutputs.use()(queryValidPathId(path)));
StringSet outputNames;
int r;
while ((r = sqlite3_step(stmtQueryDerivationOutputs)) == SQLITE_ROW) {
const char * s = (const char *) sqlite3_column_text(stmtQueryDerivationOutputs, 0);
assert(s);
outputNames.insert(s);
}
if (r != SQLITE_DONE)
throwSQLiteError(db, format("error getting output names of `%1%'") % path);
while (useQueryDerivationOutputs.next())
outputNames.insert(useQueryDerivationOutputs.getStr(0));
return outputNames;
} end_retry_sqlite;
});
}
@ -1066,17 +802,14 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
Path prefix = settings.nixStore + "/" + hashPart;
retry_sqlite {
SQLiteStmtUse use(stmtQueryPathFromHashPart);
stmtQueryPathFromHashPart.bind(prefix);
return retrySQLite<Path>([&]() -> Path {
auto useQueryPathFromHashPart(stmtQueryPathFromHashPart.use()(prefix));
int res = sqlite3_step(stmtQueryPathFromHashPart);
if (res == SQLITE_DONE) return "";
if (res != SQLITE_ROW) throwSQLiteError(db, "finding path in database");
if (!useQueryPathFromHashPart.next()) return "";
const char * s = (const char *) sqlite3_column_text(stmtQueryPathFromHashPart, 0);
return s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0 ? s : "";
} end_retry_sqlite;
});
}
@ -1306,7 +1039,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
* expense of some speed of the path registering operation. */
if (settings.syncBeforeRegistering) sync();
retry_sqlite {
return retrySQLite<void>([&]() {
SQLiteTxn txn(db);
PathSet paths;
@ -1319,10 +1052,10 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
paths.insert(i->path);
}
foreach (ValidPathInfos::const_iterator, i, infos) {
unsigned long long referrer = queryValidPathId(i->path);
foreach (PathSet::iterator, j, i->references)
addReference(referrer, queryValidPathId(*j));
for (auto & i : infos) {
auto referrer = queryValidPathId(i.path);
for (auto & j : i.references)
addReference(referrer, queryValidPathId(j));
}
/* Check that the derivation outputs are correct. We can't do
@ -1343,7 +1076,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
topoSortPaths(*this, paths);
txn.commit();
} end_retry_sqlite;
});
}
@ -1355,12 +1088,7 @@ void LocalStore::invalidatePath(const Path & path)
drvHashes.erase(path);
SQLiteStmtUse use(stmtInvalidatePath);
stmtInvalidatePath.bind(path);
if (sqlite3_step(stmtInvalidatePath) != SQLITE_DONE)
throwSQLiteError(db, format("invalidating path `%1%' in database") % path);
stmtInvalidatePath.use()(path).exec();
/* Note that the foreign key constraints on the Refs table take
care of deleting the references entries for `path'. */
@ -1733,7 +1461,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
{
assertStorePath(path);
retry_sqlite {
retrySQLite<void>([&]() {
SQLiteTxn txn(db);
if (isValidPath_(path)) {
@ -1746,7 +1474,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
}
txn.commit();
} end_retry_sqlite;
});
}

View file

@ -1,15 +1,12 @@
#pragma once
#include "sqlite.hh"
#include <string>
#include <unordered_set>
#include "pathlocks.hh"
#include "store-api.hh"
#include "util.hh"
#include "pathlocks.hh"
class sqlite3;
class sqlite3_stmt;
namespace nix {
@ -52,34 +49,6 @@ struct RunningSubstituter
};
/* Wrapper object to close the SQLite database automatically. */
struct SQLite
{
sqlite3 * db;
SQLite() { db = 0; }
~SQLite();
operator sqlite3 * () { return db; }
};
/* Wrapper object to create and destroy SQLite prepared statements. */
struct SQLiteStmt
{
sqlite3 * db;
sqlite3_stmt * stmt;
unsigned int curArg;
SQLiteStmt() { stmt = 0; }
void create(sqlite3 * db, const string & s);
void reset();
~SQLiteStmt();
operator sqlite3_stmt * () { return stmt; }
void bind(const string & value);
void bind(int value);
void bind64(long long value);
void bind();
};
class LocalStore : public StoreAPI
{
private:
@ -238,6 +207,7 @@ private:
SQLiteStmt stmtQueryValidDerivers;
SQLiteStmt stmtQueryDerivationOutputs;
SQLiteStmt stmtQueryPathFromHashPart;
SQLiteStmt stmtQueryValidPaths;
/* Cache for pathContentsGood(). */
std::map<Path, bool> pathContentsGoodCache;
@ -254,11 +224,11 @@ private:
void makeStoreWritable();
unsigned long long queryValidPathId(const Path & path);
uint64_t queryValidPathId(const Path & path);
unsigned long long addValidPath(const ValidPathInfo & info, bool checkOutputs = true);
uint64_t addValidPath(const ValidPathInfo & info, bool checkOutputs = true);
void addReference(unsigned long long referrer, unsigned long long reference);
void addReference(uint64_t referrer, uint64_t reference);
void appendReferrer(const Path & from, const Path & to, bool lock);

View file

@ -148,10 +148,23 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
inodeHash.insert(st.st_ino);
return;
}
if (errno != EEXIST)
switch (errno) {
case EEXIST:
/* Fall through if another process created linkPath before
we did. */
break;
case ENOSPC:
/* On ext4, that probably means the directory index is full. When
that happens, it's fine to ignore it: we just effectively
disable deduplication of this file. */
printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %m") % linkPath % path);
return;
default:
throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path);
/* Fall through if another process created linkPath before
we did. */
}
}
/* Yes! We've seen a file with the same contents. Replace the
@ -195,8 +208,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath);
return;
}
throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
}
throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
}
/* Atomically replace the old file with the new hard link. */
if (rename(tempLink.c_str(), path.c_str()) == -1) {

166
nix/libstore/sqlite.cc Normal file
View file

@ -0,0 +1,166 @@
#include "sqlite.hh"
#include "util.hh"
#include <sqlite3.h>
namespace nix {
[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f)
{
int err = sqlite3_errcode(db);
if (err == SQLITE_BUSY || err == SQLITE_PROTOCOL) {
if (err == SQLITE_PROTOCOL)
printMsg(lvlError, "warning: SQLite database is busy (SQLITE_PROTOCOL)");
else {
static bool warned = false;
if (!warned) {
printMsg(lvlError, "warning: SQLite database is busy");
warned = true;
}
}
/* Sleep for a while since retrying the transaction right away
is likely to fail again. */
#if HAVE_NANOSLEEP
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
nanosleep(&t, 0);
#else
sleep(1);
#endif
throw SQLiteBusy(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
}
else
throw SQLiteError(format("%1%: %2%") % f.str() % sqlite3_errmsg(db));
}
SQLite::~SQLite()
{
try {
if (db && sqlite3_close(db) != SQLITE_OK)
throwSQLiteError(db, "closing database");
} catch (...) {
ignoreException();
}
}
void SQLiteStmt::create(sqlite3 * db, const string & s)
{
checkInterrupt();
assert(!stmt);
if (sqlite3_prepare_v2(db, s.c_str(), -1, &stmt, 0) != SQLITE_OK)
throwSQLiteError(db, "creating statement");
this->db = db;
}
SQLiteStmt::~SQLiteStmt()
{
try {
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
throwSQLiteError(db, "finalizing statement");
} catch (...) {
ignoreException();
}
}
SQLiteStmt::Use::Use(SQLiteStmt & stmt)
: stmt(stmt)
{
assert(stmt.stmt);
/* Note: sqlite3_reset() returns the error code for the most
recent call to sqlite3_step(). So ignore it. */
sqlite3_reset(stmt);
}
SQLiteStmt::Use::~Use()
{
sqlite3_reset(stmt);
}
SQLiteStmt::Use & SQLiteStmt::Use::operator () (const std::string & value, bool notNull)
{
if (notNull) {
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
throwSQLiteError(stmt.db, "binding argument");
} else
bind();
return *this;
}
SQLiteStmt::Use & SQLiteStmt::Use::operator () (int64_t value, bool notNull)
{
if (notNull) {
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
throwSQLiteError(stmt.db, "binding argument");
} else
bind();
return *this;
}
SQLiteStmt::Use & SQLiteStmt::Use::bind()
{
if (sqlite3_bind_null(stmt, curArg++) != SQLITE_OK)
throwSQLiteError(stmt.db, "binding argument");
return *this;
}
int SQLiteStmt::Use::step()
{
return sqlite3_step(stmt);
}
void SQLiteStmt::Use::exec()
{
int r = step();
assert(r != SQLITE_ROW);
if (r != SQLITE_DONE)
throwSQLiteError(stmt.db, "executing SQLite statement");
}
bool SQLiteStmt::Use::next()
{
int r = step();
if (r != SQLITE_DONE && r != SQLITE_ROW)
throwSQLiteError(stmt.db, "executing SQLite query");
return r == SQLITE_ROW;
}
std::string SQLiteStmt::Use::getStr(int col)
{
auto s = (const char *) sqlite3_column_text(stmt, col);
assert(s);
return s;
}
int64_t SQLiteStmt::Use::getInt(int col)
{
// FIXME: detect nulls?
return sqlite3_column_int64(stmt, col);
}
SQLiteTxn::SQLiteTxn(sqlite3 * db)
{
this->db = db;
if (sqlite3_exec(db, "begin;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "starting transaction");
active = true;
}
void SQLiteTxn::commit()
{
if (sqlite3_exec(db, "commit;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "committing transaction");
active = false;
}
SQLiteTxn::~SQLiteTxn()
{
try {
if (active && sqlite3_exec(db, "rollback;", 0, 0, 0) != SQLITE_OK)
throwSQLiteError(db, "aborting transaction");
} catch (...) {
ignoreException();
}
}
}

102
nix/libstore/sqlite.hh Normal file
View file

@ -0,0 +1,102 @@
#pragma once
#include <functional>
#include <string>
#include "types.hh"
class sqlite3;
class sqlite3_stmt;
namespace nix {
/* RAII wrapper to close a SQLite database automatically. */
struct SQLite
{
sqlite3 * db;
SQLite() { db = 0; }
~SQLite();
operator sqlite3 * () { return db; }
};
/* RAII wrapper to create and destroy SQLite prepared statements. */
struct SQLiteStmt
{
sqlite3 * db = 0;
sqlite3_stmt * stmt = 0;
SQLiteStmt() { }
void create(sqlite3 * db, const std::string & s);
~SQLiteStmt();
operator sqlite3_stmt * () { return stmt; }
/* Helper for binding / executing statements. */
class Use
{
friend struct SQLiteStmt;
private:
SQLiteStmt & stmt;
unsigned int curArg = 1;
Use(SQLiteStmt & stmt);
public:
~Use();
/* Bind the next parameter. */
Use & operator () (const std::string & value, bool notNull = true);
Use & operator () (int64_t value, bool notNull = true);
Use & bind(); // null
int step();
/* Execute a statement that does not return rows. */
void exec();
/* For statements that return 0 or more rows. Returns true iff
a row is available. */
bool next();
std::string getStr(int col);
int64_t getInt(int col);
};
Use use()
{
return Use(*this);
}
};
/* RAII helper that ensures transactions are aborted unless explicitly
committed. */
struct SQLiteTxn
{
bool active = false;
sqlite3 * db;
SQLiteTxn(sqlite3 * db);
void commit();
~SQLiteTxn();
};
MakeError(SQLiteError, Error);
MakeError(SQLiteBusy, SQLiteError);
[[noreturn]] void throwSQLiteError(sqlite3 * db, const format & f);
/* Convenience function for retrying a SQLite transaction when the
database is busy. */
template<typename T>
T retrySQLite(std::function<T()> fun)
{
while (true) {
try {
return fun();
} catch (SQLiteBusy & e) {
}
}
}
}

View file

@ -89,8 +89,8 @@ struct ValidPathInfo
Hash hash;
PathSet references;
time_t registrationTime = 0;
unsigned long long narSize = 0; // 0 = unknown
unsigned long long id; // internal use only
uint64_t narSize = 0; // 0 = unknown
uint64_t id; // internal use only
bool operator == (const ValidPathInfo & i) const
{

View file

@ -86,7 +86,8 @@ libstore_a_SOURCES = \
%D%/libstore/local-store.cc \
%D%/libstore/build.cc \
%D%/libstore/pathlocks.cc \
%D%/libstore/derivations.cc
%D%/libstore/derivations.cc \
%D%/libstore/sqlite.cc
libstore_headers = \
%D%/libstore/references.hh \
@ -96,6 +97,7 @@ libstore_headers = \
%D%/libstore/derivations.hh \
%D%/libstore/misc.hh \
%D%/libstore/local-store.hh \
%D%/libstore/sqlite.hh \
%D%/libstore/store-api.hh
libstore_a_CPPFLAGS = \

View file

@ -1,5 +1,5 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013, 2014, 2016 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
#
# This file is part of GNU Guix.
@ -27,6 +27,7 @@ tmpdir="guix-hash-$$"
trap 'rm -rf "$tmpdir"' EXIT
test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
test `echo -n | guix hash -` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73
test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq