summary refs log tree commit diff
diff options
context:
space:
mode:
authorFranz Pletz <fpletz@fnordicwalking.de>2019-11-05 01:07:22 +0100
committerFranz Pletz <fpletz@fnordicwalking.de>2019-11-05 01:07:22 +0100
commit8dca8b9ccb05e7abe6b769485a4d224987c15c06 (patch)
tree80f8e212628d458ecc6d9e9af22661813eed8aa7
parent1ba64dad7c7b29a03ace672b2ff1a01343e853fe (diff)
parent22906321fbc0d38372d7ae2657adb2597fc384c1 (diff)
downloadnixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar.gz
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar.bz2
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar.lz
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar.xz
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.tar.zst
nixpkgs-8dca8b9ccb05e7abe6b769485a4d224987c15c06.zip
Merge remote-tracking branch 'origin/master' into gcc-9
-rw-r--r--lib/modules.nix2
-rw-r--r--maintainers/maintainer-list.nix18
-rw-r--r--nixos/doc/manual/development/running-nixos-tests-interactively.xml12
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.xml87
-rw-r--r--nixos/doc/manual/man-nixos-option.xml21
-rw-r--r--nixos/doc/manual/release-notes/rl-2003.xml6
-rw-r--r--nixos/lib/test-driver/test-driver.py758
-rw-r--r--nixos/lib/testing-python.nix279
-rw-r--r--nixos/modules/hardware/brillo.nix22
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh327
-rw-r--r--nixos/modules/installer/tools/nixos-option/CMakeLists.txt8
-rw-r--r--nixos/modules/installer/tools/nixos-option/default.nix11
-rw-r--r--nixos/modules/installer/tools/nixos-option/libnix-copy-paste.cc83
-rw-r--r--nixos/modules/installer/tools/nixos-option/libnix-copy-paste.hh9
-rw-r--r--nixos/modules/installer/tools/nixos-option/nixos-option.cc618
-rw-r--r--nixos/modules/installer/tools/tools.nix5
-rw-r--r--nixos/modules/module-list.nix4
-rw-r--r--nixos/modules/programs/ssh.nix11
-rw-r--r--nixos/modules/security/pam_mount.nix6
-rw-r--r--nixos/modules/services/audio/mpd.nix1
-rw-r--r--nixos/modules/services/networking/nat.nix2
-rw-r--r--nixos/modules/services/web-apps/moinmoin.nix303
-rw-r--r--nixos/modules/services/web-apps/trac.nix79
-rw-r--r--nixos/modules/services/x11/hardware/digimend.nix43
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix135
-rw-r--r--nixos/tests/acme.nix65
-rw-r--r--nixos/tests/all-tests.nix2
-rw-r--r--nixos/tests/ammonite.nix6
-rw-r--r--nixos/tests/automysqlbackup.nix32
-rw-r--r--nixos/tests/bittorrent.nix58
-rw-r--r--nixos/tests/boot.nix35
-rw-r--r--nixos/tests/emacs-daemon.nix23
-rw-r--r--nixos/tests/gitea.nix30
-rw-r--r--nixos/tests/login.nix104
-rw-r--r--nixos/tests/make-test-python.nix9
-rw-r--r--nixos/tests/moinmoin.nix24
-rw-r--r--nixos/tests/postgresql.nix44
-rw-r--r--nixos/tests/quake3.nix42
-rw-r--r--nixos/tests/trac.nix19
-rw-r--r--nixos/tests/wireguard/default.nix12
-rw-r--r--nixos/tests/wireguard/generated.nix56
-rw-r--r--nixos/tests/zfs.nix20
-rw-r--r--pkgs/applications/audio/asunder/default.nix8
-rw-r--r--pkgs/applications/audio/lollypop/default.nix4
-rw-r--r--pkgs/applications/audio/yoshimi/default.nix4
-rw-r--r--pkgs/applications/editors/quilter/default.nix4
-rw-r--r--pkgs/applications/graphics/freecad/default.nix12
-rw-r--r--pkgs/applications/graphics/gimp/default.nix133
-rw-r--r--pkgs/applications/graphics/gimp/plugins/default.nix23
-rw-r--r--pkgs/applications/graphics/gimp/wrapper.nix1
-rw-r--r--pkgs/applications/graphics/inkscape/default.nix5
-rw-r--r--pkgs/applications/misc/calibre/default.nix2
-rw-r--r--pkgs/applications/misc/dbeaver/default.nix4
-rw-r--r--pkgs/applications/misc/keepass-plugins/otpkeyprov/default.nix32
-rw-r--r--pkgs/applications/misc/netsurf/buildsystem/default.nix2
-rw-r--r--pkgs/applications/misc/netsurf/libnsgif/default.nix2
-rw-r--r--pkgs/applications/networking/browsers/vivaldi/default.nix4
-rw-r--r--pkgs/applications/networking/instant-messengers/vk-messenger/default.nix11
-rw-r--r--pkgs/applications/networking/instant-messengers/wire-desktop/default.nix4
-rw-r--r--pkgs/applications/networking/p2p/qbittorrent/default.nix4
-rw-r--r--pkgs/applications/office/paperwork/default.nix2
-rw-r--r--pkgs/applications/radio/sdrangel/default.nix2
-rw-r--r--pkgs/applications/science/biology/deeptools/default.nix42
-rw-r--r--pkgs/applications/version-management/p4v/default.nix6
-rw-r--r--pkgs/applications/version-management/sourcehut/builds.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/core.nix6
-rw-r--r--pkgs/applications/version-management/sourcehut/dispatch.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/git.nix15
-rw-r--r--pkgs/applications/version-management/sourcehut/hg.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/meta.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/paste.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/scm.nix4
-rw-r--r--pkgs/applications/version-management/sourcehut/todo.nix4
-rw-r--r--pkgs/applications/video/smplayer/default.nix14
-rw-r--r--pkgs/applications/virtualization/x11docker/default.nix17
-rw-r--r--pkgs/build-support/nix-prefetch-github/default.nix29
-rw-r--r--pkgs/data/fonts/liberation-sans-narrow/default.nix4
-rw-r--r--pkgs/data/fonts/rictydiminished-with-firacode/default.nix4
-rw-r--r--pkgs/data/themes/yaru/default.nix4
-rw-r--r--pkgs/desktops/gnome-3/default.nix3
-rw-r--r--pkgs/desktops/gnome-3/devtools/devhelp/default.nix55
-rw-r--r--pkgs/desktops/gnome-3/extensions/night-theme-switcher/default.nix21
-rw-r--r--pkgs/desktops/pantheon/apps/appcenter/default.nix92
-rw-r--r--pkgs/desktops/pantheon/apps/elementary-calendar/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/elementary-camera/default.nix4
-rw-r--r--pkgs/desktops/pantheon/apps/elementary-feedback/default.nix70
-rw-r--r--pkgs/desktops/pantheon/apps/elementary-files/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/sideload/default.nix73
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/about/default.nix13
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/about/fix-paths.patch26
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/about/lspci-path.patch13
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/about/remove-update-button.patch55
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/bluetooth/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/clock-format.patch12
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/display/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/default.nix6
-rw-r--r--pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/hardcode-gsettings.patch15
-rw-r--r--pkgs/desktops/pantheon/artwork/elementary-gtk-theme/default.nix6
-rw-r--r--pkgs/desktops/pantheon/artwork/elementary-icon-theme/default.nix4
-rw-r--r--pkgs/desktops/pantheon/default.nix14
-rw-r--r--pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/elementary-greeter/hardcode-fallback-background.patch10
-rw-r--r--pkgs/desktops/pantheon/desktop/elementary-onboarding/default.nix79
-rw-r--r--pkgs/desktops/pantheon/desktop/gala/default.nix6
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/applications-menu/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/bluetooth/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix28
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/keyboard/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/network/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/nightlight/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/notifications/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/power/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/session/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel-indicators/sound/default.nix4
-rw-r--r--pkgs/desktops/pantheon/desktop/wingpanel/default.nix4
-rw-r--r--pkgs/desktops/pantheon/granite/default.nix20
-rwxr-xr-xpkgs/desktops/pantheon/update.sh8
-rw-r--r--pkgs/development/compilers/gcc/7/default.nix3
-rw-r--r--pkgs/development/compilers/gcc/8/default.nix3
-rw-r--r--pkgs/development/compilers/ispc/default.nix4
-rw-r--r--pkgs/development/compilers/pakcs/curry-base.nix2
-rw-r--r--pkgs/development/compilers/pakcs/curry-frontend.nix18
-rw-r--r--pkgs/development/compilers/pakcs/default.nix4
-rwxr-xr-xpkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py4
-rw-r--r--pkgs/development/libraries/SDL/find-headers.patch20
-rw-r--r--pkgs/development/libraries/SDL/setup-hook.sh1
-rw-r--r--pkgs/development/libraries/SDL_Pango/default.nix32
-rw-r--r--pkgs/development/libraries/SDL_Pango/fixes.patch148
-rw-r--r--pkgs/development/libraries/gegl/4.0.nix116
-rw-r--r--pkgs/development/libraries/gnu-efi/default.nix15
-rw-r--r--pkgs/development/libraries/hunspell/dictionaries.nix10
-rw-r--r--pkgs/development/libraries/kmsxx/default.nix14
-rw-r--r--pkgs/development/libraries/libjpeg-turbo/default.nix4
-rw-r--r--pkgs/development/libraries/mm-common/default.nix20
-rw-r--r--pkgs/development/libraries/poly2tri-c/default.nix42
-rw-r--r--pkgs/development/libraries/protobuf/3.10.nix4
-rw-r--r--pkgs/development/libraries/protobuf/3.9.nix4
-rw-r--r--pkgs/development/libraries/wolfssl/default.nix4
-rw-r--r--pkgs/development/ocaml-modules/mlgmpidl/default.nix4
-rw-r--r--pkgs/development/perl-modules/alien-sdl.patch30
-rw-r--r--pkgs/development/python-modules/deeptoolsintervals/default.nix28
-rw-r--r--pkgs/development/python-modules/koji/default.nix12
-rw-r--r--pkgs/development/python-modules/license-expression/default.nix4
-rw-r--r--pkgs/development/python-modules/moderngl_window/default.nix38
-rw-r--r--pkgs/development/python-modules/nix-prefetch-github/default.nix4
-rw-r--r--pkgs/development/python-modules/pg8000/1_12.nix4
-rw-r--r--pkgs/development/python-modules/pre-commit/default.nix4
-rw-r--r--pkgs/development/python-modules/py2bit/default.nix27
-rw-r--r--pkgs/development/python-modules/pyatmo/default.nix3
-rw-r--r--pkgs/development/python-modules/pybigwig/default.nix33
-rw-r--r--pkgs/development/python-modules/pyglet/default.nix2
-rw-r--r--pkgs/development/python-modules/pykde4/default.nix2
-rw-r--r--pkgs/development/python-modules/solo-python/default.nix25
-rw-r--r--pkgs/development/python-modules/spacy/default.nix10
-rw-r--r--pkgs/development/python-modules/sqlalchemy-utils/default.nix4
-rw-r--r--pkgs/development/python-modules/srsly/default.nix4
-rw-r--r--pkgs/development/python-modules/thinc/default.nix9
-rw-r--r--pkgs/development/python-modules/wasabi/default.nix4
-rw-r--r--pkgs/development/python-modules/xdis/default.nix4
-rw-r--r--pkgs/development/ruby-modules/with-packages/default.nix2
-rw-r--r--pkgs/development/tools/clj-kondo/default.nix6
-rw-r--r--pkgs/development/tools/ocaml/ocp-indent/default.nix4
-rw-r--r--pkgs/development/tools/rust/cargo-geiger/default.nix39
-rw-r--r--pkgs/development/tools/vala-lint/default.nix51
-rw-r--r--pkgs/development/tools/yq/default.nix4
-rw-r--r--pkgs/development/web/nodejs/nodejs.nix26
-rw-r--r--pkgs/games/frozen-bubble/default.nix25
-rw-r--r--pkgs/games/frozen-bubble/fix-compilation.patch33
-rw-r--r--pkgs/games/openjk/default.nix6
-rw-r--r--pkgs/games/openmw/tes3mp.nix12
-rw-r--r--pkgs/games/openxray/default.nix4
-rw-r--r--pkgs/games/quakespasm/vulkan.nix5
-rw-r--r--pkgs/games/sdlmame/default.nix42
-rw-r--r--pkgs/misc/emulators/mame/default.nix59
-rw-r--r--pkgs/misc/emulators/mess/default.nix49
-rw-r--r--pkgs/misc/emulators/retroarch/cores.nix660
-rw-r--r--pkgs/misc/vscode-extensions/cpptools/default.nix4
-rw-r--r--pkgs/os-specific/linux/brillo/default.nix34
-rw-r--r--pkgs/os-specific/linux/brillo/udev-rule.patch13
-rw-r--r--pkgs/os-specific/linux/digimend/default.nix45
-rw-r--r--pkgs/os-specific/linux/kernel/linux-testing.nix4
-rw-r--r--pkgs/os-specific/linux/kmod/aggregator.nix2
-rw-r--r--pkgs/servers/amqp/rabbitmq-server/default.nix4
-rw-r--r--pkgs/servers/search/groonga/default.nix4
-rw-r--r--pkgs/servers/search/solr/8.x.nix4
-rw-r--r--pkgs/servers/shellinabox/default.nix15
-rw-r--r--pkgs/servers/sql/postgresql/ext/timescaledb.nix6
-rw-r--r--pkgs/servers/web-apps/dokuwiki/default.nix26
-rw-r--r--pkgs/shells/zsh/zsh-history-substring-search/default.nix4
-rw-r--r--pkgs/stdenv/generic/check-meta.nix6
-rw-r--r--pkgs/stdenv/linux/make-bootstrap-tools.nix29
-rw-r--r--pkgs/tools/X11/wpgtk/default.nix4
-rw-r--r--pkgs/tools/audio/video2midi/default.nix4
-rw-r--r--pkgs/tools/filesystems/sshfs-fuse/default.nix2
-rw-r--r--pkgs/tools/misc/dust/default.nix6
-rw-r--r--pkgs/tools/networking/acme-client/default.nix28
-rw-r--r--pkgs/tools/networking/phodav/default.nix14
-rw-r--r--pkgs/tools/security/gnupg-pkcs11-scd/default.nix33
-rw-r--r--pkgs/tools/security/keybase/default.nix17
-rw-r--r--pkgs/tools/security/keybase/fix-paths-kbfs.patch48
-rw-r--r--pkgs/tools/security/keybase/fix-paths-keybase.patch16
-rw-r--r--pkgs/tools/security/keybase/gui.nix6
-rw-r--r--pkgs/tools/security/keybase/kbfs.nix9
-rw-r--r--pkgs/tools/security/theharvester/default.nix44
-rw-r--r--pkgs/tools/system/tre-command/default.nix24
-rw-r--r--pkgs/top-level/aliases.nix2
-rw-r--r--pkgs/top-level/all-packages.nix84
-rw-r--r--pkgs/top-level/perl-packages.nix72
-rw-r--r--pkgs/top-level/python-packages.nix13
210 files changed, 5455 insertions, 1495 deletions
diff --git a/lib/modules.nix b/lib/modules.nix
index 71672c7d112..44db77b5d1c 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -326,6 +326,8 @@ rec {
 
       # The value with a check that it is defined
       valueDefined = if res.isDefined then res.mergedValue else
+        # (nixos-option detects this specific error message and gives it special
+        # handling.  If changed here, please change it there too.)
         throw "The option `${showOption loc}' is used but not defined.";
 
       # Apply the 'apply' function to the merged value. This allows options to
diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix
index 854b033f056..13a2713896a 100644
--- a/maintainers/maintainer-list.nix
+++ b/maintainers/maintainer-list.nix
@@ -1194,6 +1194,12 @@
     githubId = 30435868;
     name = "Okina Matara";
   };
+  chkno = {
+    email = "chuck@intelligence.org";
+    github = "chkno";
+    githubId = 1118859;
+    name = "Scott Worley";
+  };
   choochootrain = {
     email = "hurshal@imap.cc";
     github = "choochootrain";
@@ -1563,6 +1569,12 @@
     githubId = 14032;
     name = "Daniel Brockman";
   };
+  dduan = {
+    email = "daniel@duan.ca";
+    github = "dduan";
+    githubId = 75067;
+    name = "Daniel Duan";
+  };
   deepfire = {
     email = "_deepfire@feelingofgreen.ru";
     github = "deepfire";
@@ -2030,6 +2042,12 @@
       github = "ericnorris";
       githubId = 1906605;
   };
+  Enteee = {
+    email = "nix@duckpond.ch";
+    github = "Enteee";
+    githubid = 5493775;
+    name = "Ente";
+  };
   enzime = {
     email = "enzime@users.noreply.github.com";
     github = "enzime";
diff --git a/nixos/doc/manual/development/running-nixos-tests-interactively.xml b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
index e390d62fde2..ea3ba0e4bf7 100644
--- a/nixos/doc/manual/development/running-nixos-tests-interactively.xml
+++ b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
@@ -14,14 +14,14 @@
 starting VDE switch for network 1
 <prompt>&gt;</prompt>
 </screen>
-  You can then take any Perl statement, e.g.
+  You can then take any Python statement, e.g.
 <screen>
-<prompt>&gt;</prompt> startAll
-<prompt>&gt;</prompt> testScript
-<prompt>&gt;</prompt> $machine->succeed("touch /tmp/foo")
-<prompt>&gt;</prompt> print($machine->succeed("pwd")) # Show stdout of command
+<prompt>&gt;</prompt> start_all()
+<prompt>&gt;</prompt> test_script()
+<prompt>&gt;</prompt> machine.succeed("touch /tmp/foo")
+<prompt>&gt;</prompt> print(machine.succeed("pwd")) # Show stdout of command
 </screen>
-  The function <command>testScript</command> executes the entire test script
+  The function <command>test_script</command> executes the entire test script
   and drops you back into the test driver command line upon its completion.
   This allows you to inspect the state of the VMs after the test (e.g. to debug
   the test script).
diff --git a/nixos/doc/manual/development/writing-nixos-tests.xml b/nixos/doc/manual/development/writing-nixos-tests.xml
index 6be2d0a4d23..24efd2e3273 100644
--- a/nixos/doc/manual/development/writing-nixos-tests.xml
+++ b/nixos/doc/manual/development/writing-nixos-tests.xml
@@ -8,7 +8,7 @@
  <para>
   A NixOS test is a Nix expression that has the following structure:
 <programlisting>
-import ./make-test.nix {
+import ./make-test-python.nix {
 
   # Either the configuration of a single machine:
   machine =
@@ -27,11 +27,11 @@ import ./make-test.nix {
 
   testScript =
     ''
-      <replaceable>Perl code…</replaceable>
+      <replaceable>Python code…</replaceable>
     '';
 }
 </programlisting>
-  The attribute <literal>testScript</literal> is a bit of Perl code that
+  The attribute <literal>testScript</literal> is a bit of Python code that
   executes the test (described below). During the test, it will start one or
   more virtual machines, the configuration of which is described by the
   attribute <literal>machine</literal> (if you need only one machine in your
@@ -96,26 +96,27 @@ xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualis
  </para>
 
  <para>
-  The test script is a sequence of Perl statements that perform various
+  The test script is a sequence of Python statements that perform various
   actions, such as starting VMs, executing commands in the VMs, and so on. Each
   virtual machine is represented as an object stored in the variable
-  <literal>$<replaceable>name</replaceable></literal>, where
-  <replaceable>name</replaceable> is the identifier of the machine (which is
-  just <literal>machine</literal> if you didn’t specify multiple machines
-  using the <literal>nodes</literal> attribute). For instance, the following
-  starts the machine, waits until it has finished booting, then executes a
-  command and checks that the output is more-or-less correct:
+  <literal><replaceable>name</replaceable></literal> if this is also the
+  identifier of the machine in the declarative config.
+  If you didn't specify multiple machines using the <literal>nodes</literal>
+  attribute, it is just <literal>machine</literal>.
+  The following example starts the machine, waits until it has finished booting,
+  then executes a command and checks that the output is more-or-less correct:
 <programlisting>
-$machine->start;
-$machine->waitForUnit("default.target");
-$machine->succeed("uname") =~ /Linux/ or die;
+machine.start()
+machine.wait_for_unit("default.target")
+if not "Linux" in machine.succeed("uname"):
+  raise Exception("Wrong OS")
 </programlisting>
   The first line is actually unnecessary; machines are implicitly started when
-  you first execute an action on them (such as <literal>waitForUnit</literal>
+  you first execute an action on them (such as <literal>wait_for_unit</literal>
   or <literal>succeed</literal>). If you have multiple machines, you can speed
   up the test by starting them in parallel:
 <programlisting>
-startAll;
+start_all()
 </programlisting>
  </para>
 
@@ -187,7 +188,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>getScreenText</methodname>
+     <methodname>get_screen_text</methodname>
     </term>
     <listitem>
      <para>
@@ -204,7 +205,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>sendMonitorCommand</methodname>
+     <methodname>send_monitor_command</methodname>
     </term>
     <listitem>
      <para>
@@ -215,23 +216,23 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>sendKeys</methodname>
+     <methodname>send_keys</methodname>
     </term>
     <listitem>
      <para>
       Simulate pressing keys on the virtual keyboard, e.g.,
-      <literal>sendKeys("ctrl-alt-delete")</literal>.
+      <literal>send_keys("ctrl-alt-delete")</literal>.
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>sendChars</methodname>
+     <methodname>send_chars</methodname>
     </term>
     <listitem>
      <para>
       Simulate typing a sequence of characters on the virtual keyboard, e.g.,
-      <literal>sendKeys("foobar\n")</literal> will type the string
+      <literal>send_keys("foobar\n")</literal> will type the string
       <literal>foobar</literal> followed by the Enter key.
      </para>
     </listitem>
@@ -272,7 +273,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitUntilSucceeds</methodname>
+     <methodname>wait_until_succeeds</methodname>
     </term>
     <listitem>
      <para>
@@ -282,7 +283,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitUntilFails</methodname>
+     <methodname>wait_until_fails</methodname>
     </term>
     <listitem>
      <para>
@@ -292,7 +293,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForUnit</methodname>
+     <methodname>wait_for_unit</methodname>
     </term>
     <listitem>
      <para>
@@ -302,7 +303,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForFile</methodname>
+     <methodname>wait_for_file</methodname>
     </term>
     <listitem>
      <para>
@@ -312,7 +313,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForOpenPort</methodname>
+     <methodname>wait_for_open_port</methodname>
     </term>
     <listitem>
      <para>
@@ -323,7 +324,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForClosedPort</methodname>
+     <methodname>wait_for_closed_port</methodname>
     </term>
     <listitem>
      <para>
@@ -333,7 +334,7 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForX</methodname>
+     <methodname>wait_for_x</methodname>
     </term>
     <listitem>
      <para>
@@ -343,13 +344,13 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForText</methodname>
+     <methodname>wait_for_text</methodname>
     </term>
     <listitem>
      <para>
       Wait until the supplied regular expressions matches the textual contents
       of the screen by using optical character recognition (see
-      <methodname>getScreenText</methodname>).
+      <methodname>get_screen_text</methodname>).
      </para>
      <note>
       <para>
@@ -361,23 +362,23 @@ startAll;
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>waitForWindow</methodname>
+     <methodname>wait_for_window</methodname>
     </term>
     <listitem>
      <para>
       Wait until an X11 window has appeared whose name matches the given
-      regular expression, e.g., <literal>waitForWindow(qr/Terminal/)</literal>.
+      regular expression, e.g., <literal>wait_for_window("Terminal")</literal>.
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>
-     <methodname>copyFileFromHost</methodname>
+     <methodname>copy_file_from_host</methodname>
     </term>
     <listitem>
      <para>
       Copies a file from host to machine, e.g.,
-      <literal>copyFileFromHost("myfile", "/etc/my/important/file")</literal>.
+      <literal>copy_file_from_host("myfile", "/etc/my/important/file")</literal>.
      </para>
      <para>
       The first argument is the file on the host. The file needs to be
@@ -397,8 +398,8 @@ startAll;
      </para>
      <para>
 <programlisting>
-$machine->systemctl("list-jobs --no-pager"); // runs `systemctl list-jobs --no-pager`
-$machine->systemctl("list-jobs --no-pager", "any-user"); // spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager`
+machine.systemctl("list-jobs --no-pager") # runs `systemctl list-jobs --no-pager`
+machine.systemctl("list-jobs --no-pager", "any-user") # spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager`
 </programlisting>
      </para>
     </listitem>
@@ -408,14 +409,14 @@ $machine->systemctl("list-jobs --no-pager", "any-user"); // spawns a shell for `
 
  <para>
   To test user units declared by <literal>systemd.user.services</literal> the
-  optional <literal>$user</literal> argument can be used:
+  optional <literal>user</literal> argument can be used:
 <programlisting>
-$machine->start;
-$machine->waitForX;
-$machine->waitForUnit("xautolock.service", "x-session-user");
+machine.start()
+machine.wait_for_x()
+machine.wait_for_unit("xautolock.service", "x-session-user")
 </programlisting>
-  This applies to <literal>systemctl</literal>, <literal>getUnitInfo</literal>,
-  <literal>waitForUnit</literal>, <literal>startJob</literal> and
-  <literal>stopJob</literal>.
+  This applies to <literal>systemctl</literal>, <literal>get_unit_info</literal>,
+  <literal>wait_for_unit</literal>, <literal>start_job</literal> and
+  <literal>stop_job</literal>.
  </para>
 </section>
diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml
index 81e3739b3be..beabf020c92 100644
--- a/nixos/doc/manual/man-nixos-option.xml
+++ b/nixos/doc/manual/man-nixos-option.xml
@@ -19,14 +19,10 @@
    </arg>
 
    <arg>
-    <option>--verbose</option>
+    <option>--all</option>
    </arg>
 
    <arg>
-    <option>--xml</option>
-   </arg>
-
-   <arg choice="plain">
     <replaceable>option.name</replaceable>
    </arg>
   </cmdsynopsis>
@@ -62,22 +58,11 @@
    </varlistentry>
    <varlistentry>
     <term>
-     <option>--verbose</option>
-    </term>
-    <listitem>
-     <para>
-      This option enables verbose mode, which currently is just the Bash
-      <command>set</command> <option>-x</option> debug mode.
-     </para>
-    </listitem>
-   </varlistentry>
-   <varlistentry>
-    <term>
-     <option>--xml</option>
+     <option>--all</option>
     </term>
     <listitem>
      <para>
-      This option causes the output to be rendered as XML.
+      Print the values of all options.
      </para>
     </listitem>
    </varlistentry>
diff --git a/nixos/doc/manual/release-notes/rl-2003.xml b/nixos/doc/manual/release-notes/rl-2003.xml
index f001a18b1c1..72766f16eb9 100644
--- a/nixos/doc/manual/release-notes/rl-2003.xml
+++ b/nixos/doc/manual/release-notes/rl-2003.xml
@@ -49,6 +49,12 @@
        zfs as soon as any zfs mountpoint is configured in <varname>fileSystems</varname>.
      </para>
    </listitem>
+   <listitem>
+    <para>
+      <command>nixos-option</command> has been rewritten in C++, speeding it up, improving correctness,
+      and adding a <option>--all</option> option which prints all options and their values.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
diff --git a/nixos/lib/test-driver/test-driver.py b/nixos/lib/test-driver/test-driver.py
new file mode 100644
index 00000000000..45b7e229a5c
--- /dev/null
+++ b/nixos/lib/test-driver/test-driver.py
@@ -0,0 +1,758 @@
+#! /somewhere/python3
+
+from contextlib import contextmanager
+from xml.sax.saxutils import XMLGenerator
+import _thread
+import atexit
+import os
+import pty
+import queue
+import re
+import shutil
+import socket
+import subprocess
+import sys
+import tempfile
+import time
+import unicodedata
+import ptpython.repl
+
+CHAR_TO_KEY = {
+    "A": "shift-a",
+    "N": "shift-n",
+    "-": "0x0C",
+    "_": "shift-0x0C",
+    "B": "shift-b",
+    "O": "shift-o",
+    "=": "0x0D",
+    "+": "shift-0x0D",
+    "C": "shift-c",
+    "P": "shift-p",
+    "[": "0x1A",
+    "{": "shift-0x1A",
+    "D": "shift-d",
+    "Q": "shift-q",
+    "]": "0x1B",
+    "}": "shift-0x1B",
+    "E": "shift-e",
+    "R": "shift-r",
+    ";": "0x27",
+    ":": "shift-0x27",
+    "F": "shift-f",
+    "S": "shift-s",
+    "'": "0x28",
+    '"': "shift-0x28",
+    "G": "shift-g",
+    "T": "shift-t",
+    "`": "0x29",
+    "~": "shift-0x29",
+    "H": "shift-h",
+    "U": "shift-u",
+    "\\": "0x2B",
+    "|": "shift-0x2B",
+    "I": "shift-i",
+    "V": "shift-v",
+    ",": "0x33",
+    "<": "shift-0x33",
+    "J": "shift-j",
+    "W": "shift-w",
+    ".": "0x34",
+    ">": "shift-0x34",
+    "K": "shift-k",
+    "X": "shift-x",
+    "/": "0x35",
+    "?": "shift-0x35",
+    "L": "shift-l",
+    "Y": "shift-y",
+    " ": "spc",
+    "M": "shift-m",
+    "Z": "shift-z",
+    "\n": "ret",
+    "!": "shift-0x02",
+    "@": "shift-0x03",
+    "#": "shift-0x04",
+    "$": "shift-0x05",
+    "%": "shift-0x06",
+    "^": "shift-0x07",
+    "&": "shift-0x08",
+    "*": "shift-0x09",
+    "(": "shift-0x0A",
+    ")": "shift-0x0B",
+}
+
+
+def eprint(*args, **kwargs):
+    print(*args, file=sys.stderr, **kwargs)
+
+
+def create_vlan(vlan_nr):
+    global log
+    log.log("starting VDE switch for network {}".format(vlan_nr))
+    vde_socket = os.path.abspath("./vde{}.ctl".format(vlan_nr))
+    pty_master, pty_slave = pty.openpty()
+    vde_process = subprocess.Popen(
+        ["vde_switch", "-s", vde_socket, "--dirmode", "0777"],
+        bufsize=1,
+        stdin=pty_slave,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        shell=False,
+    )
+    fd = os.fdopen(pty_master, "w")
+    fd.write("version\n")
+    # TODO: perl version checks if this can be read from
+    # an if not, dies. we could hang here forever. Fix it.
+    vde_process.stdout.readline()
+    if not os.path.exists(os.path.join(vde_socket, "ctl")):
+        raise Exception("cannot start vde_switch")
+
+    return (vlan_nr, vde_socket, vde_process, fd)
+
+
+def retry(fn):
+    """Call the given function repeatedly, with 1 second intervals,
+    until it returns True or a timeout is reached.
+    """
+
+    for _ in range(900):
+        if fn(False):
+            return
+        time.sleep(1)
+
+    if not fn(True):
+        raise Exception("action timed out")
+
+
+class Logger:
+    def __init__(self):
+        self.logfile = os.environ.get("LOGFILE", "/dev/null")
+        self.logfile_handle = open(self.logfile, "wb")
+        self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
+        self.queue = queue.Queue(1000)
+
+        self.xml.startDocument()
+        self.xml.startElement("logfile", attrs={})
+
+    def close(self):
+        self.xml.endElement("logfile")
+        self.xml.endDocument()
+        self.logfile_handle.close()
+
+    def sanitise(self, message):
+        return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
+
+    def maybe_prefix(self, message, attributes):
+        if "machine" in attributes:
+            return "{}: {}".format(attributes["machine"], message)
+        return message
+
+    def log_line(self, message, attributes):
+        self.xml.startElement("line", attributes)
+        self.xml.characters(message)
+        self.xml.endElement("line")
+
+    def log(self, message, attributes={}):
+        eprint(self.maybe_prefix(message, attributes))
+        self.drain_log_queue()
+        self.log_line(message, attributes)
+
+    def enqueue(self, message):
+        self.queue.put(message)
+
+    def drain_log_queue(self):
+        try:
+            while True:
+                item = self.queue.get_nowait()
+                attributes = {"machine": item["machine"], "type": "serial"}
+                self.log_line(self.sanitise(item["msg"]), attributes)
+        except queue.Empty:
+            pass
+
+    @contextmanager
+    def nested(self, message, attributes={}):
+        eprint(self.maybe_prefix(message, attributes))
+
+        self.xml.startElement("nest", attrs={})
+        self.xml.startElement("head", attributes)
+        self.xml.characters(message)
+        self.xml.endElement("head")
+
+        tic = time.time()
+        self.drain_log_queue()
+        yield
+        self.drain_log_queue()
+        toc = time.time()
+        self.log("({:.2f} seconds)".format(toc - tic))
+
+        self.xml.endElement("nest")
+
+
+class Machine:
+    def __init__(self, args):
+        if "name" in args:
+            self.name = args["name"]
+        else:
+            self.name = "machine"
+            try:
+                cmd = args["startCommand"]
+                self.name = re.search("run-(.+)-vm$", cmd).group(1)
+            except KeyError:
+                pass
+            except AttributeError:
+                pass
+
+        self.script = args.get("startCommand", self.create_startcommand(args))
+
+        tmp_dir = os.environ.get("TMPDIR", tempfile.gettempdir())
+
+        def create_dir(name):
+            path = os.path.join(tmp_dir, name)
+            os.makedirs(path, mode=0o700, exist_ok=True)
+            return path
+
+        self.state_dir = create_dir("vm-state-{}".format(self.name))
+        self.shared_dir = create_dir("xchg-shared")
+
+        self.booted = False
+        self.connected = False
+        self.pid = None
+        self.socket = None
+        self.monitor = None
+        self.logger = args["log"]
+        self.allow_reboot = args.get("allowReboot", False)
+
+    @staticmethod
+    def create_startcommand(args):
+        net_backend = "-netdev user,id=net0"
+        net_frontend = "-device virtio-net-pci,netdev=net0"
+
+        if "netBackendArgs" in args:
+            net_backend += "," + args["netBackendArgs"]
+
+        if "netFrontendArgs" in args:
+            net_frontend += "," + args["netFrontendArgs"]
+
+        start_command = (
+            "qemu-kvm -m 384 " + net_backend + " " + net_frontend + " $QEMU_OPTS "
+        )
+
+        if "hda" in args:
+            hda_path = os.path.abspath(args["hda"])
+            if args.get("hdaInterface", "") == "scsi":
+                start_command += (
+                    "-drive id=hda,file="
+                    + hda_path
+                    + ",werror=report,if=none "
+                    + "-device scsi-hd,drive=hda "
+                )
+            else:
+                start_command += (
+                    "-drive file="
+                    + hda_path
+                    + ",if="
+                    + args["hdaInterface"]
+                    + ",werror=report "
+                )
+
+        if "cdrom" in args:
+            start_command += "-cdrom " + args["cdrom"] + " "
+
+        if "usb" in args:
+            start_command += (
+                "-device piix3-usb-uhci -drive "
+                + "id=usbdisk,file="
+                + args["usb"]
+                + ",if=none,readonly "
+                + "-device usb-storage,drive=usbdisk "
+            )
+        if "bios" in args:
+            start_command += "-bios " + args["bios"] + " "
+
+        start_command += args.get("qemuFlags", "")
+
+        return start_command
+
+    def is_up(self):
+        return self.booted and self.connected
+
+    def log(self, msg):
+        self.logger.log(msg, {"machine": self.name})
+
+    def nested(self, msg, attrs={}):
+        my_attrs = {"machine": self.name}
+        my_attrs.update(attrs)
+        return self.logger.nested(msg, my_attrs)
+
+    def wait_for_monitor_prompt(self):
+        while True:
+            answer = self.monitor.recv(1024).decode()
+            if answer.endswith("(qemu) "):
+                return answer
+
+    def send_monitor_command(self, command):
+        message = ("{}\n".format(command)).encode()
+        self.log("sending monitor command: {}".format(command))
+        self.monitor.send(message)
+        return self.wait_for_monitor_prompt()
+
+    def wait_for_unit(self, unit, user=None):
+        while True:
+            info = self.get_unit_info(unit, user)
+            state = info["ActiveState"]
+            if state == "failed":
+                raise Exception('unit "{}" reached state "{}"'.format(unit, state))
+
+            if state == "inactive":
+                status, jobs = self.systemctl("list-jobs --full 2>&1", user)
+                if "No jobs" in jobs:
+                    info = self.get_unit_info(unit)
+                    if info["ActiveState"] == state:
+                        raise Exception(
+                            (
+                                'unit "{}" is inactive and there ' "are no pending jobs"
+                            ).format(unit)
+                        )
+            if state == "active":
+                return True
+
+    def get_unit_info(self, unit, user=None):
+        status, lines = self.systemctl('--no-pager show "{}"'.format(unit), user)
+        if status != 0:
+            return None
+
+        line_pattern = re.compile(r"^([^=]+)=(.*)$")
+
+        def tuple_from_line(line):
+            match = line_pattern.match(line)
+            return match[1], match[2]
+
+        return dict(
+            tuple_from_line(line)
+            for line in lines.split("\n")
+            if line_pattern.match(line)
+        )
+
+    def systemctl(self, q, user=None):
+        if user is not None:
+            q = q.replace("'", "\\'")
+            return self.execute(
+                (
+                    "su -l {} -c "
+                    "$'XDG_RUNTIME_DIR=/run/user/`id -u` "
+                    "systemctl --user {}'"
+                ).format(user, q)
+            )
+        return self.execute("systemctl {}".format(q))
+
+    def execute(self, command):
+        self.connect()
+
+        out_command = "( {} ); echo '|!EOF' $?\n".format(command)
+        self.shell.send(out_command.encode())
+
+        output = ""
+        status_code_pattern = re.compile(r"(.*)\|\!EOF\s+(\d+)")
+
+        while True:
+            chunk = self.shell.recv(4096).decode()
+            match = status_code_pattern.match(chunk)
+            if match:
+                output += match[1]
+                status_code = int(match[2])
+                return (status_code, output)
+            output += chunk
+
+    def succeed(self, *commands):
+        """Execute each command and check that it succeeds."""
+        for command in commands:
+            with self.nested("must succeed: {}".format(command)):
+                status, output = self.execute(command)
+                if status != 0:
+                    self.log("output: {}".format(output))
+                    raise Exception(
+                        "command `{}` failed (exit code {})".format(command, status)
+                    )
+                return output
+
+    def fail(self, *commands):
+        """Execute each command and check that it fails."""
+        for command in commands:
+            with self.nested("must fail: {}".format(command)):
+                status, output = self.execute(command)
+                if status == 0:
+                    raise Exception(
+                        "command `{}` unexpectedly succeeded".format(command)
+                    )
+
+    def wait_until_succeeds(self, command):
+        with self.nested("waiting for success: {}".format(command)):
+            while True:
+                status, output = self.execute(command)
+                if status == 0:
+                    return output
+
+    def wait_until_fails(self, command):
+        with self.nested("waiting for failure: {}".format(command)):
+            while True:
+                status, output = self.execute(command)
+                if status != 0:
+                    return output
+
+    def wait_for_shutdown(self):
+        if not self.booted:
+            return
+
+        with self.nested("waiting for the VM to power off"):
+            sys.stdout.flush()
+            self.process.wait()
+
+            self.pid = None
+            self.booted = False
+            self.connected = False
+
+    def get_tty_text(self, tty):
+        status, output = self.execute(
+            "fold -w$(stty -F /dev/tty{0} size | "
+            "awk '{{print $2}}') /dev/vcs{0}".format(tty)
+        )
+        return output
+
+    def wait_until_tty_matches(self, tty, regexp):
+        matcher = re.compile(regexp)
+        with self.nested("waiting for {} to appear on tty {}".format(regexp, tty)):
+            while True:
+                text = self.get_tty_text(tty)
+                if len(matcher.findall(text)) > 0:
+                    return True
+
+    def send_chars(self, chars):
+        with self.nested("sending keys ‘{}‘".format(chars)):
+            for char in chars:
+                self.send_key(char)
+
+    def wait_for_file(self, filename):
+        with self.nested("waiting for file ‘{}‘".format(filename)):
+            while True:
+                status, _ = self.execute("test -e {}".format(filename))
+                if status == 0:
+                    return True
+
+    def wait_for_open_port(self, port):
+        def port_is_open(_):
+            status, _ = self.execute("nc -z localhost {}".format(port))
+            return status == 0
+
+        with self.nested("waiting for TCP port {}".format(port)):
+            retry(port_is_open)
+
+    def wait_for_closed_port(self, port):
+        def port_is_closed(_):
+            status, _ = self.execute("nc -z localhost {}".format(port))
+            return status != 0
+
+        retry(port_is_closed)
+
+    def start_job(self, jobname, user=None):
+        return self.systemctl("start {}".format(jobname), user)
+
+    def stop_job(self, jobname, user=None):
+        return self.systemctl("stop {}".format(jobname), user)
+
+    def wait_for_job(self, jobname):
+        return self.wait_for_unit(jobname)
+
+    def connect(self):
+        if self.connected:
+            return
+
+        with self.nested("waiting for the VM to finish booting"):
+            self.start()
+
+            tic = time.time()
+            self.shell.recv(1024)
+            # TODO: Timeout
+            toc = time.time()
+
+            self.log("connected to guest root shell")
+            self.log("(connecting took {:.2f} seconds)".format(toc - tic))
+            self.connected = True
+
+    def screenshot(self, filename):
+        out_dir = os.environ.get("out", os.getcwd())
+        word_pattern = re.compile(r"^\w+$")
+        if word_pattern.match(filename):
+            filename = os.path.join(out_dir, "{}.png".format(filename))
+        tmp = "{}.ppm".format(filename)
+
+        with self.nested(
+            "making screenshot {}".format(filename),
+            {"image": os.path.basename(filename)},
+        ):
+            self.send_monitor_command("screendump {}".format(tmp))
+            ret = subprocess.run("pnmtopng {} > {}".format(tmp, filename), shell=True)
+            os.unlink(tmp)
+            if ret.returncode != 0:
+                raise Exception("Cannot convert screenshot")
+
+    def get_screen_text(self):
+        if shutil.which("tesseract") is None:
+            raise Exception("get_screen_text used but enableOCR is false")
+
+        magick_args = (
+            "-filter Catrom -density 72 -resample 300 "
+            + "-contrast -normalize -despeckle -type grayscale "
+            + "-sharpen 1 -posterize 3 -negate -gamma 100 "
+            + "-blur 1x65535"
+        )
+
+        tess_args = "-c debug_file=/dev/null --psm 11 --oem 2"
+
+        with self.nested("performing optical character recognition"):
+            with tempfile.NamedTemporaryFile() as tmpin:
+                self.send_monitor_command("screendump {}".format(tmpin.name))
+
+                cmd = "convert {} {} tiff:- | tesseract - - {}".format(
+                    magick_args, tmpin.name, tess_args
+                )
+                ret = subprocess.run(cmd, shell=True, capture_output=True)
+                if ret.returncode != 0:
+                    raise Exception(
+                        "OCR failed with exit code {}".format(ret.returncode)
+                    )
+
+                return ret.stdout.decode("utf-8")
+
+    def wait_for_text(self, regex):
+        def screen_matches(last):
+            text = self.get_screen_text()
+            m = re.search(regex, text)
+
+            if last and not m:
+                self.log("Last OCR attempt failed. Text was: {}".format(text))
+
+            return m
+
+        with self.nested("waiting for {} to appear on screen".format(regex)):
+            retry(screen_matches)
+
+    def send_key(self, key):
+        key = CHAR_TO_KEY.get(key, key)
+        self.send_monitor_command("sendkey {}".format(key))
+
+    def start(self):
+        if self.booted:
+            return
+
+        self.log("starting vm")
+
+        def create_socket(path):
+            if os.path.exists(path):
+                os.unlink(path)
+            s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM)
+            s.bind(path)
+            s.listen(1)
+            return s
+
+        monitor_path = os.path.join(self.state_dir, "monitor")
+        self.monitor_socket = create_socket(monitor_path)
+
+        shell_path = os.path.join(self.state_dir, "shell")
+        self.shell_socket = create_socket(shell_path)
+
+        qemu_options = (
+            " ".join(
+                [
+                    "" if self.allow_reboot else "-no-reboot",
+                    "-monitor unix:{}".format(monitor_path),
+                    "-chardev socket,id=shell,path={}".format(shell_path),
+                    "-device virtio-serial",
+                    "-device virtconsole,chardev=shell",
+                    "-device virtio-rng-pci",
+                    "-serial stdio" if "DISPLAY" in os.environ else "-nographic",
+                ]
+            )
+            + " "
+            + os.environ.get("QEMU_OPTS", "")
+        )
+
+        environment = {
+            "QEMU_OPTS": qemu_options,
+            "SHARED_DIR": self.shared_dir,
+            "USE_TMPDIR": "1",
+        }
+        environment.update(dict(os.environ))
+
+        self.process = subprocess.Popen(
+            self.script,
+            bufsize=1,
+            stdin=subprocess.DEVNULL,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+            shell=False,
+            cwd=self.state_dir,
+            env=environment,
+        )
+        self.monitor, _ = self.monitor_socket.accept()
+        self.shell, _ = self.shell_socket.accept()
+
+        def process_serial_output():
+            for line in self.process.stdout:
+                line = line.decode().replace("\r", "").rstrip()
+                eprint("{} # {}".format(self.name, line))
+                self.logger.enqueue({"msg": line, "machine": self.name})
+
+        _thread.start_new_thread(process_serial_output, ())
+
+        self.wait_for_monitor_prompt()
+
+        self.pid = self.process.pid
+        self.booted = True
+
+        self.log("QEMU running (pid {})".format(self.pid))
+
+    def shutdown(self):
+        if self.booted:
+            return
+
+        self.shell.send("poweroff\n".encode())
+        self.wait_for_shutdown()
+
+    def crash(self):
+        if self.booted:
+            return
+
+        self.log("forced crash")
+        self.send_monitor_command("quit")
+        self.wait_for_shutdown()
+
+    def wait_for_x(self):
+        """Wait until it is possible to connect to the X server.  Note that
+        testing the existence of /tmp/.X11-unix/X0 is insufficient.
+        """
+        with self.nested("waiting for the X11 server"):
+            while True:
+                cmd = (
+                    "journalctl -b SYSLOG_IDENTIFIER=systemd | "
+                    + 'grep "Reached target Current graphical"'
+                )
+                status, _ = self.execute(cmd)
+                if status != 0:
+                    continue
+                status, _ = self.execute("[ -e /tmp/.X11-unix/X0 ]")
+                if status == 0:
+                    return
+
+    def sleep(self, secs):
+        time.sleep(secs)
+
+    def block(self):
+        """Make the machine unreachable by shutting down eth1 (the multicast
+        interface used to talk to the other VMs).  We keep eth0 up so that
+        the test driver can continue to talk to the machine.
+        """
+        self.send_monitor_command("set_link virtio-net-pci.1 off")
+
+    def unblock(self):
+        """Make the machine reachable.
+        """
+        self.send_monitor_command("set_link virtio-net-pci.1 on")
+
+
+def create_machine(args):
+    global log
+    args["log"] = log
+    args["redirectSerial"] = os.environ.get("USE_SERIAL", "0") == "1"
+    return Machine(args)
+
+
+def start_all():
+    with log.nested("starting all VMs"):
+        for machine in machines:
+            machine.start()
+
+
+def join_all():
+    with log.nested("waiting for all VMs to finish"):
+        for machine in machines:
+            machine.wait_for_shutdown()
+
+
+def test_script():
+    exec(os.environ["testScript"])
+
+
+def run_tests():
+    tests = os.environ.get("tests", None)
+    if tests is not None:
+        with log.nested("running the VM test script"):
+            try:
+                exec(tests)
+            except Exception as e:
+                eprint("error: {}".format(str(e)))
+                sys.exit(1)
+    else:
+        ptpython.repl.embed(locals(), globals())
+
+    # TODO: Collect coverage data
+
+    for machine in machines:
+        if machine.is_up():
+            machine.execute("sync")
+
+    if nr_tests != 0:
+        log.log("{} out of {} tests succeeded".format(nr_succeeded, nr_tests))
+
+
+@contextmanager
+def subtest(name):
+    global nr_tests
+    global nr_succeeded
+
+    with log.nested(name):
+        nr_tests += 1
+        try:
+            yield
+            nr_succeeded += 1
+            return True
+        except Exception as e:
+            log.log("error: {}".format(str(e)))
+
+    return False
+
+
+if __name__ == "__main__":
+    global log
+    log = Logger()
+
+    vlan_nrs = list(dict.fromkeys(os.environ["VLANS"].split()))
+    vde_sockets = [create_vlan(v) for v in vlan_nrs]
+    for nr, vde_socket, _, _ in vde_sockets:
+        os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
+
+    vm_scripts = sys.argv[1:]
+    machines = [create_machine({"startCommand": s}) for s in vm_scripts]
+    machine_eval = [
+        "{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
+    ]
+    exec("\n".join(machine_eval))
+
+    nr_tests = 0
+    nr_succeeded = 0
+
+    @atexit.register
+    def clean_up():
+        with log.nested("cleaning up"):
+            for machine in machines:
+                if machine.pid is None:
+                    continue
+                log.log("killing {} (pid {})".format(machine.name, machine.pid))
+                machine.process.kill()
+
+            for _, _, process, _ in vde_sockets:
+                process.kill()
+        log.close()
+
+    tic = time.time()
+    run_tests()
+    toc = time.time()
+    print("test script finished in {:.2f}s".format(toc - tic))
diff --git a/nixos/lib/testing-python.nix b/nixos/lib/testing-python.nix
new file mode 100644
index 00000000000..21f6172e967
--- /dev/null
+++ b/nixos/lib/testing-python.nix
@@ -0,0 +1,279 @@
+{ system
+, pkgs ? import ../.. { inherit system config; }
+  # Use a minimal kernel?
+, minimal ? false
+  # Ignored
+, config ? {}
+  # Modules to add to each VM
+, extraConfigurations ? [] }:
+
+with import ./build-vms.nix { inherit system pkgs minimal extraConfigurations; };
+with pkgs;
+
+let
+  jquery-ui = callPackage ./testing/jquery-ui.nix { };
+  jquery = callPackage ./testing/jquery.nix { };
+
+in rec {
+
+  inherit pkgs;
+
+
+  testDriver = let
+    testDriverScript = ./test-driver/test-driver.py;
+  in stdenv.mkDerivation {
+    name = "nixos-test-driver";
+
+    nativeBuildInputs = [ makeWrapper ];
+    buildInputs = [ (python3.withPackages (p: [ p.ptpython ])) ];
+    checkInputs = with python3Packages; [ pylint black ];
+
+    dontUnpack = true;
+
+    preferLocalBuild = true;
+
+    doCheck = true;
+    checkPhase = ''
+      pylint --errors-only ${testDriverScript}
+      black --check --diff ${testDriverScript}
+    '';
+
+    installPhase =
+      ''
+        mkdir -p $out/bin
+        cp ${testDriverScript} $out/bin/nixos-test-driver
+        chmod u+x $out/bin/nixos-test-driver
+        # TODO: copy user script part into this file (append)
+
+        wrapProgram $out/bin/nixos-test-driver \
+          --prefix PATH : "${lib.makeBinPath [ qemu_test vde2 netpbm coreutils ]}" \
+      '';
+  };
+
+
+  # Run an automated test suite in the given virtual network.
+  # `driver' is the script that runs the network.
+  runTests = driver:
+    stdenv.mkDerivation {
+      name = "vm-test-run-${driver.testName}";
+
+      requiredSystemFeatures = [ "kvm" "nixos-test" ];
+
+      buildInputs = [ libxslt ];
+
+      buildCommand =
+        ''
+          mkdir -p $out/nix-support
+
+          LOGFILE=$out/log.xml tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
+
+          # Generate a pretty-printed log.
+          xsltproc --output $out/log.html ${./test-driver/log2html.xsl} $out/log.xml
+          ln -s ${./test-driver/logfile.css} $out/logfile.css
+          ln -s ${./test-driver/treebits.js} $out/treebits.js
+          ln -s ${jquery}/js/jquery.min.js $out/
+          ln -s ${jquery}/js/jquery.js $out/
+          ln -s ${jquery-ui}/js/jquery-ui.min.js $out/
+          ln -s ${jquery-ui}/js/jquery-ui.js $out/
+
+          touch $out/nix-support/hydra-build-products
+          echo "report testlog $out log.html" >> $out/nix-support/hydra-build-products
+
+          for i in */xchg/coverage-data; do
+            mkdir -p $out/coverage-data
+            mv $i $out/coverage-data/$(dirname $(dirname $i))
+          done
+        '';
+    };
+
+
+  makeTest =
+    { testScript
+    , makeCoverageReport ? false
+    , enableOCR ? false
+    , name ? "unnamed"
+    , ...
+    } @ t:
+
+    let
+      # A standard store path to the vm monitor is built like this:
+      #   /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor
+      # The max filename length of a unix domain socket is 108 bytes.
+      # This means $name can at most be 50 bytes long.
+      maxTestNameLen = 50;
+      testNameLen = builtins.stringLength name;
+
+      testDriverName = with builtins;
+        if testNameLen > maxTestNameLen then
+          abort ("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " +
+            "it's currently ${toString testNameLen} characters long.")
+        else
+          "nixos-test-driver-${name}";
+
+      nodes = buildVirtualNetwork (
+        t.nodes or (if t ? machine then { machine = t.machine; } else { }));
+
+      testScript' =
+        # Call the test script with the computed nodes.
+        if lib.isFunction testScript
+        then testScript { inherit nodes; }
+        else testScript;
+
+      vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes);
+
+      vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
+
+      ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
+
+      imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
+
+      # Generate onvenience wrappers for running the test driver
+      # interactively with the specified network, and for starting the
+      # VMs from the command line.
+      driver = runCommand testDriverName
+        { buildInputs = [ makeWrapper];
+          testScript = testScript';
+          preferLocalBuild = true;
+          testName = name;
+        }
+        ''
+          mkdir -p $out/bin
+
+          echo -n "$testScript" > $out/test-script
+          ${python3Packages.black}/bin/black --check --diff $out/test-script
+
+          ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
+          vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
+          wrapProgram $out/bin/nixos-test-driver \
+            --add-flags "''${vms[*]}" \
+            ${lib.optionalString enableOCR
+              "--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
+            --run "export testScript=\"\$(cat $out/test-script)\"" \
+            --set VLANS '${toString vlans}'
+          ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
+          wrapProgram $out/bin/nixos-run-vms \
+            --add-flags "''${vms[*]}" \
+            ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
+            --set tests 'start_all(); join_all();' \
+            --set VLANS '${toString vlans}' \
+            ${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"}
+        ''; # "
+
+      passMeta = drv: drv // lib.optionalAttrs (t ? meta) {
+        meta = (drv.meta or {}) // t.meta;
+      };
+
+      test = passMeta (runTests driver);
+      report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; });
+
+      nodeNames = builtins.attrNames nodes;
+      invalidNodeNames = lib.filter
+        (node: builtins.match "^[A-z_][A-z0-9_]+$" node == null) nodeNames;
+
+    in
+      if lib.length invalidNodeNames > 0 then
+        throw ''
+          Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
+          All machines are referenced as perl variables in the testing framework which will break the
+          script when special characters are used.
+
+          Please stick to alphanumeric chars and underscores as separation.
+        ''
+      else
+        (if makeCoverageReport then report else test) // {
+          inherit nodes driver test;
+        };
+
+  runInMachine =
+    { drv
+    , machine
+    , preBuild ? ""
+    , postBuild ? ""
+    , ... # ???
+    }:
+    let
+      vm = buildVM { }
+        [ machine
+          { key = "run-in-machine";
+            networking.hostName = "client";
+            nix.readOnlyStore = false;
+            virtualisation.writableStore = false;
+          }
+        ];
+
+      buildrunner = writeText "vm-build" ''
+        source $1
+
+        ${coreutils}/bin/mkdir -p $TMPDIR
+        cd $TMPDIR
+
+        exec $origBuilder $origArgs
+      '';
+
+      testScript = ''
+        startAll;
+        $client->waitForUnit("multi-user.target");
+        ${preBuild}
+        $client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2");
+        ${postBuild}
+        $client->succeed("sync"); # flush all data before pulling the plug
+      '';
+
+      vmRunCommand = writeText "vm-run" ''
+        xchg=vm-state-client/xchg
+        ${coreutils}/bin/mkdir $out
+        ${coreutils}/bin/mkdir -p $xchg
+
+        for i in $passAsFile; do
+          i2=''${i}Path
+          _basename=$(${coreutils}/bin/basename ''${!i2})
+          ${coreutils}/bin/cp ''${!i2} $xchg/$_basename
+          eval $i2=/tmp/xchg/$_basename
+          ${coreutils}/bin/ls -la $xchg
+        done
+
+        unset i i2 _basename
+        export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env
+        unset xchg
+
+        export tests='${testScript}'
+        ${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm
+      ''; # */
+
+    in
+      lib.overrideDerivation drv (attrs: {
+        requiredSystemFeatures = [ "kvm" ];
+        builder = "${bash}/bin/sh";
+        args = ["-e" vmRunCommand];
+        origArgs = attrs.args;
+        origBuilder = attrs.builder;
+      });
+
+
+  runInMachineWithX = { require ? [], ... } @ args:
+    let
+      client =
+        { ... }:
+        {
+          inherit require;
+          virtualisation.memorySize = 1024;
+          services.xserver.enable = true;
+          services.xserver.displayManager.slim.enable = false;
+          services.xserver.displayManager.auto.enable = true;
+          services.xserver.windowManager.default = "icewm";
+          services.xserver.windowManager.icewm.enable = true;
+          services.xserver.desktopManager.default = "none";
+        };
+    in
+      runInMachine ({
+        machine = client;
+        preBuild =
+          ''
+            $client->waitForX;
+          '';
+      } // args);
+
+
+  simpleTest = as: (makeTest as).test;
+
+}
diff --git a/nixos/modules/hardware/brillo.nix b/nixos/modules/hardware/brillo.nix
new file mode 100644
index 00000000000..e970c948099
--- /dev/null
+++ b/nixos/modules/hardware/brillo.nix
@@ -0,0 +1,22 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.hardware.brillo;
+in
+{
+  options = {
+    hardware.brillo = {
+      enable = mkEnableOption ''
+        Enable brillo in userspace.
+        This will allow brightness control from users in the video group.
+      '';
+    };
+  };
+
+
+  config = mkIf cfg.enable {
+    services.udev.packages = [ pkgs.brillo ];
+    environment.systemPackages = [ pkgs.brillo ];
+  };
+}
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
deleted file mode 100644
index 4560e9c7403..00000000000
--- a/nixos/modules/installer/tools/nixos-option.sh
+++ /dev/null
@@ -1,327 +0,0 @@
-#! @shell@ -e
-
-# FIXME: rewrite this in a more suitable language.
-
-usage () {
-    exec man nixos-option
-    exit 1
-}
-
-#####################
-# Process Arguments #
-#####################
-
-xml=false
-verbose=false
-nixPath=""
-
-option=""
-exit_code=0
-
-argfun=""
-for arg; do
-  if test -z "$argfun"; then
-    case $arg in
-      -*)
-        sarg="$arg"
-        longarg=""
-        while test "$sarg" != "-"; do
-          case $sarg in
-            --*) longarg=$arg; sarg="--";;
-            -I) argfun="include_nixpath";;
-            -*) usage;;
-          esac
-          # remove the first letter option
-          sarg="-${sarg#??}"
-        done
-        ;;
-      *) longarg=$arg;;
-    esac
-    for larg in $longarg; do
-      case $larg in
-        --xml) xml=true;;
-        --verbose) verbose=true;;
-        --help) usage;;
-        -*) usage;;
-        *) if test -z "$option"; then
-             option="$larg"
-           else
-             usage
-           fi;;
-      esac
-    done
-  else
-    case $argfun in
-      set_*)
-        var=$(echo $argfun | sed 's,^set_,,')
-        eval $var=$arg
-        ;;
-      include_nixpath)
-        nixPath="-I $arg $nixPath"
-        ;;
-    esac
-    argfun=""
-  fi
-done
-
-if $verbose; then
-  set -x
-else
-  set +x
-fi
-
-#############################
-# Process the configuration #
-#############################
-
-evalNix(){
-  # disable `-e` flag, it's possible that the evaluation of `nix-instantiate` fails (e.g. due to broken pkgs)
-  set +e
-  result=$(nix-instantiate ${nixPath:+$nixPath} - --eval-only "$@" 2>&1)
-  exit_code=$?
-  set -e
-
-  if test $exit_code -eq 0; then
-      sed '/^warning: Nix search path/d' <<EOF
-$result
-EOF
-      return 0;
-  else
-      sed -n '
-  /^error/ { s/, at (string):[0-9]*:[0-9]*//; p; };
-  /^warning: Nix search path/ { p; };
-' >&2 <<EOF
-$result
-EOF
-    exit_code=1
-  fi
-}
-
-header="let
-  nixos = import <nixpkgs/nixos> {};
-  nixpkgs = import <nixpkgs> {};
-in with nixpkgs.lib;
-"
-
-# This function is used for converting the option definition path given by
-# the user into accessors for reaching the definition and the declaration
-# corresponding to this option.
-generateAccessors(){
-  if result=$(evalNix --strict --show-trace <<EOF
-$header
-
-let
-  path = "${option:+$option}";
-  pathList = splitString "." path;
-
-  walkOptions = attrsNames: result:
-    if attrsNames == [] then
-      result
-    else
-      let name = head attrsNames; rest = tail attrsNames; in
-      if isOption result.options then
-        walkOptions rest {
-          options = result.options.type.getSubOptions "";
-          opt = ''(\${result.opt}.type.getSubOptions "")'';
-          cfg = ''\${result.cfg}."\${name}"'';
-        }
-      else
-        walkOptions rest {
-          options = result.options.\${name};
-          opt = ''\${result.opt}."\${name}"'';
-          cfg = ''\${result.cfg}."\${name}"'';
-        }
-    ;
-
-  walkResult = (if path == "" then x: x else walkOptions pathList) {
-    options = nixos.options;
-    opt = ''nixos.options'';
-    cfg = ''nixos.config'';
-  };
-
-in
-  ''let option = \${walkResult.opt}; config = \${walkResult.cfg}; in''
-EOF
-)
-  then
-      echo $result
-  else
-      # In case of error we want to ignore the error message roduced by the
-      # script above, as it is iterating over each attribute, which does not
-      # produce a nice error message.  The following code is a fallback
-      # solution which is cause a nicer error message in the next
-      # evaluation.
-      echo "\"let option = nixos.options${option:+.$option}; config = nixos.config${option:+.$option}; in\""
-  fi
-}
-
-header="$header
-$(eval echo $(generateAccessors))
-"
-
-evalAttr(){
-  local prefix="$1"
-  local strict="$2"
-  local suffix="$3"
-
-  # If strict is set, then set it to "true".
-  test -n "$strict" && strict=true
-
-  evalNix ${strict:+--strict} <<EOF
-$header
-
-let
-  value = $prefix${suffix:+.$suffix};
-  strict = ${strict:-false};
-  cleanOutput = x: with nixpkgs.lib;
-    if isDerivation x then x.outPath
-    else if isFunction x then "<CODE>"
-    else if strict then
-      if isAttrs x then mapAttrs (n: cleanOutput) x
-      else if isList x then map cleanOutput x
-      else x
-    else x;
-in
-  cleanOutput value
-EOF
-}
-
-evalOpt(){
-  evalAttr "option" "" "$@"
-}
-
-evalCfg(){
-  local strict="$1"
-  evalAttr "config" "$strict"
-}
-
-findSources(){
-  local suffix=$1
-  evalNix --strict <<EOF
-$header
-
-option.$suffix
-EOF
-}
-
-# Given a result from nix-instantiate, recover the list of attributes it
-# contains.
-attrNames() {
-  local attributeset=$1
-  # sed is used to replace un-printable subset by 0s, and to remove most of
-  # the inner-attribute set, which reduce the likelyhood to encounter badly
-  # pre-processed input.
-  echo "builtins.attrNames $attributeset" | \
-    sed 's,<[A-Z]*>,0,g; :inner; s/{[^\{\}]*};/0;/g; t inner;' | \
-    evalNix --strict
-}
-
-# map a simple list which contains strings or paths.
-nixMap() {
-  local fun="$1"
-  local list="$2"
-  local elem
-  for elem in $list; do
-    test $elem = '[' -o $elem = ']' && continue;
-    $fun $elem
-  done
-}
-
-# This duplicates the work made below, but it is useful for processing
-# the output of nixos-option with other tools such as nixos-gui.
-if $xml; then
-  evalNix --xml --no-location <<EOF
-$header
-
-let
-  sources = builtins.map (f: f.source);
-  opt = option;
-  cfg = config;
-in
-
-with nixpkgs.lib;
-
-let
-  optStrict = v:
-    let
-      traverse = x :
-        if isAttrs x then
-          if x ? outPath then true
-          else all id (mapAttrsFlatten (n: traverseNoAttrs) x)
-        else traverseNoAttrs x;
-      traverseNoAttrs = x:
-        # do not continue in attribute sets
-        if isAttrs x then true
-        else if isList x then all id (map traverse x)
-        else true;
-    in assert traverse v; v;
-in
-
-if isOption opt then
-  optStrict ({}
-  // optionalAttrs (opt ? default) { inherit (opt) default; }
-  // optionalAttrs (opt ? example) { inherit (opt) example; }
-  // optionalAttrs (opt ? description) { inherit (opt) description; }
-  // optionalAttrs (opt ? type) { typename = opt.type.description; }
-  // optionalAttrs (opt ? options) { inherit (opt) options; }
-  // {
-    # to disambiguate the xml output.
-    _isOption = true;
-    declarations = sources opt.declarations;
-    definitions = sources opt.definitions;
-    value = cfg;
-  })
-else
-  opt
-EOF
-  exit $?
-fi
-
-if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then
-  echo "Value:"
-  evalCfg 1
-
-  echo
-
-  echo "Default:"
-  if default=$(evalOpt "default" - 2> /dev/null); then
-    echo "$default"
-  else
-    echo "<None>"
-  fi
-  echo
-  if example=$(evalOpt "example" - 2> /dev/null); then
-    echo "Example:"
-    echo "$example"
-    echo
-  fi
-  echo "Description:"
-  echo
-  echo $(evalOpt "description")
-
-  echo $desc;
-
-  printPath () { echo "  $1"; }
-
-  echo "Declared by:"
-  nixMap printPath "$(findSources "declarations")"
-  echo
-  echo "Defined by:"
-  nixMap printPath "$(findSources "files")"
-  echo
-
-else
-  # echo 1>&2 "Warning: This value is not an option."
-
-  result=$(evalCfg "")
-  if [ ! -z "$result" ]; then
-    names=$(attrNames "$result" 2> /dev/null)
-    echo 1>&2 "This attribute set contains:"
-    escapeQuotes () { eval echo "$1"; }
-    nixMap escapeQuotes "$names"
-  else
-    echo 1>&2 "An error occurred while looking for attribute names. Are you sure that '$option' exists?"
-  fi
-fi
-
-exit $exit_code
diff --git a/nixos/modules/installer/tools/nixos-option/CMakeLists.txt b/nixos/modules/installer/tools/nixos-option/CMakeLists.txt
new file mode 100644
index 00000000000..e5834598c4f
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required (VERSION 2.6)
+project (nixos-option)
+
+add_executable(nixos-option nixos-option.cc libnix-copy-paste.cc)
+target_link_libraries(nixos-option PRIVATE -lnixmain -lnixexpr -lnixstore -lnixutil)
+target_compile_features(nixos-option PRIVATE cxx_std_17)
+
+install (TARGETS nixos-option DESTINATION bin)
diff --git a/nixos/modules/installer/tools/nixos-option/default.nix b/nixos/modules/installer/tools/nixos-option/default.nix
new file mode 100644
index 00000000000..753fd92c7bb
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option/default.nix
@@ -0,0 +1,11 @@
+{lib, stdenv, boost, cmake, pkgconfig, nix, ... }:
+stdenv.mkDerivation rec {
+  name = "nixos-option";
+  src = ./.;
+  nativeBuildInputs = [ cmake pkgconfig ];
+  buildInputs = [ boost nix ];
+  meta = {
+    license = stdenv.lib.licenses.lgpl2Plus;
+    maintainers = with lib.maintainers; [ chkno ];
+  };
+}
diff --git a/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.cc b/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.cc
new file mode 100644
index 00000000000..875c07da639
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.cc
@@ -0,0 +1,83 @@
+// These are useful methods inside the nix library that ought to be exported.
+// Since they are not, copy/paste them here.
+// TODO: Delete these and use the ones in the library as they become available.
+
+#include <nix/config.h> // for nix/globals.hh's reference to SYSTEM
+
+#include "libnix-copy-paste.hh"
+#include <boost/format/alt_sstream.hpp>           // for basic_altstringbuf...
+#include <boost/format/alt_sstream_impl.hpp>      // for basic_altstringbuf...
+#include <boost/format/format_class.hpp>          // for basic_format
+#include <boost/format/format_fwd.hpp>            // for format
+#include <boost/format/format_implementation.hpp> // for basic_format::basi...
+#include <boost/optional/optional.hpp>            // for get_pointer
+#include <iostream>                               // for operator<<, basic_...
+#include <nix/types.hh>                           // for Strings, Error
+#include <string>                                 // for string, basic_string
+
+using boost::format;
+using nix::Error;
+using nix::Strings;
+using std::string;
+
+// From nix/src/libexpr/attr-path.cc
+Strings parseAttrPath(const string & s)
+{
+    Strings res;
+    string cur;
+    string::const_iterator i = s.begin();
+    while (i != s.end()) {
+        if (*i == '.') {
+            res.push_back(cur);
+            cur.clear();
+        } else if (*i == '"') {
+            ++i;
+            while (1) {
+                if (i == s.end())
+                    throw Error(format("missing closing quote in selection path '%1%'") % s);
+                if (*i == '"')
+                    break;
+                cur.push_back(*i++);
+            }
+        } else
+            cur.push_back(*i);
+        ++i;
+    }
+    if (!cur.empty())
+        res.push_back(cur);
+    return res;
+}
+
+// From nix/src/nix/repl.cc
+bool isVarName(const string & s)
+{
+    if (s.size() == 0)
+        return false;
+    char c = s[0];
+    if ((c >= '0' && c <= '9') || c == '-' || c == '\'')
+        return false;
+    for (auto & i : s)
+        if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-' ||
+              i == '\''))
+            return false;
+    return true;
+}
+
+// From nix/src/nix/repl.cc
+std::ostream & printStringValue(std::ostream & str, const char * string)
+{
+    str << "\"";
+    for (const char * i = string; *i; i++)
+        if (*i == '\"' || *i == '\\')
+            str << "\\" << *i;
+        else if (*i == '\n')
+            str << "\\n";
+        else if (*i == '\r')
+            str << "\\r";
+        else if (*i == '\t')
+            str << "\\t";
+        else
+            str << *i;
+    str << "\"";
+    return str;
+}
diff --git a/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.hh b/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.hh
new file mode 100644
index 00000000000..2274e9a0f85
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option/libnix-copy-paste.hh
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <iostream>
+#include <nix/types.hh>
+#include <string>
+
+nix::Strings parseAttrPath(const std::string & s);
+bool isVarName(const std::string & s);
+std::ostream & printStringValue(std::ostream & str, const char * string);
diff --git a/nixos/modules/installer/tools/nixos-option/nixos-option.cc b/nixos/modules/installer/tools/nixos-option/nixos-option.cc
new file mode 100644
index 00000000000..9b92dc829cd
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option/nixos-option.cc
@@ -0,0 +1,618 @@
+#include <nix/config.h> // for nix/globals.hh's reference to SYSTEM
+
+#include <exception>               // for exception_ptr, current_exception
+#include <functional>              // for function
+#include <iostream>                // for operator<<, basic_ostream, ostrin...
+#include <iterator>                // for next
+#include <list>                    // for _List_iterator
+#include <memory>                  // for allocator, unique_ptr, make_unique
+#include <new>                     // for operator new
+#include <nix/args.hh>             // for argvToStrings, UsageError
+#include <nix/attr-path.hh>        // for findAlongAttrPath
+#include <nix/attr-set.hh>         // for Attr, Bindings, Bindings::iterator
+#include <nix/common-eval-args.hh> // for MixEvalArgs
+#include <nix/eval-inline.hh>      // for EvalState::forceValue
+#include <nix/eval.hh>             // for EvalState, initGC, operator<<
+#include <nix/globals.hh>          // for initPlugins, Settings, settings
+#include <nix/nixexpr.hh>          // for Pos
+#include <nix/shared.hh>           // for getArg, LegacyArgs, printVersion
+#include <nix/store-api.hh>        // for openStore
+#include <nix/symbol-table.hh>     // for Symbol, SymbolTable
+#include <nix/types.hh>            // for Error, Path, Strings, PathSet
+#include <nix/util.hh>             // for absPath, baseNameOf
+#include <nix/value.hh>            // for Value, Value::(anonymous), Value:...
+#include <string>                  // for string, operator+, operator==
+#include <utility>                 // for move
+#include <variant>                 // for get, holds_alternative, variant
+#include <vector>                  // for vector<>::iterator, vector
+
+#include "libnix-copy-paste.hh"
+
+using nix::absPath;
+using nix::Bindings;
+using nix::Error;
+using nix::EvalError;
+using nix::EvalState;
+using nix::Path;
+using nix::PathSet;
+using nix::Strings;
+using nix::Symbol;
+using nix::tAttrs;
+using nix::ThrownError;
+using nix::tLambda;
+using nix::tString;
+using nix::UsageError;
+using nix::Value;
+
+// An ostream wrapper to handle nested indentation
+class Out
+{
+  public:
+    class Separator
+    {};
+    const static Separator sep;
+    enum LinePolicy
+    {
+        ONE_LINE,
+        MULTI_LINE
+    };
+    explicit Out(std::ostream & ostream) : ostream(ostream), policy(ONE_LINE), writeSinceSep(true) {}
+    Out(Out & o, const std::string & start, const std::string & end, LinePolicy policy);
+    Out(Out & o, const std::string & start, const std::string & end, int count)
+        : Out(o, start, end, count < 2 ? ONE_LINE : MULTI_LINE)
+    {}
+    Out(const Out &) = delete;
+    Out(Out &&) = default;
+    Out & operator=(const Out &) = delete;
+    Out & operator=(Out &&) = delete;
+    ~Out() { ostream << end; }
+
+  private:
+    std::ostream & ostream;
+    std::string indentation;
+    std::string end;
+    LinePolicy policy;
+    bool writeSinceSep;
+    template <typename T> friend Out & operator<<(Out & o, T thing);
+};
+
+template <typename T> Out & operator<<(Out & o, T thing)
+{
+    if (!o.writeSinceSep && o.policy == Out::MULTI_LINE) {
+        o.ostream << o.indentation;
+    }
+    o.writeSinceSep = true;
+    o.ostream << thing;
+    return o;
+}
+
+template <> Out & operator<<<Out::Separator>(Out & o, Out::Separator /* thing */)
+{
+    o.ostream << (o.policy == Out::ONE_LINE ? " " : "\n");
+    o.writeSinceSep = false;
+    return o;
+}
+
+Out::Out(Out & o, const std::string & start, const std::string & end, LinePolicy policy)
+    : ostream(o.ostream), indentation(policy == ONE_LINE ? o.indentation : o.indentation + "  "),
+      end(policy == ONE_LINE ? end : o.indentation + end), policy(policy), writeSinceSep(true)
+{
+    o << start;
+    *this << Out::sep;
+}
+
+// Stuff needed for evaluation
+struct Context
+{
+    Context(EvalState & state, Bindings & autoArgs, Value optionsRoot, Value configRoot)
+        : state(state), autoArgs(autoArgs), optionsRoot(optionsRoot), configRoot(configRoot),
+          underscoreType(state.symbols.create("_type"))
+    {}
+    EvalState & state;
+    Bindings & autoArgs;
+    Value optionsRoot;
+    Value configRoot;
+    Symbol underscoreType;
+};
+
+Value evaluateValue(Context & ctx, Value & v)
+{
+    ctx.state.forceValue(v);
+    if (ctx.autoArgs.empty()) {
+        return v;
+    }
+    Value called{};
+    ctx.state.autoCallFunction(ctx.autoArgs, v, called);
+    return called;
+}
+
+bool isOption(Context & ctx, const Value & v)
+{
+    if (v.type != tAttrs) {
+        return false;
+    }
+    const auto & atualType = v.attrs->find(ctx.underscoreType);
+    if (atualType == v.attrs->end()) {
+        return false;
+    }
+    try {
+        Value evaluatedType = evaluateValue(ctx, *atualType->value);
+        if (evaluatedType.type != tString) {
+            return false;
+        }
+        return static_cast<std::string>(evaluatedType.string.s) == "option";
+    } catch (Error &) {
+        return false;
+    }
+}
+
+// Add quotes to a component of a path.
+// These are needed for paths like:
+//    fileSystems."/".fsType
+//    systemd.units."dbus.service".text
+std::string quoteAttribute(const std::string & attribute)
+{
+    if (isVarName(attribute)) {
+        return attribute;
+    }
+    std::ostringstream buf;
+    printStringValue(buf, attribute.c_str());
+    return buf.str();
+}
+
+const std::string appendPath(const std::string & prefix, const std::string & suffix)
+{
+    if (prefix.empty()) {
+        return quoteAttribute(suffix);
+    }
+    return prefix + "." + quoteAttribute(suffix);
+}
+
+bool forbiddenRecursionName(std::string name) { return (!name.empty() && name[0] == '_') || name == "haskellPackages"; }
+
+void recurse(const std::function<bool(const std::string & path, std::variant<Value, std::exception_ptr>)> & f,
+             Context & ctx, Value v, const std::string & path)
+{
+    std::variant<Value, std::exception_ptr> evaluated;
+    try {
+        evaluated = evaluateValue(ctx, v);
+    } catch (Error &) {
+        evaluated = std::current_exception();
+    }
+    if (!f(path, evaluated)) {
+        return;
+    }
+    if (std::holds_alternative<std::exception_ptr>(evaluated)) {
+        return;
+    }
+    const Value & evaluated_value = std::get<Value>(evaluated);
+    if (evaluated_value.type != tAttrs) {
+        return;
+    }
+    for (const auto & child : evaluated_value.attrs->lexicographicOrder()) {
+        if (forbiddenRecursionName(child->name)) {
+            continue;
+        }
+        recurse(f, ctx, *child->value, appendPath(path, child->name));
+    }
+}
+
+// Calls f on all the option names
+void mapOptions(const std::function<void(const std::string & path)> & f, Context & ctx, Value root)
+{
+    recurse(
+        [f, &ctx](const std::string & path, std::variant<Value, std::exception_ptr> v) {
+            bool isOpt = std::holds_alternative<std::exception_ptr>(v) || isOption(ctx, std::get<Value>(v));
+            if (isOpt) {
+                f(path);
+            }
+            return !isOpt;
+        },
+        ctx, root, "");
+}
+
+// Calls f on all the config values inside one option.
+// Simple options have one config value inside, like sound.enable = true.
+// Compound options have multiple config values.  For example, the option
+// "users.users" has about 1000 config values inside it:
+//   users.users.avahi.createHome = false;
+//   users.users.avahi.cryptHomeLuks = null;
+//   users.users.avahi.description = "`avahi-daemon' privilege separation user";
+//   ...
+//   users.users.avahi.openssh.authorizedKeys.keyFiles = [ ];
+//   users.users.avahi.openssh.authorizedKeys.keys = [ ];
+//   ...
+//   users.users.avahi.uid = 10;
+//   users.users.avahi.useDefaultShell = false;
+//   users.users.cups.createHome = false;
+//   ...
+//   users.users.cups.useDefaultShell = false;
+//   users.users.gdm = ... ... ...
+//   users.users.messagebus = ... .. ...
+//   users.users.nixbld1 = ... .. ...
+//   ...
+//   users.users.systemd-timesync = ... .. ...
+void mapConfigValuesInOption(
+    const std::function<void(const std::string & path, std::variant<Value, std::exception_ptr> v)> & f,
+    const std::string & path, Context & ctx)
+{
+    Value * option;
+    try {
+        option = findAlongAttrPath(ctx.state, path, ctx.autoArgs, ctx.configRoot);
+    } catch (Error &) {
+        f(path, std::current_exception());
+        return;
+    }
+    recurse(
+        [f, ctx](const std::string & path, std::variant<Value, std::exception_ptr> v) {
+            bool leaf = std::holds_alternative<std::exception_ptr>(v) || std::get<Value>(v).type != tAttrs ||
+                        ctx.state.isDerivation(std::get<Value>(v));
+            if (!leaf) {
+                return true; // Keep digging
+            }
+            f(path, v);
+            return false;
+        },
+        ctx, *option, path);
+}
+
+std::string describeError(const Error & e) { return "«error: " + e.msg() + "»"; }
+
+void describeDerivation(Context & ctx, Out & out, Value v)
+{
+    // Copy-pasted from nix/src/nix/repl.cc  :(
+    Bindings::iterator i = v.attrs->find(ctx.state.sDrvPath);
+    PathSet pathset;
+    try {
+        Path drvPath = i != v.attrs->end() ? ctx.state.coerceToPath(*i->pos, *i->value, pathset) : "???";
+        out << "«derivation " << drvPath << "»";
+    } catch (Error & e) {
+        out << describeError(e);
+    }
+}
+
+Value parseAndEval(EvalState & state, const std::string & expression, const std::string & path)
+{
+    Value v{};
+    state.eval(state.parseExprFromString(expression, absPath(path)), v);
+    return v;
+}
+
+void printValue(Context & ctx, Out & out, std::variant<Value, std::exception_ptr> maybeValue, const std::string & path);
+
+void printList(Context & ctx, Out & out, Value & v)
+{
+    Out listOut(out, "[", "]", v.listSize());
+    for (unsigned int n = 0; n < v.listSize(); ++n) {
+        printValue(ctx, listOut, *v.listElems()[n], "");
+        listOut << Out::sep;
+    }
+}
+
+void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path)
+{
+    Out attrsOut(out, "{", "}", v.attrs->size());
+    for (const auto & a : v.attrs->lexicographicOrder()) {
+        std::string name = a->name;
+        attrsOut << name << " = ";
+        printValue(ctx, attrsOut, *a->value, appendPath(path, name));
+        attrsOut << ";" << Out::sep;
+    }
+}
+
+void multiLineStringEscape(Out & out, const std::string & s)
+{
+    int i;
+    for (i = 1; i < s.size(); i++) {
+        if (s[i - 1] == '$' && s[i] == '{') {
+            out << "''${";
+            i++;
+        } else if (s[i - 1] == '\'' && s[i] == '\'') {
+            out << "'''";
+            i++;
+        } else {
+            out << s[i - 1];
+        }
+    }
+    if (i == s.size()) {
+        out << s[i - 1];
+    }
+}
+
+void printMultiLineString(Out & out, const Value & v)
+{
+    std::string s = v.string.s;
+    Out strOut(out, "''", "''", Out::MULTI_LINE);
+    std::string::size_type begin = 0;
+    while (begin < s.size()) {
+        std::string::size_type end = s.find('\n', begin);
+        if (end == std::string::npos) {
+            multiLineStringEscape(strOut, s.substr(begin, s.size() - begin));
+            break;
+        }
+        multiLineStringEscape(strOut, s.substr(begin, end - begin));
+        strOut << Out::sep;
+        begin = end + 1;
+    }
+}
+
+void printValue(Context & ctx, Out & out, std::variant<Value, std::exception_ptr> maybeValue, const std::string & path)
+{
+    try {
+        if (auto ex = std::get_if<std::exception_ptr>(&maybeValue)) {
+            std::rethrow_exception(*ex);
+        }
+        Value v = evaluateValue(ctx, std::get<Value>(maybeValue));
+        if (ctx.state.isDerivation(v)) {
+            describeDerivation(ctx, out, v);
+        } else if (v.isList()) {
+            printList(ctx, out, v);
+        } else if (v.type == tAttrs) {
+            printAttrs(ctx, out, v, path);
+        } else if (v.type == tString && std::string(v.string.s).find('\n') != std::string::npos) {
+            printMultiLineString(out, v);
+        } else {
+            ctx.state.forceValueDeep(v);
+            out << v;
+        }
+    } catch (ThrownError & e) {
+        if (e.msg() == "The option `" + path + "' is used but not defined.") {
+            // 93% of errors are this, and just letting this message through would be
+            // misleading.  These values may or may not actually be "used" in the
+            // config.  The thing throwing the error message assumes that if anything
+            // ever looks at this value, it is a "use" of this value.  But here in
+            // nixos-option, we are looking at this value only to print it.
+            // In order to avoid implying that this undefined value is actually
+            // referenced, eat the underlying error message and emit "«not defined»".
+            out << "«not defined»";
+        } else {
+            out << describeError(e);
+        }
+    } catch (Error & e) {
+        out << describeError(e);
+    }
+}
+
+void printConfigValue(Context & ctx, Out & out, const std::string & path, std::variant<Value, std::exception_ptr> v)
+{
+    out << path << " = ";
+    printValue(ctx, out, std::move(v), path);
+    out << ";\n";
+}
+
+void printAll(Context & ctx, Out & out)
+{
+    mapOptions(
+        [&ctx, &out](const std::string & optionPath) {
+            mapConfigValuesInOption(
+                [&ctx, &out](const std::string & configPath, std::variant<Value, std::exception_ptr> v) {
+                    printConfigValue(ctx, out, configPath, v);
+                },
+                optionPath, ctx);
+        },
+        ctx, ctx.optionsRoot);
+}
+
+void printAttr(Context & ctx, Out & out, const std::string & path, Value & root)
+{
+    try {
+        printValue(ctx, out, *findAlongAttrPath(ctx.state, path, ctx.autoArgs, root), path);
+    } catch (Error & e) {
+        out << describeError(e);
+    }
+}
+
+bool hasExample(Context & ctx, Value & option)
+{
+    try {
+        findAlongAttrPath(ctx.state, "example", ctx.autoArgs, option);
+        return true;
+    } catch (Error &) {
+        return false;
+    }
+}
+
+void printOption(Context & ctx, Out & out, const std::string & path, Value & option)
+{
+    out << "Value:\n";
+    printAttr(ctx, out, path, ctx.configRoot);
+
+    out << "\n\nDefault:\n";
+    printAttr(ctx, out, "default", option);
+
+    out << "\n\nType:\n";
+    printAttr(ctx, out, "type.description", option);
+
+    if (hasExample(ctx, option)) {
+        out << "\n\nExample:\n";
+        printAttr(ctx, out, "example", option);
+    }
+
+    out << "\n\nDescription:\n";
+    printAttr(ctx, out, "description", option);
+
+    out << "\n\nDeclared by:\n";
+    printAttr(ctx, out, "declarations", option);
+
+    out << "\n\nDefined by:\n";
+    printAttr(ctx, out, "files", option);
+    out << "\n";
+}
+
+void printListing(Out & out, Value & v)
+{
+    out << "This attribute set contains:\n";
+    for (const auto & a : v.attrs->lexicographicOrder()) {
+        std::string name = a->name;
+        if (!name.empty() && name[0] != '_') {
+            out << name << "\n";
+        }
+    }
+}
+
+bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
+{
+    try {
+        const auto & typeLookup = v.attrs->find(ctx.state.sType);
+        if (typeLookup == v.attrs->end()) {
+            return false;
+        }
+        Value type = evaluateValue(ctx, *typeLookup->value);
+        if (type.type != tAttrs) {
+            return false;
+        }
+        const auto & nameLookup = type.attrs->find(ctx.state.sName);
+        if (nameLookup == type.attrs->end()) {
+            return false;
+        }
+        Value name = evaluateValue(ctx, *nameLookup->value);
+        if (name.type != tString) {
+            return false;
+        }
+        return name.string.s == soughtType;
+    } catch (Error &) {
+        return false;
+    }
+}
+
+bool isAggregateOptionType(Context & ctx, Value & v)
+{
+    return optionTypeIs(ctx, v, "attrsOf") || optionTypeIs(ctx, v, "listOf") || optionTypeIs(ctx, v, "loaOf");
+}
+
+MakeError(OptionPathError, EvalError);
+
+Value getSubOptions(Context & ctx, Value & option)
+{
+    Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option));
+    if (getSubOptions.type != tLambda) {
+        throw OptionPathError("Option's type.getSubOptions isn't a function");
+    }
+    Value emptyString{};
+    nix::mkString(emptyString, "");
+    Value v;
+    ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
+    return v;
+}
+
+// Carefully walk an option path, looking for sub-options when a path walks past
+// an option value.
+Value findAlongOptionPath(Context & ctx, const std::string & path)
+{
+    Strings tokens = parseAttrPath(path);
+    Value v = ctx.optionsRoot;
+    for (auto i = tokens.begin(); i != tokens.end(); i++) {
+        const auto & attr = *i;
+        try {
+            bool lastAttribute = std::next(i) == tokens.end();
+            v = evaluateValue(ctx, v);
+            if (attr.empty()) {
+                throw OptionPathError("empty attribute name");
+            }
+            if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
+                v = getSubOptions(ctx, v);
+            }
+            if (isOption(ctx, v) && isAggregateOptionType(ctx, v) && !lastAttribute) {
+                v = getSubOptions(ctx, v);
+                // Note that we've consumed attr, but didn't actually use it.  This is the path component that's looked
+                // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
+            } else if (v.type != tAttrs) {
+                throw OptionPathError("Value is %s while a set was expected", showType(v));
+            } else {
+                const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
+                if (next == v.attrs->end()) {
+                    throw OptionPathError("Attribute not found", attr, path);
+                }
+                v = *next->value;
+            }
+        } catch (OptionPathError & e) {
+            throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
+        }
+    }
+    return v;
+}
+
+void printOne(Context & ctx, Out & out, const std::string & path)
+{
+    try {
+        Value option = findAlongOptionPath(ctx, path);
+        option = evaluateValue(ctx, option);
+        if (isOption(ctx, option)) {
+            printOption(ctx, out, path, option);
+        } else {
+            printListing(out, option);
+        }
+    } catch (Error & e) {
+        std::cerr << "error: " << e.msg()
+                  << "\nAn error occurred while looking for attribute names. Are "
+                     "you sure that '"
+                  << path << "' exists?\n";
+    }
+}
+
+int main(int argc, char ** argv)
+{
+    bool all = false;
+    std::string path = ".";
+    std::string optionsExpr = "(import <nixpkgs/nixos> {}).options";
+    std::string configExpr = "(import <nixpkgs/nixos> {}).config";
+    std::vector<std::string> args;
+
+    struct MyArgs : nix::LegacyArgs, nix::MixEvalArgs
+    {
+        using nix::LegacyArgs::LegacyArgs;
+    };
+
+    MyArgs myArgs(nix::baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) {
+        if (*arg == "--help") {
+            nix::showManPage("nixos-option");
+        } else if (*arg == "--version") {
+            nix::printVersion("nixos-option");
+        } else if (*arg == "--all") {
+            all = true;
+        } else if (*arg == "--path") {
+            path = nix::getArg(*arg, arg, end);
+        } else if (*arg == "--options_expr") {
+            optionsExpr = nix::getArg(*arg, arg, end);
+        } else if (*arg == "--config_expr") {
+            configExpr = nix::getArg(*arg, arg, end);
+        } else if (!arg->empty() && arg->at(0) == '-') {
+            return false;
+        } else {
+            args.push_back(*arg);
+        }
+        return true;
+    });
+
+    myArgs.parseCmdline(nix::argvToStrings(argc, argv));
+
+    nix::initPlugins();
+    nix::initGC();
+    nix::settings.readOnlyMode = true;
+    auto store = nix::openStore();
+    auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
+
+    Value optionsRoot = parseAndEval(*state, optionsExpr, path);
+    Value configRoot = parseAndEval(*state, configExpr, path);
+
+    Context ctx{*state, *myArgs.getAutoArgs(*state), optionsRoot, configRoot};
+    Out out(std::cout);
+
+    if (all) {
+        if (!args.empty()) {
+            throw UsageError("--all cannot be used with arguments");
+        }
+        printAll(ctx, out);
+    } else {
+        if (args.empty()) {
+            printOne(ctx, out, "");
+        }
+        for (const auto & arg : args) {
+            printOne(ctx, out, arg);
+        }
+    }
+
+    ctx.state.printStats();
+
+    return 0;
+}
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 052e7fdd4fc..e4db39b5c81 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -41,10 +41,7 @@ let
     inherit (config.system.nixos-generate-config) configuration;
   };
 
-  nixos-option = makeProg {
-    name = "nixos-option";
-    src = ./nixos-option.sh;
-  };
+  nixos-option = pkgs.callPackage ./nixos-option { };
 
   nixos-version = makeProg {
     name = "nixos-version";
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index df6e4dc1336..cacb4b13f41 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -44,6 +44,7 @@
   ./hardware/all-firmware.nix
   ./hardware/bladeRF.nix
   ./hardware/brightnessctl.nix
+  ./hardware/brillo.nix
   ./hardware/ckb-next.nix
   ./hardware/cpu/amd-microcode.nix
   ./hardware/cpu/intel-microcode.nix
@@ -812,8 +813,10 @@
   ./services/web-apps/nexus.nix
   ./services/web-apps/pgpkeyserver-lite.nix
   ./services/web-apps/matomo.nix
+  ./services/web-apps/moinmoin.nix
   ./services/web-apps/restya-board.nix
   ./services/web-apps/tt-rss.nix
+  ./services/web-apps/trac.nix
   ./services/web-apps/selfoss.nix
   ./services/web-apps/shiori.nix
   ./services/web-apps/virtlyst.nix
@@ -864,6 +867,7 @@
   ./services/x11/hardware/multitouch.nix
   ./services/x11/hardware/synaptics.nix
   ./services/x11/hardware/wacom.nix
+  ./services/x11/hardware/digimend.nix
   ./services/x11/hardware/cmt.nix
   ./services/x11/gdk-pixbuf.nix
   ./services/x11/redshift.nix
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 733b8f7636f..703975fd06c 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -115,6 +115,16 @@ in
         '';
       };
 
+      agentPKCS11Whitelist = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "\${pkgs.opensc}/lib/opensc-pkcs11.so";
+        description = ''
+          A pattern-list of acceptable paths for PKCS#11 shared libraries
+          that may be used with the -s option to ssh-add.
+        '';
+      };
+
       package = mkOption {
         type = types.package;
         default = pkgs.openssh;
@@ -241,6 +251,7 @@ in
             ExecStart =
                 "${cfg.package}/bin/ssh-agent " +
                 optionalString (cfg.agentTimeout != null) ("-t ${cfg.agentTimeout} ") +
+                optionalString (cfg.agentPKCS11Whitelist != null) ("-P ${cfg.agentPKCS11Whitelist} ")
                 "-a %t/ssh-agent";
             StandardOutput = "null";
             Type = "forking";
diff --git a/nixos/modules/security/pam_mount.nix b/nixos/modules/security/pam_mount.nix
index 8b131c54a2a..75f58462d13 100644
--- a/nixos/modules/security/pam_mount.nix
+++ b/nixos/modules/security/pam_mount.nix
@@ -50,9 +50,6 @@ in
           <pam_mount>
           <debug enable="0" />
 
-          ${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))}
-          ${concatStringsSep "\n" cfg.extraVolumes}
-
           <!-- if activated, requires ofl from hxtools to be present -->
           <logout wait="0" hup="no" term="no" kill="no" />
           <!-- set PATH variable for pam_mount module -->
@@ -64,6 +61,9 @@ in
           <cryptmount>${pkgs.pam_mount}/bin/mount.crypt %(VOLUME) %(MNTPT)</cryptmount>
           <cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount>
           <pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun>
+
+          ${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))}
+          ${concatStringsSep "\n" cfg.extraVolumes}
           </pam_mount>
           '';
     }];
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 0df8f9688d2..56dc858b640 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -181,6 +181,7 @@ in {
         ProtectKernelModules = true;
         RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK";
         RestrictNamespaces = true;
+        Restart = "always";
       };
     };
 
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index 89d8590093d..5681bda51cb 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -29,7 +29,7 @@ let
     iptables -w -t nat -N nixos-nat-post
 
     # We can't match on incoming interface in POSTROUTING, so
-    # mark packets coming from the external interfaces.
+    # mark packets coming from the internal interfaces.
     ${concatMapStrings (iface: ''
       iptables -w -t nat -A nixos-nat-pre \
         -i '${iface}' -j MARK --set-mark 1
diff --git a/nixos/modules/services/web-apps/moinmoin.nix b/nixos/modules/services/web-apps/moinmoin.nix
new file mode 100644
index 00000000000..0fee64be0bb
--- /dev/null
+++ b/nixos/modules/services/web-apps/moinmoin.nix
@@ -0,0 +1,303 @@
+{ config, lib, pkgs, ... }:
+with lib;
+
+let
+  cfg = config.services.moinmoin;
+  python = pkgs.python27;
+  pkg = python.pkgs.moinmoin;
+  dataDir = "/var/lib/moin";
+  usingGunicorn = cfg.webServer == "nginx-gunicorn" || cfg.webServer == "gunicorn";
+  usingNginx = cfg.webServer == "nginx-gunicorn";
+  user = "moin";
+  group = "moin";
+
+  uLit = s: ''u"${s}"'';
+  indentLines = n: str: concatMapStrings (line: "${fixedWidthString n " " " "}${line}\n") (splitString "\n" str);
+
+  moinCliWrapper = wikiIdent: pkgs.writeShellScriptBin "moin-${wikiIdent}" ''
+    ${pkgs.su}/bin/su -s ${pkgs.runtimeShell} -c "${pkg}/bin/moin --config-dir=/var/lib/moin/${wikiIdent}/config $*" ${user}
+  '';
+
+  wikiConfig = wikiIdent: w: ''
+    # -*- coding: utf-8 -*-
+
+    from MoinMoin.config import multiconfig, url_prefix_static
+
+    class Config(multiconfig.DefaultConfig):
+        ${optionalString (w.webLocation != "/") ''
+          url_prefix_static = '${w.webLocation}' + url_prefix_static
+        ''}
+
+        sitename = u'${w.siteName}'
+        page_front_page = u'${w.frontPage}'
+
+        data_dir = '${dataDir}/${wikiIdent}/data'
+        data_underlay_dir = '${dataDir}/${wikiIdent}/underlay'
+
+        language_default = u'${w.languageDefault}'
+        ${optionalString (w.superUsers != []) ''
+          superuser = [${concatMapStringsSep ", " uLit w.superUsers}]
+        ''}
+
+    ${indentLines 4 w.extraConfig}
+  '';
+  wikiConfigFile = name: wiki: pkgs.writeText "${name}.py" (wikiConfig name wiki);
+
+in
+{
+  options.services.moinmoin = with types; {
+    enable = mkEnableOption "MoinMoin Wiki Engine";
+
+    webServer = mkOption {
+      type = enum [ "nginx-gunicorn" "gunicorn" "none" ];
+      default = "nginx-gunicorn";
+      example = "none";
+      description = ''
+        Which web server to use to serve the wiki.
+        Use <literal>none</literal> if you want to configure this yourself.
+      '';
+    };
+
+    gunicorn.workers = mkOption {
+      type = ints.positive;
+      default = 3;
+      example = 10;
+      description = ''
+        The number of worker processes for handling requests.
+      '';
+    };
+
+    wikis = mkOption {
+      type = attrsOf (submodule ({ name, ... }: {
+        options = {
+          siteName = mkOption {
+            type = str;
+            default = "Untitled Wiki";
+            example = "ExampleWiki";
+            description = ''
+              Short description of your wiki site, displayed below the logo on each page, and
+              used in RSS documents as the channel title.
+            '';
+          };
+
+          webHost = mkOption {
+            type = str;
+            description = "Host part of the wiki URL. If undefined, the name of the attribute set will be used.";
+            example = "wiki.example.org";
+          };
+
+          webLocation = mkOption {
+            type = str;
+            default = "/";
+            example = "/moin";
+            description = "Location part of the wiki URL.";
+          };
+
+          frontPage = mkOption {
+            type = str;
+            default = "LanguageSetup";
+            example = "FrontPage";
+            description = ''
+              Front page name. Set this to something like <literal>FrontPage</literal> once languages are
+              configured.
+            '';
+          };
+
+          superUsers = mkOption {
+            type = listOf str;
+            default = [];
+            example = [ "elvis" ];
+            description = ''
+              List of trusted user names with wiki system administration super powers.
+
+              Please note that accounts for these users need to be created using the <command>moin</command> command-line utility, e.g.:
+              <command>moin-<replaceable>WIKINAME</replaceable> account create --name=<replaceable>NAME</replaceable> --email=<replaceable>EMAIL</replaceable> --password=<replaceable>PASSWORD</replaceable></command>.
+            '';
+          };
+
+          languageDefault = mkOption {
+            type = str;
+            default = "en";
+            example = "de";
+            description = "The ISO-639-1 name of the main wiki language. Languages that MoinMoin does not support are ignored.";
+          };
+
+          extraConfig = mkOption {
+            type = lines;
+            default = "";
+            example = ''
+              show_hosts = True
+              search_results_per_page = 100
+              acl_rights_default = u"Known:read,write,delete,revert All:read"
+              logo_string = u"<h2>\U0001f639</h2>"
+              theme_default = u"modernized"
+
+              user_checkbox_defaults = {'show_page_trail': 0, 'edit_on_doubleclick': 0}
+              navi_bar = [u'SomePage'] + multiconfig.DefaultConfig.navi_bar
+              actions_excluded = multiconfig.DefaultConfig.actions_excluded + ['newaccount']
+
+              mail_smarthost = "mail.example.org"
+              mail_from = u"Example.Org Wiki <wiki@example.org>"
+            '';
+            description = ''
+              Additional configuration to be appended verbatim to this wiki's config.
+
+              See <link xlink:href='http://moinmo.in/HelpOnConfiguration' /> for documentation.
+            '';
+          };
+
+        };
+        config = {
+          webHost = mkDefault name;
+        };
+      }));
+      example = literalExample ''
+        {
+          "mywiki" = {
+            siteName = "Example Wiki";
+            webHost = "wiki.example.org";
+            superUsers = [ "admin" ];
+            frontPage = "Index";
+            extraConfig = "page_category_regex = ur'(?P<all>(Category|Kategorie)(?P<key>(?!Template)\S+))'"
+          };
+        }
+      '';
+      description = ''
+        Configurations of the individual wikis. Attribute names must be valid Python
+        identifiers of the form <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.
+
+        For every attribute <replaceable>WIKINAME</replaceable>, a helper script
+        moin-<replaceable>WIKINAME</replaceable> is created which runs the
+        <command>moin</command> command under the <literal>moin</literal> user (to avoid
+        file ownership issues) and with the right configuration directory passed to it.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = forEach (attrNames cfg.wikis) (wname:
+      { assertion = builtins.match "[A-Za-z_][A-Za-z0-9_]*" wname != null;
+        message = "${wname} is not valid Python identifier";
+      }
+    );
+
+    users.users = {
+      moin = {
+        description = "MoinMoin wiki";
+        home = dataDir;
+        group = group;
+        isSystemUser = true;
+      };
+    };
+
+    users.groups = {
+      moin = {
+        members = mkIf usingNginx [ config.services.nginx.user ];
+      };
+    };
+
+    environment.systemPackages = [ pkg ] ++ map moinCliWrapper (attrNames cfg.wikis);
+
+    systemd.services = mkIf usingGunicorn
+      (flip mapAttrs' cfg.wikis (wikiIdent: wiki:
+        nameValuePair "moin-${wikiIdent}"
+          {
+            description = "MoinMoin wiki ${wikiIdent} - gunicorn process";
+            wantedBy = [ "multi-user.target" ];
+            after = [ "network.target" ];
+            restartIfChanged = true;
+            restartTriggers = [ (wikiConfigFile wikiIdent wiki) ];
+
+            environment = let
+              penv = python.buildEnv.override {
+                # setuptools: https://github.com/benoitc/gunicorn/issues/1716
+                extraLibs = [ python.pkgs.gevent python.pkgs.setuptools pkg ];
+              };
+            in {
+              PYTHONPATH = "${dataDir}/${wikiIdent}/config:${penv}/${python.sitePackages}";
+            };
+
+            preStart = ''
+              umask 0007
+              rm -rf ${dataDir}/${wikiIdent}/underlay
+              cp -r ${pkg}/share/moin/underlay ${dataDir}/${wikiIdent}/
+              chmod -R u+w ${dataDir}/${wikiIdent}/underlay
+            '';
+
+            serviceConfig = {
+              User = user;
+              Group = group;
+              WorkingDirectory = "${dataDir}/${wikiIdent}";
+              ExecStart = ''${python.pkgs.gunicorn}/bin/gunicorn moin_wsgi \
+                --name gunicorn-${wikiIdent} \
+                --workers ${toString cfg.gunicorn.workers} \
+                --worker-class gevent \
+                --bind unix:/run/moin/${wikiIdent}/gunicorn.sock
+              '';
+
+              Restart = "on-failure";
+              RestartSec = "2s";
+              StartLimitIntervalSec = "30s";
+
+              StateDirectory = "moin/${wikiIdent}";
+              StateDirectoryMode = "0750";
+              RuntimeDirectory = "moin/${wikiIdent}";
+              RuntimeDirectoryMode = "0750";
+
+              NoNewPrivileges = true;
+              ProtectSystem = "strict";
+              ProtectHome = true;
+              PrivateTmp = true;
+              PrivateDevices = true;
+              PrivateNetwork = true;
+              ProtectKernelTunables = true;
+              ProtectKernelModules = true;
+              ProtectControlGroups = true;
+              RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+              RestrictNamespaces = true;
+              LockPersonality = true;
+              MemoryDenyWriteExecute = true;
+              RestrictRealtime = true;
+            };
+          }
+      ));
+
+    services.nginx = mkIf usingNginx {
+      enable = true;
+      virtualHosts = flip mapAttrs' cfg.wikis (name: w: nameValuePair w.webHost {
+        forceSSL = mkDefault true;
+        enableACME = mkDefault true;
+        locations."${w.webLocation}" = {
+          extraConfig = ''
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+            proxy_set_header X-Forwarded-Host $host;
+            proxy_set_header X-Forwarded-Server $host;
+
+            proxy_pass http://unix:/run/moin/${name}/gunicorn.sock;
+          '';
+        };
+      });
+    };
+
+    systemd.tmpfiles.rules = [
+      "d  /run/moin            0750 ${user} ${group} - -"
+      "d  ${dataDir}           0550 ${user} ${group} - -"
+    ]
+    ++ (concatLists (flip mapAttrsToList cfg.wikis (wikiIdent: wiki: [
+      "d  ${dataDir}/${wikiIdent}                      0750 ${user} ${group} - -"
+      "d  ${dataDir}/${wikiIdent}/config               0550 ${user} ${group} - -"
+      "L+ ${dataDir}/${wikiIdent}/config/wikiconfig.py -    -       -        - ${wikiConfigFile wikiIdent wiki}"
+      # needed in order to pass module name to gunicorn
+      "L+ ${dataDir}/${wikiIdent}/config/moin_wsgi.py  -    -       -        - ${pkg}/share/moin/server/moin.wsgi"
+      # seed data files
+      "C  ${dataDir}/${wikiIdent}/data                 0770 ${user} ${group} - ${pkg}/share/moin/data"
+      # fix nix store permissions
+      "Z  ${dataDir}/${wikiIdent}/data                 0770 ${user} ${group} - -"
+    ])));
+  };
+
+  meta.maintainers = with lib.maintainers; [ b42 ];
+}
diff --git a/nixos/modules/services/web-apps/trac.nix b/nixos/modules/services/web-apps/trac.nix
new file mode 100644
index 00000000000..207fb857438
--- /dev/null
+++ b/nixos/modules/services/web-apps/trac.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.trac;
+
+  inherit (lib) mkEnableOption mkIf mkOption types;
+
+in {
+
+  options = {
+
+    services.trac = {
+      enable = mkEnableOption "Trac service";
+
+      listen = {
+        ip = mkOption {
+          type = types.str;
+          default = "0.0.0.0";
+          description = ''
+            IP address that Trac should listen on.
+          '';
+        };
+
+        port = mkOption {
+          type = types.port;
+          default = 8000;
+          description = ''
+            Listen port for Trac.
+          '';
+        };
+      };
+
+      dataDir = mkOption {
+        default = "/var/lib/trac";
+        type = types.path;
+        description = ''
+            The directory for storing the Trac data.
+        '';
+      };
+
+      openFirewall = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Open ports in the firewall for Trac.
+        '';
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.trac = {
+      description = "Trac server";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        DynamicUser = true;
+        StateDirectory = baseNameOf cfg.dataDir;
+        ExecStart = ''
+          ${pkgs.trac}/bin/tracd -s \
+            -b ${toString cfg.listen.ip} \
+            -p ${toString cfg.listen.port} \
+            ${cfg.dataDir}
+        '';
+      };
+      preStart = ''
+        if [ ! -e ${cfg.dataDir}/VERSION ]; then
+          ${pkgs.trac}/bin/trac-admin ${cfg.dataDir} initenv Trac "sqlite:db/trac.db"
+        fi
+      '';
+    };
+
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedTCPPorts = [ cfg.listen.port ];
+    };
+
+  };
+}
diff --git a/nixos/modules/services/x11/hardware/digimend.nix b/nixos/modules/services/x11/hardware/digimend.nix
new file mode 100644
index 00000000000..a9f5640905a
--- /dev/null
+++ b/nixos/modules/services/x11/hardware/digimend.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.xserver.digimend;
+
+  pkg = config.boot.kernelPackages.digimend;
+
+in
+
+{
+
+  options = {
+
+    services.xserver.digimend = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to enable the digimend drivers for Huion/XP-Pen/etc. tablets.
+        '';
+      };
+
+    };
+
+  };
+
+
+  config = mkIf cfg.enable {
+
+    # digimend drivers use xsetwacom and wacom X11 drivers
+    services.xserver.wacom.enable = true;
+
+    boot.extraModulePackages = [ pkg ];
+
+    environment.etc."X11/xorg.conf.d/50-digimend.conf".source =
+      "${pkg}/usr/share/X11/xorg.conf.d/50-digimend.conf";
+
+  };
+
+}
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index ed3431554be..e313d2b411b 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -23,24 +23,56 @@ let
 
   cfg = config.virtualisation;
 
-  qemuGraphics = lib.optionalString (!cfg.graphics) "-nographic";
-
   consoles = lib.concatMapStringsSep " " (c: "console=${c}") cfg.qemu.consoles;
 
-  # XXX: This is very ugly and in the future we really should use attribute
-  # sets to build ALL of the QEMU flags instead of this mixed mess of Nix
-  # expressions and shell script stuff.
-  mkDiskIfaceDriveFlag = idx: driveArgs: let
-    inherit (cfg.qemu) diskInterface;
-    # The drive identifier created by incrementing the index by one using the
-    # shell.
-    drvId = "drive$((${idx} + 1))";
-    # NOTE: DO NOT shell escape, because this may contain shell variables.
-    commonArgs = "index=${idx},id=${drvId},${driveArgs}";
-    isSCSI = diskInterface == "scsi";
-    devArgs = "${diskInterface}-hd,drive=${drvId}";
-    args = "-drive ${commonArgs},if=none -device lsi53c895a -device ${devArgs}";
-  in if isSCSI then args else "-drive ${commonArgs},if=${diskInterface}";
+  driveOpts = { ... }: {
+
+    options = {
+
+      file = mkOption {
+        type = types.str;
+        description = "The file image used for this drive.";
+      };
+
+      driveExtraOpts = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        description = "Extra options passed to drive flag.";
+      };
+
+      deviceExtraOpts = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        description = "Extra options passed to device flag.";
+      };
+
+    };
+
+  };
+
+  driveCmdline = idx: { file, driveExtraOpts, deviceExtraOpts, ... }:
+    let
+      drvId = "drive${toString idx}";
+      mkKeyValue = generators.mkKeyValueDefault {} "=";
+      mkOpts = opts: concatStringsSep "," (mapAttrsToList mkKeyValue opts);
+      driveOpts = mkOpts (driveExtraOpts // {
+        index = idx;
+        id = drvId;
+        "if" = "none";
+        inherit file;
+      });
+      deviceOpts = mkOpts (deviceExtraOpts // {
+        drive = drvId;
+      });
+      device =
+        if cfg.qemu.diskInterface == "scsi" then
+          "-device lsi53c895a -device scsi-hd,${deviceOpts}"
+        else
+          "-device virtio-blk-pci,${deviceOpts}";
+    in
+      "-drive ${driveOpts} ${device}";
+
+  drivesCmdLine = drives: concatStringsSep " " (imap1 driveCmdline drives);
 
   # Shell script to start the VM.
   startVM =
@@ -77,13 +109,11 @@ let
       ''}
 
       cd $TMPDIR
-      idx=2
-      extraDisks=""
+      idx=0
       ${flip concatMapStrings cfg.emptyDiskImages (size: ''
         if ! test -e "empty$idx.qcow2"; then
             ${qemu}/bin/qemu-img create -f qcow2 "empty$idx.qcow2" "${toString size}M"
         fi
-        extraDisks="$extraDisks ${mkDiskIfaceDriveFlag "$idx" "file=$(pwd)/empty$idx.qcow2,werror=report"}"
         idx=$((idx + 1))
       '')}
 
@@ -97,21 +127,7 @@ let
           -virtfs local,path=/nix/store,security_model=none,mount_tag=store \
           -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
           -virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
-          ${if cfg.useBootLoader then ''
-            ${mkDiskIfaceDriveFlag "0" "file=$NIX_DISK_IMAGE,cache=writeback,werror=report"} \
-            ${mkDiskIfaceDriveFlag "1" "file=$TMPDIR/disk.img,media=disk"} \
-            ${if cfg.useEFIBoot then ''
-              -pflash $TMPDIR/bios.bin \
-            '' else ''
-            ''}
-          '' else ''
-            ${mkDiskIfaceDriveFlag "0" "file=$NIX_DISK_IMAGE,cache=writeback,werror=report"} \
-            -kernel ${config.system.build.toplevel}/kernel \
-            -initrd ${config.system.build.toplevel}/initrd \
-            -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS" \
-          ''} \
-          $extraDisks \
-          ${qemuGraphics} \
+          ${drivesCmdLine config.virtualisation.qemu.drives} \
           ${toString config.virtualisation.qemu.options} \
           $QEMU_OPTS \
           "$@"
@@ -367,6 +383,12 @@ in
           '';
         };
 
+      drives =
+        mkOption {
+          type = types.listOf (types.submodule driveOpts);
+          description = "Drives passed to qemu.";
+        };
+
       diskInterface =
         mkOption {
           default = "virtio";
@@ -476,8 +498,49 @@ in
 
     # FIXME: Consolidate this one day.
     virtualisation.qemu.options = mkMerge [
-      (mkIf (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ "-vga std" "-usb" "-device usb-tablet,bus=usb-bus.0" ])
-      (mkIf (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [ "-device virtio-gpu-pci" "-device usb-ehci,id=usb0" "-device usb-kbd" "-device usb-tablet" ])
+      (mkIf (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
+        "-vga std" "-usb" "-device usb-tablet,bus=usb-bus.0"
+      ])
+      (mkIf (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [
+        "-device virtio-gpu-pci" "-device usb-ehci,id=usb0" "-device usb-kbd" "-device usb-tablet"
+      ])
+      (mkIf (!cfg.useBootLoader) [
+        "-kernel ${config.system.build.toplevel}/kernel"
+        "-initrd ${config.system.build.toplevel}/initrd"
+        ''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"''
+      ])
+      (mkIf cfg.useEFIBoot [
+        "-pflash $TMPDIR/bios.bin"
+      ])
+      (mkIf (!cfg.graphics) [
+        "-nographic"
+      ])
+    ];
+
+    virtualisation.qemu.drives = mkMerge [
+      (mkIf cfg.useBootLoader [
+        {
+          file = "$NIX_DISK_IMAGE";
+          driveExtraOpts.cache = "writeback";
+          driveExtraOpts.werror = "report";
+        }
+        {
+          file = "$TMPDIR/disk.img";
+          driveExtraOpts.media = "disk";
+          deviceExtraOpts.bootindex = "1";
+        }
+      ])
+      (mkIf (!cfg.useBootLoader) [
+        {
+          file = "$NIX_DISK_IMAGE";
+          driveExtraOpts.cache = "writeback";
+          driveExtraOpts.werror = "report";
+        }
+      ])
+      (imap0 (idx: _: {
+        file = "$(pwd)/empty${toString idx}.qcow2";
+        driveExtraOpts.werror = "report";
+      }) cfg.emptyDiskImages)
     ];
 
     # Mount the host filesystem via 9P, and bind-mount the Nix store
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index 206d97849f0..6bd315ff1ea 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -1,6 +1,6 @@
 let
   commonConfig = ./common/letsencrypt/common.nix;
-in import ./make-test.nix {
+in import ./make-test-python.nix {
   name = "acme";
 
   nodes = rec {
@@ -90,39 +90,44 @@ in import ./make-test.nix {
       newServerSystem = nodes.webserver2.config.system.build.toplevel;
       switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test";
     in
-    # Note, waitForUnit does not work for oneshot services that do not have RemainAfterExit=true,
+    # Note, wait_for_unit does not work for oneshot services that do not have RemainAfterExit=true,
     # this is because a oneshot goes from inactive => activating => inactive, and never
     # reaches the active state. To work around this, we create some mock target units which
     # get pulled in by the oneshot units. The target units linger after activation, and hence we
     # can use them to probe that a oneshot fired. It is a bit ugly, but it is the best we can do
     ''
-      $client->start;
-      $letsencrypt->start;
-      $acmeStandalone->start;
-
-      $letsencrypt->waitForUnit("default.target");
-      $letsencrypt->waitForUnit("pebble.service");
-
-      subtest "can request certificate with HTTPS-01 challenge", sub {
-        $acmeStandalone->waitForUnit("default.target");
-        $acmeStandalone->succeed("systemctl start acme-standalone.com.service");
-        $acmeStandalone->waitForUnit("acme-finished-standalone.com.target");
-      };
-
-      $client->waitForUnit("default.target");
-
-      $client->succeed('curl https://acme-v02.api.letsencrypt.org:15000/roots/0 > /tmp/ca.crt');
-      $client->succeed('curl https://acme-v02.api.letsencrypt.org:15000/intermediate-keys/0 >> /tmp/ca.crt');
-
-      subtest "Can request certificate for nginx service", sub {
-        $webserver->waitForUnit("acme-finished-a.example.com.target");
-        $client->succeed('curl --cacert /tmp/ca.crt https://a.example.com/ | grep -qF "hello world"');
-      };
-
-      subtest "Can add another certificate for nginx service", sub {
-        $webserver->succeed("/run/current-system/fine-tune/child-1/bin/switch-to-configuration test");
-        $webserver->waitForUnit("acme-finished-b.example.com.target");
-        $client->succeed('curl --cacert /tmp/ca.crt https://b.example.com/ | grep -qF "hello world"');
-      };
+      client.start()
+      letsencrypt.start()
+      acmeStandalone.start()
+
+      letsencrypt.wait_for_unit("default.target")
+      letsencrypt.wait_for_unit("pebble.service")
+
+      with subtest("can request certificate with HTTPS-01 challenge"):
+          acmeStandalone.wait_for_unit("default.target")
+          acmeStandalone.succeed("systemctl start acme-standalone.com.service")
+          acmeStandalone.wait_for_unit("acme-finished-standalone.com.target")
+
+      client.wait_for_unit("default.target")
+
+      client.succeed("curl https://acme-v02.api.letsencrypt.org:15000/roots/0 > /tmp/ca.crt")
+      client.succeed(
+          "curl https://acme-v02.api.letsencrypt.org:15000/intermediate-keys/0 >> /tmp/ca.crt"
+      )
+
+      with subtest("Can request certificate for nginx service"):
+          webserver.wait_for_unit("acme-finished-a.example.com.target")
+          client.succeed(
+              "curl --cacert /tmp/ca.crt https://a.example.com/ | grep -qF 'hello world'"
+          )
+
+      with subtest("Can add another certificate for nginx service"):
+          webserver.succeed(
+              "/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
+          )
+          webserver.wait_for_unit("acme-finished-b.example.com.target")
+          client.succeed(
+              "curl --cacert /tmp/ca.crt https://b.example.com/ | grep -qF 'hello world'"
+          )
     '';
 }
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 744d7ed0f83..1d933153ffa 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -170,6 +170,7 @@ in
   minio = handleTest ./minio.nix {};
   minidlna = handleTest ./minidlna.nix {};
   misc = handleTest ./misc.nix {};
+  moinmoin = handleTest ./moinmoin.nix {};
   mongodb = handleTest ./mongodb.nix {};
   moodle = handleTest ./moodle.nix {};
   morty = handleTest ./morty.nix {};
@@ -280,6 +281,7 @@ in
   tinydns = handleTest ./tinydns.nix {};
   tor = handleTest ./tor.nix {};
   transmission = handleTest ./transmission.nix {};
+  trac = handleTest ./trac.nix {};
   trezord = handleTest ./trezord.nix {};
   trickster = handleTest ./trickster.nix {};
   udisks2 = handleTest ./udisks2.nix {};
diff --git a/nixos/tests/ammonite.nix b/nixos/tests/ammonite.nix
index fedfde233e8..1955e42be5f 100644
--- a/nixos/tests/ammonite.nix
+++ b/nixos/tests/ammonite.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, ...} : {
   name = "ammonite";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ nequissimus ];
@@ -13,8 +13,8 @@ import ./make-test.nix ({ pkgs, ...} : {
     };
 
   testScript = ''
-    startAll;
+    start_all()
 
-    $amm->succeed("amm -c 'val foo = 21; println(foo * 2)' | grep 42")
+    amm.succeed("amm -c 'val foo = 21; println(foo * 2)' | grep 42")
   '';
 })
diff --git a/nixos/tests/automysqlbackup.nix b/nixos/tests/automysqlbackup.nix
index ada104a34de..224b93862fb 100644
--- a/nixos/tests/automysqlbackup.nix
+++ b/nixos/tests/automysqlbackup.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, lib, ... }:
+import ./make-test-python.nix ({ pkgs, lib, ... }:
 
 {
   name = "automysqlbackup";
@@ -15,20 +15,24 @@ import ./make-test.nix ({ pkgs, lib, ... }:
     };
 
   testScript = ''
-    startAll;
+    start_all()
 
     # Need to have mysql started so that it can be populated with data.
-    $machine->waitForUnit("mysql.service");
-
-    # Wait for testdb to be fully populated (5 rows).
-    $machine->waitUntilSucceeds("mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5");
-
-    # Do a backup and wait for it to start
-    $machine->startJob("automysqlbackup.service");
-    $machine->waitForJob("automysqlbackup.service");
-
-    # wait for backup file and check that data appears in backup
-    $machine->waitForFile("/var/backup/mysql/daily/testdb");
-    $machine->succeed("${pkgs.gzip}/bin/zcat /var/backup/mysql/daily/testdb/daily_testdb_*.sql.gz | grep hello");
+    machine.wait_for_unit("mysql.service")
+
+    with subtest("Wait for testdb to be fully populated (5 rows)."):
+        machine.wait_until_succeeds(
+            "mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5"
+        )
+
+    with subtest("Do a backup and wait for it to start"):
+        machine.start_job("automysqlbackup.service")
+        machine.wait_for_job("automysqlbackup.service")
+
+    with subtest("wait for backup file and check that data appears in backup"):
+        machine.wait_for_file("/var/backup/mysql/daily/testdb")
+        machine.succeed(
+            "${pkgs.gzip}/bin/zcat /var/backup/mysql/daily/testdb/daily_testdb_*.sql.gz | grep hello"
+        )
     '';
 })
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 3b1169a1b7f..e5be652c711 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -6,7 +6,7 @@
 # which only works if the first client successfully uses the UPnP-IGD
 # protocol to poke a hole in the NAT.
 
-import ./make-test.nix ({ pkgs, ... }:
+import ./make-test-python.nix ({ pkgs, ... }:
 
 let
 
@@ -108,42 +108,56 @@ in
   testScript =
     { nodes, ... }:
     ''
-      startAll;
+      start_all()
 
       # Wait for network and miniupnpd.
-      $router->waitForUnit("network-online.target");
-      $router->waitForUnit("miniupnpd");
+      router.wait_for_unit("network-online.target")
+      router.wait_for_unit("miniupnpd")
 
       # Create the torrent.
-      $tracker->succeed("mkdir /tmp/data");
-      $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2");
-      $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent");
-      $tracker->succeed("chmod 644 /tmp/test.torrent");
+      tracker.succeed("mkdir /tmp/data")
+      tracker.succeed(
+          "cp ${file} /tmp/data/test.tar.bz2"
+      )
+      tracker.succeed(
+          "transmission-create /tmp/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent"
+      )
+      tracker.succeed("chmod 644 /tmp/test.torrent")
 
       # Start the tracker.  !!! use a less crappy tracker
-      $tracker->waitForUnit("network-online.target");
-      $tracker->waitForUnit("opentracker.service");
-      $tracker->waitForOpenPort(6969);
+      tracker.wait_for_unit("network-online.target")
+      tracker.wait_for_unit("opentracker.service")
+      tracker.wait_for_open_port(6969)
 
       # Start the initial seeder.
-      $tracker->succeed("transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir /tmp/data");
+      tracker.succeed(
+          "transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir /tmp/data"
+      )
 
       # Now we should be able to download from the client behind the NAT.
-      $tracker->waitForUnit("httpd");
-      $client1->waitForUnit("network-online.target");
-      $client1->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --download-dir /tmp >&2 &");
-      $client1->waitForFile("/tmp/test.tar.bz2");
-      $client1->succeed("cmp /tmp/test.tar.bz2 ${file}");
+      tracker.wait_for_unit("httpd")
+      client1.wait_for_unit("network-online.target")
+      client1.succeed(
+          "transmission-remote --add http://${externalTrackerAddress}/test.torrent --download-dir /tmp >&2 &"
+      )
+      client1.wait_for_file("/tmp/test.tar.bz2")
+      client1.succeed(
+          "cmp /tmp/test.tar.bz2 ${file}"
+      )
 
       # Bring down the initial seeder.
-      # $tracker->stopJob("transmission");
+      # tracker.stop_job("transmission")
 
       # Now download from the second client.  This can only succeed if
       # the first client created a NAT hole in the router.
-      $client2->waitForUnit("network-online.target");
-      $client2->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht --download-dir /tmp >&2 &");
-      $client2->waitForFile("/tmp/test.tar.bz2");
-      $client2->succeed("cmp /tmp/test.tar.bz2 ${file}");
+      client2.wait_for_unit("network-online.target")
+      client2.succeed(
+          "transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht --download-dir /tmp >&2 &"
+      )
+      client2.wait_for_file("/tmp/test.tar.bz2")
+      client2.succeed(
+          "cmp /tmp/test.tar.bz2 ${file}"
+      )
     '';
 
 })
diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix
index 57d8006d7ac..c5040f3b31f 100644
--- a/nixos/tests/boot.nix
+++ b/nixos/tests/boot.nix
@@ -3,7 +3,7 @@
   pkgs ? import ../.. { inherit system config; }
 }:
 
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
 with pkgs.lib;
 
 let
@@ -17,11 +17,11 @@ let
         ];
     }).config.system.build.isoImage;
 
-  perlAttrs = params: "{ ${concatStringsSep ", " (mapAttrsToList (name: param: "${name} => ${builtins.toJSON param}") params)} }";
+  pythonDict = params: "\n    {\n        ${concatStringsSep ",\n        " (mapAttrsToList (name: param: "\"${name}\": \"${param}\"") params)},\n    }\n";
 
   makeBootTest = name: extraConfig:
     let
-      machineConfig = perlAttrs ({ qemuFlags = "-m 768"; } // extraConfig);
+      machineConfig = pythonDict ({ qemuFlags = "-m 768"; } // extraConfig);
     in
       makeTest {
         inherit iso;
@@ -29,16 +29,16 @@ let
         nodes = { };
         testScript =
           ''
-            my $machine = createMachine(${machineConfig});
-            $machine->start;
-            $machine->waitForUnit("multi-user.target");
-            $machine->succeed("nix verify -r --no-trust /run/current-system");
+            machine = create_machine(${machineConfig})
+            machine.start()
+            machine.wait_for_unit("multi-user.target")
+            machine.succeed("nix verify -r --no-trust /run/current-system")
 
-            # Test whether the channel got installed correctly.
-            $machine->succeed("nix-instantiate --dry-run '<nixpkgs>' -A hello");
-            $machine->succeed("nix-env --dry-run -iA nixos.procps");
+            with subtest("Check whether the channel got installed correctly"):
+                machine.succeed("nix-instantiate --dry-run '<nixpkgs>' -A hello")
+                machine.succeed("nix-env --dry-run -iA nixos.procps")
 
-            $machine->shutdown;
+            machine.shutdown()
           '';
       };
 
@@ -60,7 +60,7 @@ let
           config.system.build.netbootIpxeScript
         ];
       };
-      machineConfig = perlAttrs ({
+      machineConfig = pythonDict ({
         qemuFlags = "-boot order=n -m 2000";
         netBackendArgs = "tftp=${ipxeBootDir},bootfile=netboot.ipxe";
       } // extraConfig);
@@ -68,12 +68,11 @@ let
       makeTest {
         name = "boot-netboot-" + name;
         nodes = { };
-        testScript =
-          ''
-            my $machine = createMachine(${machineConfig});
-            $machine->start;
-            $machine->waitForUnit("multi-user.target");
-            $machine->shutdown;
+        testScript = ''
+            machine = create_machine(${machineConfig})
+            machine.start()
+            machine.wait_for_unit("multi-user.target")
+            machine.shutdown()
           '';
       };
 in {
diff --git a/nixos/tests/emacs-daemon.nix b/nixos/tests/emacs-daemon.nix
index 3594e35e343..b89d9b1bde6 100644
--- a/nixos/tests/emacs-daemon.nix
+++ b/nixos/tests/emacs-daemon.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, ...} : {
   name = "emacs-daemon";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ ];
@@ -21,25 +21,28 @@ import ./make-test.nix ({ pkgs, ...} : {
       environment.variables.TEST_SYSTEM_VARIABLE = "system variable";
     };
 
-  testScript =
-    ''
-      $machine->waitForUnit("multi-user.target");
+  testScript = ''
+      machine.wait_for_unit("multi-user.target")
 
       # checks that the EDITOR environment variable is set
-      $machine->succeed("test \$(basename \"\$EDITOR\") = emacseditor");
+      machine.succeed('test $(basename "$EDITOR") = emacseditor')
 
       # waits for the emacs service to be ready
-      $machine->waitUntilSucceeds("systemctl --user status emacs.service | grep 'Active: active'");
+      machine.wait_until_succeeds(
+          "systemctl --user status emacs.service | grep 'Active: active'"
+      )
 
       # connects to the daemon
-      $machine->succeed("emacsclient --create-frame \$EDITOR &");
+      machine.succeed("emacsclient --create-frame $EDITOR &")
 
       # checks that Emacs shows the edited filename
-      $machine->waitForText("emacseditor");
+      machine.wait_for_text("emacseditor")
 
       # makes sure environment variables are accessible from Emacs
-      $machine->succeed("emacsclient --eval '(getenv \"TEST_SYSTEM_VARIABLE\")'") =~ /system variable/ or die;
+      machine.succeed(
+          "emacsclient --eval '(getenv \"TEST_SYSTEM_VARIABLE\")' | grep -q 'system variable'"
+      )
 
-      $machine->screenshot("emacsclient");
+      machine.screenshot("emacsclient")
     '';
 })
diff --git a/nixos/tests/gitea.nix b/nixos/tests/gitea.nix
index b8ab6dabc8c..ffbc07cfbb2 100644
--- a/nixos/tests/gitea.nix
+++ b/nixos/tests/gitea.nix
@@ -3,7 +3,7 @@
   pkgs ? import ../.. { inherit system config; }
 }:
 
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
 with pkgs.lib;
 
 {
@@ -18,11 +18,11 @@ with pkgs.lib;
       };
 
     testScript = ''
-      startAll;
+      start_all()
 
-      $machine->waitForUnit('gitea.service');
-      $machine->waitForOpenPort('3000');
-      $machine->succeed("curl --fail http://localhost:3000/");
+      machine.wait_for_unit("gitea.service")
+      machine.wait_for_open_port(3000)
+      machine.succeed("curl --fail http://localhost:3000/")
     '';
   };
 
@@ -37,11 +37,11 @@ with pkgs.lib;
       };
 
     testScript = ''
-      startAll;
+      start_all()
 
-      $machine->waitForUnit('gitea.service');
-      $machine->waitForOpenPort('3000');
-      $machine->succeed("curl --fail http://localhost:3000/");
+      machine.wait_for_unit("gitea.service")
+      machine.wait_for_open_port(3000)
+      machine.succeed("curl --fail http://localhost:3000/")
     '';
   };
 
@@ -56,12 +56,14 @@ with pkgs.lib;
       };
 
     testScript = ''
-      startAll;
+      start_all()
 
-      $machine->waitForUnit('gitea.service');
-      $machine->waitForOpenPort('3000');
-      $machine->succeed("curl --fail http://localhost:3000/");
-      $machine->succeed("curl --fail http://localhost:3000/user/sign_up | grep 'Registration is disabled. Please contact your site administrator.'");
+      machine.wait_for_unit("gitea.service")
+      machine.wait_for_open_port(3000)
+      machine.succeed("curl --fail http://localhost:3000/")
+      machine.succeed(
+          "curl --fail http://localhost:3000/user/sign_up | grep 'Registration is disabled. Please contact your site administrator.'"
+      )
     '';
   };
 }
diff --git a/nixos/tests/login.nix b/nixos/tests/login.nix
index bd8ed23a7b8..d36c1a91be4 100644
--- a/nixos/tests/login.nix
+++ b/nixos/tests/login.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, latestKernel ? false, ... }:
+import ./make-test-python.nix ({ pkgs, latestKernel ? false, ... }:
 
 {
   name = "login";
@@ -12,62 +12,48 @@ import ./make-test.nix ({ pkgs, latestKernel ? false, ... }:
       sound.enable = true; # needed for the factl test, /dev/snd/* exists without them but udev doesn't care then
     };
 
-  testScript =
-    ''
-      $machine->waitForUnit('multi-user.target');
-      $machine->waitUntilSucceeds("pgrep -f 'agetty.*tty1'");
-      $machine->screenshot("postboot");
-
-      subtest "create user", sub {
-          $machine->succeed("useradd -m alice");
-          $machine->succeed("(echo foobar; echo foobar) | passwd alice");
-      };
-
-      # Check whether switching VTs works.
-      subtest "virtual console switching", sub {
-          $machine->fail("pgrep -f 'agetty.*tty2'");
-          $machine->sendKeys("alt-f2");
-          $machine->waitUntilSucceeds("[ \$(fgconsole) = 2 ]");
-          $machine->waitForUnit('getty@tty2.service');
-          $machine->waitUntilSucceeds("pgrep -f 'agetty.*tty2'");
-      };
-
-      # Log in as alice on a virtual console.
-      subtest "virtual console login", sub {
-          $machine->waitUntilTTYMatches(2, "login: ");
-          $machine->sendChars("alice\n");
-          $machine->waitUntilTTYMatches(2, "login: alice");
-          $machine->waitUntilSucceeds("pgrep login");
-          $machine->waitUntilTTYMatches(2, "Password: ");
-          $machine->sendChars("foobar\n");
-          $machine->waitUntilSucceeds("pgrep -u alice bash");
-          $machine->sendChars("touch done\n");
-          $machine->waitForFile("/home/alice/done");
-      };
-
-      # Check whether systemd gives and removes device ownership as
-      # needed.
-      subtest "device permissions", sub {
-          $machine->succeed("getfacl -p /dev/snd/timer | grep -q alice");
-          $machine->sendKeys("alt-f1");
-          $machine->waitUntilSucceeds("[ \$(fgconsole) = 1 ]");
-          $machine->fail("getfacl -p /dev/snd/timer | grep -q alice");
-          $machine->succeed("chvt 2");
-          $machine->waitUntilSucceeds("getfacl -p /dev/snd/timer | grep -q alice");
-      };
-
-      # Log out.
-      subtest "virtual console logout", sub {
-          $machine->sendChars("exit\n");
-          $machine->waitUntilFails("pgrep -u alice bash");
-          $machine->screenshot("mingetty");
-      };
-
-      # Check whether ctrl-alt-delete works.
-      subtest "ctrl-alt-delete", sub {
-          $machine->sendKeys("ctrl-alt-delete");
-          $machine->waitForShutdown;
-      };
-    '';
-
+  testScript = ''
+      machine.wait_for_unit("multi-user.target")
+      machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
+      machine.screenshot("postboot")
+
+      with subtest("create user"):
+          machine.succeed("useradd -m alice")
+          machine.succeed("(echo foobar; echo foobar) | passwd alice")
+
+      with subtest("Check whether switching VTs works"):
+          machine.fail("pgrep -f 'agetty.*tty2'")
+          machine.send_key("alt-f2")
+          machine.wait_until_succeeds("[ $(fgconsole) = 2 ]")
+          machine.wait_for_unit("getty@tty2.service")
+          machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
+
+      with subtest("Log in as alice on a virtual console"):
+          machine.wait_until_tty_matches(2, "login: ")
+          machine.send_chars("alice\n")
+          machine.wait_until_tty_matches(2, "login: alice")
+          machine.wait_until_succeeds("pgrep login")
+          machine.wait_until_tty_matches(2, "Password: ")
+          machine.send_chars("foobar\n")
+          machine.wait_until_succeeds("pgrep -u alice bash")
+          machine.send_chars("touch done\n")
+          machine.wait_for_file("/home/alice/done")
+
+      with subtest("Systemd gives and removes device ownership as needed"):
+          machine.succeed("getfacl /dev/snd/timer | grep -q alice")
+          machine.send_key("alt-f1")
+          machine.wait_until_succeeds("[ $(fgconsole) = 1 ]")
+          machine.fail("getfacl /dev/snd/timer | grep -q alice")
+          machine.succeed("chvt 2")
+          machine.wait_until_succeeds("getfacl /dev/snd/timer | grep -q alice")
+
+      with subtest("Virtual console logout"):
+          machine.send_chars("exit\n")
+          machine.wait_until_fails("pgrep -u alice bash")
+          machine.screenshot("mingetty")
+
+      with subtest("Check whether ctrl-alt-delete works"):
+          machine.send_key("ctrl-alt-delete")
+          machine.wait_for_shutdown()
+  '';
 })
diff --git a/nixos/tests/make-test-python.nix b/nixos/tests/make-test-python.nix
new file mode 100644
index 00000000000..89897fe7e61
--- /dev/null
+++ b/nixos/tests/make-test-python.nix
@@ -0,0 +1,9 @@
+f: {
+  system ? builtins.currentSystem,
+  pkgs ? import ../.. { inherit system; config = {}; },
+  ...
+} @ args:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+
+makeTest (if pkgs.lib.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
diff --git a/nixos/tests/moinmoin.nix b/nixos/tests/moinmoin.nix
new file mode 100644
index 00000000000..2662b79aa09
--- /dev/null
+++ b/nixos/tests/moinmoin.nix
@@ -0,0 +1,24 @@
+import ./make-test.nix ({ pkgs, lib, ... }: {
+  name = "moinmoin";
+  meta.maintainers = [ ]; # waiting for https://github.com/NixOS/nixpkgs/pull/65397
+
+  machine =
+    { ... }:
+    { services.moinmoin.enable = true;
+      services.moinmoin.wikis.ExampleWiki.superUsers = [ "admin" ];
+      services.moinmoin.wikis.ExampleWiki.webHost = "localhost";
+
+      services.nginx.virtualHosts.localhost.enableACME = false;
+      services.nginx.virtualHosts.localhost.forceSSL = false;
+    };
+
+  testScript = ''
+    startAll;
+
+    $machine->waitForUnit('moin-ExampleWiki.service');
+    $machine->waitForUnit('nginx.service');
+    $machine->waitForFile('/run/moin/ExampleWiki/gunicorn.sock');
+    $machine->succeed('curl -L http://localhost/') =~ /If you have just installed/ or die;
+    $machine->succeed('moin-ExampleWiki account create --name=admin --email=admin@example.com --password=foo 2>&1') =~ /status success/ or die;
+  '';
+})
diff --git a/nixos/tests/postgresql.nix b/nixos/tests/postgresql.nix
index ae5d6d095ea..e71c3888288 100644
--- a/nixos/tests/postgresql.nix
+++ b/nixos/tests/postgresql.nix
@@ -3,7 +3,7 @@
   pkgs ? import ../.. { inherit system config; }
 }:
 
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
 with pkgs.lib;
 
 let
@@ -40,29 +40,33 @@ let
       backupName = if backup-all then "all" else "postgres";
       backupService = if backup-all then "postgresqlBackup" else "postgresqlBackup-postgres";
     in ''
-      sub check_count {
-        my ($select, $nlines) = @_;
-        return 'test $(sudo -u postgres psql postgres -tAc "' . $select . '"|wc -l) -eq ' . $nlines;
-      }
+      def check_count(statement, lines):
+          return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format(
+              statement, lines
+          )
+
+
+      machine.start()
+      machine.wait_for_unit("postgresql")
 
-      $machine->start;
-      $machine->waitForUnit("postgresql");
       # postgresql should be available just after unit start
-      $machine->succeed("cat ${test-sql} | sudo -u postgres psql");
-      $machine->shutdown; # make sure that postgresql survive restart (bug #1735)
-      sleep(2);
-      $machine->start;
-      $machine->waitForUnit("postgresql");
-      $machine->fail(check_count("SELECT * FROM sth;", 3));
-      $machine->succeed(check_count("SELECT * FROM sth;", 5));
-      $machine->fail(check_count("SELECT * FROM sth;", 4));
-      $machine->succeed(check_count("SELECT xpath(\'/test/text()\', doc) FROM xmltest;", 1));
+      machine.succeed(
+          "cat ${test-sql} | sudo -u postgres psql"
+      )
+      machine.shutdown()  # make sure that postgresql survive restart (bug #1735)
+      time.sleep(2)
+      machine.start()
+      machine.wait_for_unit("postgresql")
+      machine.fail(check_count("SELECT * FROM sth;", 3))
+      machine.succeed(check_count("SELECT * FROM sth;", 5))
+      machine.fail(check_count("SELECT * FROM sth;", 4))
+      machine.succeed(check_count("SELECT xpath('/test/text()', doc) FROM xmltest;", 1))
 
       # Check backup service
-      $machine->succeed("systemctl start ${backupService}.service");
-      $machine->succeed("zcat /var/backup/postgresql/${backupName}.sql.gz | grep '<test>ok</test>'");
-      $machine->succeed("stat -c '%a' /var/backup/postgresql/${backupName}.sql.gz | grep 600");
-      $machine->shutdown;
+      machine.succeed("systemctl start ${backupService}.service")
+      machine.succeed("zcat /var/backup/postgresql/${backupName}.sql.gz | grep '<test>ok</test>'")
+      machine.succeed("stat -c '%a' /var/backup/postgresql/${backupName}.sql.gz | grep 600")
+      machine.shutdown()
     '';
 
   };
diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix
index 4253ce4a867..4d57e219790 100644
--- a/nixos/tests/quake3.nix
+++ b/nixos/tests/quake3.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ...} :
+import ./make-test-python.nix ({ pkgs, ...} :
 
 let
 
@@ -59,37 +59,37 @@ rec {
 
   testScript =
     ''
-      startAll;
+      start_all()
 
-      $server->waitForUnit("quake3-server");
-      $client1->waitForX;
-      $client2->waitForX;
+      server.wait_for_unit("quake3-server")
+      client1.wait_for_x()
+      client2.wait_for_x()
 
-      $client1->execute("quake3 +set r_fullscreen 0 +set name Foo +connect server &");
-      $client2->execute("quake3 +set r_fullscreen 0 +set name Bar +connect server &");
+      client1.execute("quake3 +set r_fullscreen 0 +set name Foo +connect server &")
+      client2.execute("quake3 +set r_fullscreen 0 +set name Bar +connect server &")
 
-      $server->waitUntilSucceeds("grep -q 'Foo.*entered the game' /tmp/log");
-      $server->waitUntilSucceeds("grep -q 'Bar.*entered the game' /tmp/log");
+      server.wait_until_succeeds("grep -q 'Foo.*entered the game' /tmp/log")
+      server.wait_until_succeeds("grep -q 'Bar.*entered the game' /tmp/log")
 
-      $server->sleep(10); # wait for a while to get a nice screenshot
+      server.sleep(10)  # wait for a while to get a nice screenshot
 
-      $client1->block();
+      client1.block()
 
-      $server->sleep(20);
+      server.sleep(20)
 
-      $client1->screenshot("screen1");
-      $client2->screenshot("screen2");
+      client1.screenshot("screen1")
+      client2.screenshot("screen2")
 
-      $client1->unblock();
+      client1.unblock()
 
-      $server->sleep(10);
+      server.sleep(10)
 
-      $client1->screenshot("screen3");
-      $client2->screenshot("screen4");
+      client1.screenshot("screen3")
+      client2.screenshot("screen4")
 
-      $client1->shutdown();
-      $client2->shutdown();
-      $server->stopJob("quake3-server");
+      client1.shutdown()
+      client2.shutdown()
+      server.stop_job("quake3-server")
     '';
 
 })
diff --git a/nixos/tests/trac.nix b/nixos/tests/trac.nix
new file mode 100644
index 00000000000..643095d947e
--- /dev/null
+++ b/nixos/tests/trac.nix
@@ -0,0 +1,19 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "trac";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ mmahut ];
+  };
+
+  nodes = {
+    machine = { ... }: {
+      services.trac.enable = true;
+    };
+  };
+
+  testScript = ''
+    startAll;
+    $machine->waitForUnit("trac.service");
+    $machine->waitForOpenPort(8000);
+    $machine->waitUntilSucceeds("curl -L http://localhost:8000/ | grep 'Trac Powered'");
+  '';
+})
diff --git a/nixos/tests/wireguard/default.nix b/nixos/tests/wireguard/default.nix
index b0797b96323..8206823a918 100644
--- a/nixos/tests/wireguard/default.nix
+++ b/nixos/tests/wireguard/default.nix
@@ -2,7 +2,7 @@ let
   wg-snakeoil-keys = import ./snakeoil-keys.nix;
 in
 
-import ../make-test.nix ({ pkgs, ...} : {
+import ../make-test-python.nix ({ pkgs, ...} : {
   name = "wireguard";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ ma27 ];
@@ -86,12 +86,12 @@ import ../make-test.nix ({ pkgs, ...} : {
   };
 
   testScript = ''
-    startAll;
+    start_all()
 
-    $peer0->waitForUnit("wireguard-wg0.service");
-    $peer1->waitForUnit("wireguard-wg0.service");
+    peer0.wait_for_unit("wireguard-wg0.service")
+    peer1.wait_for_unit("wireguard-wg0.service")
 
-    $peer1->succeed("ping -c5 fc00::1");
-    $peer1->succeed("ping -c5 10.23.42.1")
+    peer1.succeed("ping -c5 fc00::1")
+    peer1.succeed("ping -c5 10.23.42.1")
   '';
 })
diff --git a/nixos/tests/wireguard/generated.nix b/nixos/tests/wireguard/generated.nix
index 897feafe3ff..a29afd2d466 100644
--- a/nixos/tests/wireguard/generated.nix
+++ b/nixos/tests/wireguard/generated.nix
@@ -1,4 +1,4 @@
-import ../make-test.nix ({ pkgs, ...} : {
+import ../make-test-python.nix ({ pkgs, ...} : {
   name = "wireguard-generated";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ ma27 grahamc ];
@@ -28,30 +28,34 @@ import ../make-test.nix ({ pkgs, ...} : {
   };
 
   testScript = ''
-    startAll;
-
-    $peer1->waitForUnit("wireguard-wg0.service");
-    $peer2->waitForUnit("wireguard-wg0.service");
-
-    my ($retcode, $peer1pubkey) = $peer1->execute("wg pubkey < /etc/wireguard/private");
-    $peer1pubkey =~ s/\s+$//;
-    if ($retcode != 0) {
-      die "Could not read public key from peer1";
-    }
-
-    my ($retcode, $peer2pubkey) = $peer2->execute("wg pubkey < /etc/wireguard/private");
-    $peer2pubkey =~ s/\s+$//;
-    if ($retcode != 0) {
-      die "Could not read public key from peer2";
-    }
-
-    $peer1->succeed("wg set wg0 peer $peer2pubkey allowed-ips 10.10.10.2/32 endpoint 192.168.1.2:12345 persistent-keepalive 1");
-    $peer1->succeed("ip route replace 10.10.10.2/32 dev wg0 table main");
-
-    $peer2->succeed("wg set wg0 peer $peer1pubkey allowed-ips 10.10.10.1/32 endpoint 192.168.1.1:12345 persistent-keepalive 1");
-    $peer2->succeed("ip route replace 10.10.10.1/32 dev wg0 table main");
-
-    $peer1->succeed("ping -c1 10.10.10.2");
-    $peer2->succeed("ping -c1 10.10.10.1");
+    start_all()
+
+    peer1.wait_for_unit("wireguard-wg0.service")
+    peer2.wait_for_unit("wireguard-wg0.service")
+
+    retcode, peer1pubkey = peer1.execute("wg pubkey < /etc/wireguard/private")
+    if retcode != 0:
+        raise Exception("Could not read public key from peer1")
+
+    retcode, peer2pubkey = peer2.execute("wg pubkey < /etc/wireguard/private")
+    if retcode != 0:
+        raise Exception("Could not read public key from peer2")
+
+    peer1.succeed(
+        "wg set wg0 peer {} allowed-ips 10.10.10.2/32 endpoint 192.168.1.2:12345 persistent-keepalive 1".format(
+            peer2pubkey.strip()
+        )
+    )
+    peer1.succeed("ip route replace 10.10.10.2/32 dev wg0 table main")
+
+    peer2.succeed(
+        "wg set wg0 peer {} allowed-ips 10.10.10.1/32 endpoint 192.168.1.1:12345 persistent-keepalive 1".format(
+            peer1pubkey.strip()
+        )
+    )
+    peer2.succeed("ip route replace 10.10.10.1/32 dev wg0 table main")
+
+    peer1.succeed("ping -c1 10.10.10.2")
+    peer2.succeed("ping -c1 10.10.10.1")
   '';
 })
diff --git a/nixos/tests/zfs.nix b/nixos/tests/zfs.nix
index d7a08268e98..8f844aca416 100644
--- a/nixos/tests/zfs.nix
+++ b/nixos/tests/zfs.nix
@@ -7,7 +7,7 @@ with import ../lib/testing.nix { inherit system pkgs; };
 
 let
 
-  makeTest = import ./make-test.nix;
+  makeTest = import ./make-test-python.nix;
 
   makeZfsTest = name:
     { kernelPackage ? pkgs.linuxPackages_latest
@@ -34,12 +34,12 @@ let
         };
 
       testScript = ''
-        $machine->succeed("modprobe zfs");
-        $machine->succeed("zpool status");
+        machine.succeed("modprobe zfs")
+        machine.succeed("zpool status")
 
-        $machine->succeed("ls /dev");
+        machine.succeed("ls /dev")
 
-        $machine->succeed(
+        machine.succeed(
           "mkdir /tmp/mnt",
 
           "udevadm settle",
@@ -55,9 +55,7 @@ let
           "umount /tmp/mnt",
           "zpool destroy rpool",
           "udevadm settle"
-
-        );
-
+        )
       '' + extraTest;
 
     };
@@ -70,8 +68,8 @@ in {
   unstable = makeZfsTest "unstable" {
     enableUnstable = true;
     extraTest = ''
-      $machine->succeed(
-        "echo password | zpool create -o altroot='/tmp/mnt' -O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
+      machine.succeed(
+        "echo password | zpool create -o altroot=\"/tmp/mnt\" -O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
         "zfs create -o mountpoint=legacy rpool/root",
         "mount -t zfs rpool/root /tmp/mnt",
         "udevadm settle",
@@ -79,7 +77,7 @@ in {
         "umount /tmp/mnt",
         "zpool destroy rpool",
         "udevadm settle"
-      );
+      )
     '';
   };
 
diff --git a/pkgs/applications/audio/asunder/default.nix b/pkgs/applications/audio/asunder/default.nix
index e252635e953..5a0b6797a24 100644
--- a/pkgs/applications/audio/asunder/default.nix
+++ b/pkgs/applications/audio/asunder/default.nix
@@ -12,15 +12,15 @@
 with stdenv.lib;
 
 stdenv.mkDerivation rec {
-  version = "2.9.4";
+  version = "2.9.5";
   pname = "asunder";
   src = fetchurl {
     url = "http://littlesvr.ca/asunder/releases/${pname}-${version}.tar.bz2";
-    sha256 = "1bwc9v9l1f3kqjd7wis6g2sv6ibc618ybh0gsb8mkkfhadp68w30";
+    sha256 = "069x6az2r3wlb2hd07iz0hxpxwknw7s9h7pyhnkmzv1pw9ci3kk4";
   };
 
-  nativeBuildInputs = [ pkgconfig ];
-  buildInputs = [ gtk2 libcddb intltool makeWrapper ];
+  nativeBuildInputs = [ intltool makeWrapper pkgconfig ];
+  buildInputs = [ gtk2 libcddb ];
 
   runtimeDeps =
     optional mp3Support lame ++
diff --git a/pkgs/applications/audio/lollypop/default.nix b/pkgs/applications/audio/lollypop/default.nix
index f8a2aa8db76..8bdf45a968a 100644
--- a/pkgs/applications/audio/lollypop/default.nix
+++ b/pkgs/applications/audio/lollypop/default.nix
@@ -19,7 +19,7 @@
 
 python3.pkgs.buildPythonApplication rec  {
   pname = "lollypop";
-  version = "1.2.2";
+  version = "1.2.5";
 
   format = "other";
   doCheck = false;
@@ -28,7 +28,7 @@ python3.pkgs.buildPythonApplication rec  {
     url = "https://gitlab.gnome.org/World/lollypop";
     rev = "refs/tags/${version}";
     fetchSubmodules = true;
-    sha256 = "02dgp3b10yaw0yqzdzd15msjgxayvjkg9m652is0d7rwgjq1pk6v";
+    sha256 = "148p3ab7nnfz13hgjkx1cf2ahq9mgl72csrl35xy6d0nkfqbfr8r";
   };
 
   nativeBuildInputs = [
diff --git a/pkgs/applications/audio/yoshimi/default.nix b/pkgs/applications/audio/yoshimi/default.nix
index 74a59c0e963..b8acaa5a7e4 100644
--- a/pkgs/applications/audio/yoshimi/default.nix
+++ b/pkgs/applications/audio/yoshimi/default.nix
@@ -6,11 +6,11 @@ assert stdenv ? glibc;
 
 stdenv.mkDerivation  rec {
   pname = "yoshimi";
-  version = "1.6.0.1";
+  version = "1.6.0.2";
 
   src = fetchurl {
     url = "mirror://sourceforge/yoshimi/${pname}-${version}.tar.bz2";
-    sha256 = "140f2k4akj39pny8c7i794q125415gyvmy4rday0il5ncp3glik4";
+    sha256 = "0q2cw168r53r50zghkdqcxba2cybn44axbdkwacvkm7ag2z0j2l8";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/editors/quilter/default.nix b/pkgs/applications/editors/quilter/default.nix
index 7df036cc215..d9c3bd0825d 100644
--- a/pkgs/applications/editors/quilter/default.nix
+++ b/pkgs/applications/editors/quilter/default.nix
@@ -4,13 +4,13 @@
 
 stdenv.mkDerivation rec {
   pname = "quilter";
-  version = "2.0.2";
+  version = "2.0.3";
 
   src = fetchFromGitHub {
     owner = "lainsce";
     repo = pname;
     rev = version;
-    sha256 = "0qd8qssqzds06l08f4yf39i3bjl1ljyr85wgc3yn6mn698ynx30g";
+    sha256 = "13l8z3bchha4ax14s48pcqdxh8gnj4mlvv06lk9dwk9fplc93821";
   };
 
   nativeBuildInputs = [
diff --git a/pkgs/applications/graphics/freecad/default.nix b/pkgs/applications/graphics/freecad/default.nix
index ee7586709dc..eb087c42ce0 100644
--- a/pkgs/applications/graphics/freecad/default.nix
+++ b/pkgs/applications/graphics/freecad/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, mkDerivation, fetchurl, fetchpatch, cmake, ninja, coin3d, xercesc, ode
+{ stdenv, mkDerivation, fetchFromGitHub, fetchpatch, cmake, ninja, coin3d, xercesc, ode
 , eigen, qtbase, qttools, qtwebkit, opencascade-occt, gts, hdf5, vtk, medfile
 , zlib, python3Packages, swig, gfortran, libXmu, soqt, libf2c, libGLU
 , makeWrapper, pkgconfig, mpi ? null }:
@@ -9,11 +9,13 @@ let
   pythonPackages = python3Packages;
 in mkDerivation rec {
   pname = "freecad";
-  version = "0.18.3";
+  version = "0.18.4";
 
-  src = fetchurl {
-    url = "https://github.com/FreeCAD/FreeCAD/archive/${version}.tar.gz";
-    sha256 = "07j7azgnicmd8cqnyskp15y44ykgj5qqz5y3w1jdynrv3yrvk1kz";
+  src = fetchFromGitHub {
+    owner = "FreeCAD";
+    repo = "FreeCAD";
+    rev = version;
+    sha256 = "1phs9a0px5fnzpyx930cz39p5dis0f0yajxzii3c3sazgkzrd55s";
   };
 
   nativeBuildInputs = [ cmake ninja pkgconfig pythonPackages.pyside2-tools ];
diff --git a/pkgs/applications/graphics/gimp/default.nix b/pkgs/applications/graphics/gimp/default.nix
index e3994b1b412..e53deb99b5b 100644
--- a/pkgs/applications/graphics/gimp/default.nix
+++ b/pkgs/applications/graphics/gimp/default.nix
@@ -1,31 +1,118 @@
-{ stdenv, fetchurl, substituteAll, pkgconfig, intltool, babl, gegl, gtk2, glib, gdk-pixbuf, isocodes
-, pango, cairo, freetype, fontconfig, lcms, libpng, libjpeg, poppler, poppler_data, libtiff
-, libmng, librsvg, libwmf, zlib, libzip, ghostscript, aalib, shared-mime-info
-, python2Packages, libexif, gettext, xorg, glib-networking, libmypaint, gexiv2
-, harfbuzz, mypaint-brushes, libwebp, libheif, libgudev, openexr
-, AppKit, Cocoa, gtk-mac-integration-gtk2 }:
+{ stdenv
+, lib
+, fetchurl
+, substituteAll
+, pkgconfig
+, intltool
+, babl
+, gegl
+, gtk2
+, glib
+, gdk-pixbuf
+, isocodes
+, pango
+, cairo
+, freetype
+, fontconfig
+, lcms
+, libpng
+, libjpeg
+, poppler
+, poppler_data
+, libtiff
+, libmng
+, librsvg
+, libwmf
+, zlib
+, libzip
+, ghostscript
+, aalib
+, shared-mime-info
+, python2Packages
+, libexif
+, gettext
+, xorg
+, glib-networking
+, libmypaint
+, gexiv2
+, harfbuzz
+, mypaint-brushes
+, libwebp
+, libheif
+, libgudev
+, openexr
+, AppKit
+, Cocoa
+, gtk-mac-integration-gtk2
+}:
 
 let
   inherit (python2Packages) pygtk wrapPython python;
 in stdenv.mkDerivation rec {
   pname = "gimp";
-  version = "2.10.12";
+  version = "2.10.14";
 
   src = fetchurl {
-    url = "http://download.gimp.org/pub/gimp/v${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.bz2";
-    sha256 = "0wdcr8d2ink4swn5r4v13bsiya6s3xm4ya97sdbhs4l40y7bb03x";
+    url = "http://download.gimp.org/pub/gimp/v${lib.versions.majorMinor version}/${pname}-${version}.tar.bz2";
+    sha256 = "0m6wdnfvsxyhimdd4v3351g4r1fklllnbipbwcfym3h7q88hz6yz";
   };
 
-  nativeBuildInputs = [ pkgconfig intltool gettext wrapPython ];
-  propagatedBuildInputs = [ gegl ]; # needed by gimp-2.0.pc
+  nativeBuildInputs = [
+    pkgconfig
+    intltool
+    gettext
+    wrapPython
+  ];
+
   buildInputs = [
-    babl gegl gtk2 glib gdk-pixbuf pango cairo gexiv2 harfbuzz isocodes
-    freetype fontconfig lcms libpng libjpeg poppler poppler_data libtiff openexr
-    libmng librsvg libwmf zlib libzip ghostscript aalib shared-mime-info libwebp libheif
-    python pygtk libexif xorg.libXpm glib-networking libmypaint mypaint-brushes
-  ] ++ stdenv.lib.optionals stdenv.isDarwin [
-    AppKit Cocoa gtk-mac-integration-gtk2
-  ] ++ stdenv.lib.optionals stdenv.isLinux [ libgudev ];
+    babl
+    gegl
+    gtk2
+    glib
+    gdk-pixbuf
+    pango
+    cairo
+    gexiv2
+    harfbuzz
+    isocodes
+    freetype
+    fontconfig
+    lcms
+    libpng
+    libjpeg
+    poppler
+    poppler_data
+    libtiff
+    openexr
+    libmng
+    librsvg
+    libwmf
+    zlib
+    libzip
+    ghostscript
+    aalib
+    shared-mime-info
+    libwebp
+    libheif
+    python
+    pygtk
+    libexif
+    xorg.libXpm
+    glib-networking
+    libmypaint
+    mypaint-brushes
+  ] ++ lib.optionals stdenv.isDarwin [
+    AppKit
+    Cocoa
+    gtk-mac-integration-gtk2
+  ] ++ lib.optionals stdenv.isLinux [
+    libgudev
+  ];
+
+  # needed by gimp-2.0.pc
+  propagatedBuildInputs = [
+    gegl
+  ];
 
   pythonPath = [ pygtk ];
 
@@ -48,7 +135,7 @@ in stdenv.mkDerivation rec {
 
   postFixup = ''
     wrapPythonProgramsIn $out/lib/gimp/${passthru.majorVersion}/plug-ins/
-    wrapProgram $out/bin/gimp-${stdenv.lib.versions.majorMinor version} \
+    wrapProgram $out/bin/gimp-${lib.versions.majorMinor version} \
       --prefix PYTHONPATH : "$PYTHONPATH" \
       --set GDK_PIXBUF_MODULE_FILE "$GDK_PIXBUF_MODULE_FILE"
   '';
@@ -56,9 +143,9 @@ in stdenv.mkDerivation rec {
   passthru = rec {
     # The declarations for `gimp-with-plugins` wrapper,
     # used for determining plug-in installation paths
-    majorVersion = "${stdenv.lib.versions.major version}.0";
+    majorVersion = "${lib.versions.major version}.0";
     targetPluginDir = "lib/gimp/${majorVersion}/plug-ins";
-    targetScriptDir = "lib/gimp/${majorVersion}/scripts";
+    targetScriptDir = "share/gimp/${majorVersion}/scripts";
 
     # probably its a good idea to use the same gtk in plugins ?
     gtk = gtk2;
@@ -76,9 +163,9 @@ in stdenv.mkDerivation rec {
 
   enableParallelBuilding = true;
 
-  meta = with stdenv.lib; {
+  meta = with lib; {
     description = "The GNU Image Manipulation Program";
-    homepage = https://www.gimp.org/;
+    homepage = "https://www.gimp.org/";
     maintainers = with maintainers; [ jtojnar ];
     license = licenses.gpl3Plus;
     platforms = platforms.unix;
diff --git a/pkgs/applications/graphics/gimp/plugins/default.nix b/pkgs/applications/graphics/gimp/plugins/default.nix
index 2c520f21f84..29c1445b9ce 100644
--- a/pkgs/applications/graphics/gimp/plugins/default.nix
+++ b/pkgs/applications/graphics/gimp/plugins/default.nix
@@ -8,31 +8,33 @@ let
   inherit (pkgs) stdenv fetchurl pkgconfig intltool glib fetchFromGitHub;
   inherit (gimp) targetPluginDir targetScriptDir;
 
-  pluginDerivation = a: stdenv.mkDerivation ({
+  pluginDerivation = a: let
+    name = a.name or "${a.pname}-${a.version}";
+  in stdenv.mkDerivation ({
     prePhases = "extraLib";
     extraLib = ''
       installScripts(){
-        mkdir -p $out/${targetScriptDir};
-        for p in "$@"; do cp "$p" $out/${targetScriptDir}; done
+        mkdir -p $out/${targetScriptDir}/${name};
+        for p in "$@"; do cp "$p" -r $out/${targetScriptDir}/${name}; done
       }
       installPlugins(){
-        mkdir -p $out/${targetPluginDir};
-        for p in "$@"; do cp "$p" $out/${targetPluginDir}; done
+        mkdir -p $out/${targetPluginDir}/${name};
+        for p in "$@"; do cp "$p" -r $out/${targetPluginDir}/${name}; done
       }
     '';
   }
   // a
   // {
-      name = "gimp-plugin-${a.name or "${a.pname}-${a.version}"}";
+      name = "gimp-plugin-${name}";
       buildInputs = [ gimp gimp.gtk glib ] ++ (a.buildInputs or []);
       nativeBuildInputs = [ pkgconfig intltool ] ++ (a.nativeBuildInputs or []);
     }
   );
 
-  scriptDerivation = {name, src} : pluginDerivation {
-    inherit name; phases = "extraLib installPhase";
+  scriptDerivation = {src, ...}@attrs : pluginDerivation ({
+    phases = [ "extraLib" "installPhase" ];
     installPhase = "installScripts ${src}";
-  };
+  } // attrs);
 
 in
 
@@ -46,6 +48,7 @@ stdenv.lib.makeScope pkgs.newScope (self: with self; {
       url = https://ftp.gimp.org/pub/gimp/plug-ins/v2.6/gap/gimp-gap-2.6.0.tar.bz2;
       sha256 = "1jic7ixcmsn4kx2cn32nc5087rk6g8xsrz022xy11yfmgvhzb0ql";
     };
+    NIX_LDFLAGS = [ "-lm" ];
     patchPhase = ''
       sed -e 's,^\(GIMP_PLUGIN_DIR=\).*,\1'"$out/${gimp.name}-plugins", \
        -e 's,^\(GIMP_DATA_DIR=\).*,\1'"$out/share/${gimp.name}", -i configure
@@ -131,6 +134,7 @@ stdenv.lib.makeScope pkgs.newScope (self: with self; {
       Filters/Enhance/Wavelet sharpen
     */
     name = "wavelet-sharpen-0.1.2";
+    NIX_LDFLAGS = [ "-lm" ];
     src = fetchurl {
       url = http://registry.gimp.org/files/wavelet-sharpen-0.1.2.tar.gz;
       sha256 = "0vql1k67i21g5ivaa1jh56rg427m0icrkpryrhg75nscpirfxxqw";
@@ -195,6 +199,7 @@ stdenv.lib.makeScope pkgs.newScope (self: with self; {
       url = http://tir.astro.utoledo.edu/jdsmith/code/eb/exposure-blend.scm;
       sha256 = "1b6c9wzpklqras4wwsyw3y3jp6fjmhnnskqiwm5sabs8djknfxla";
     };
+    meta.broken = true;
   };
 
   lightning = scriptDerivation {
diff --git a/pkgs/applications/graphics/gimp/wrapper.nix b/pkgs/applications/graphics/gimp/wrapper.nix
index d58dc375cb9..841728d3a29 100644
--- a/pkgs/applications/graphics/gimp/wrapper.nix
+++ b/pkgs/applications/graphics/gimp/wrapper.nix
@@ -17,6 +17,7 @@ in symlinkJoin {
     for each in gimp-${versionBranch} gimp-console-${versionBranch}; do
       wrapProgram $out/bin/$each \
         --set GIMP2_PLUGINDIR "$out/lib/gimp/2.0" \
+        --set GIMP2_DATADIR "$out/share/gimp/2.0" \
         --prefix GTK_PATH : "${gnome3.gnome-themes-extra}/lib/gtk-2.0" \
         ${toString extraArgs}
     done
diff --git a/pkgs/applications/graphics/inkscape/default.nix b/pkgs/applications/graphics/inkscape/default.nix
index c945412bc2c..e3fa897aec6 100644
--- a/pkgs/applications/graphics/inkscape/default.nix
+++ b/pkgs/applications/graphics/inkscape/default.nix
@@ -1,7 +1,7 @@
 { stdenv, fetchurl, pkgconfig, perlPackages, libXft
 , libpng, zlib, popt, boehmgc, libxml2, libxslt, glib, gtkmm2
 , glibmm, libsigcxx, lcms, boost, gettext, makeWrapper
-, gsl, gtkspell2, python2, poppler, imagemagick, libwpg, librevenge
+, gsl, gtkspell2, cairo, python2, poppler, imagemagick, libwpg, librevenge
 , libvisio, libcdr, libexif, potrace, cmake
 , librsvg, wrapGAppsHook
 }:
@@ -52,7 +52,8 @@ stdenv.mkDerivation rec {
     librsvg # for loading icons
 
     python2Env perlPackages.perl
-  ] ++ stdenv.lib.optional (!stdenv.isDarwin) gtkspell2;
+  ] ++ stdenv.lib.optional (!stdenv.isDarwin) gtkspell2
+    ++ stdenv.lib.optional stdenv.isDarwin cairo;
 
   enableParallelBuilding = true;
 
diff --git a/pkgs/applications/misc/calibre/default.nix b/pkgs/applications/misc/calibre/default.nix
index b2c54105946..22ae573353e 100644
--- a/pkgs/applications/misc/calibre/default.nix
+++ b/pkgs/applications/misc/calibre/default.nix
@@ -47,7 +47,7 @@ mkDerivation rec {
     poppler_utils libpng imagemagick libjpeg
     fontconfig podofo qtbase chmlib icu sqlite libusb1 libmtp xdg_utils
   ] ++ (with pypkgs; [
-    apsw cssselect css-parser dateutil dnspython html5-parser lxml netifaces pillow
+    apsw cssselect css-parser dateutil dnspython html5-parser lxml markdown netifaces pillow
     python pyqt5_with_qtwebkit sip
     regex msgpack beautifulsoup4 html2text
     # the following are distributed with calibre, but we use upstream instead
diff --git a/pkgs/applications/misc/dbeaver/default.nix b/pkgs/applications/misc/dbeaver/default.nix
index 191c6a31972..1549ab00a4f 100644
--- a/pkgs/applications/misc/dbeaver/default.nix
+++ b/pkgs/applications/misc/dbeaver/default.nix
@@ -7,7 +7,7 @@
 
 stdenv.mkDerivation rec {
   pname = "dbeaver-ce";
-  version = "6.2.3";
+  version = "6.2.4";
 
   desktopItem = makeDesktopItem {
     name = "dbeaver";
@@ -30,7 +30,7 @@ stdenv.mkDerivation rec {
 
   src = fetchurl {
     url = "https://dbeaver.io/files/${version}/dbeaver-ce-${version}-linux.gtk.x86_64.tar.gz";
-    sha256 = "1v4sllzvaz4fj8s14ddzw11wczlghbdppv8fl5jg6xglg687sgaj";
+    sha256 = "1k3aan290kfy2b53gl8r4yxvb8jas6sms1r052m3jld3i8frqgva";
   };
 
   installPhase = ''
diff --git a/pkgs/applications/misc/keepass-plugins/otpkeyprov/default.nix b/pkgs/applications/misc/keepass-plugins/otpkeyprov/default.nix
new file mode 100644
index 00000000000..e2b26eaee90
--- /dev/null
+++ b/pkgs/applications/misc/keepass-plugins/otpkeyprov/default.nix
@@ -0,0 +1,32 @@
+{ stdenv, buildEnv, fetchzip, mono }:
+
+let
+  version = "2.6";
+  drv = stdenv.mkDerivation {
+    pname = "otpkeyprov";
+    inherit version;
+
+    src = fetchzip {
+      url = "https://keepass.info/extensions/v2/otpkeyprov/OtpKeyProv-${version}.zip";
+      sha256 = "1p60k55v2sxnv1varmp0dgbsi2rhjg9kj19cf54mkc87nss5h1ki";
+      stripRoot = false;
+    };
+
+    meta = {
+      description = "OtpKeyProv is a key provider based on one-time passwords";
+      homepage    = "https://keepass.info/plugins.html#otpkeyprov";
+      platforms   = with stdenv.lib.platforms; linux;
+      license     = stdenv.lib.licenses.gpl2;
+      maintainers = [ stdenv.lib.maintainers.ente ];
+    };
+
+    pluginFilename = "OtpKeyProv.plgx";
+
+    installPhase = ''
+      mkdir -p $out/lib/dotnet/keepass/
+      cp $pluginFilename $out/lib/dotnet/keepass/$pluginFilename
+    '';
+  };
+in
+  # Mono is required to compile plugin at runtime, after loading.
+  buildEnv { name = drv.name; paths = [ mono drv ]; }
diff --git a/pkgs/applications/misc/netsurf/buildsystem/default.nix b/pkgs/applications/misc/netsurf/buildsystem/default.nix
index 36d5a70735a..0560b1d25b3 100644
--- a/pkgs/applications/misc/netsurf/buildsystem/default.nix
+++ b/pkgs/applications/misc/netsurf/buildsystem/default.nix
@@ -19,6 +19,6 @@ stdenv.mkDerivation rec {
     description = "Build system for netsurf browser";
     license = licenses.gpl2;
     maintainers = [ maintainers.vrthra ];
-    platforms = platforms.linux;
+    platforms = platforms.unix;
   };
 }
diff --git a/pkgs/applications/misc/netsurf/libnsgif/default.nix b/pkgs/applications/misc/netsurf/libnsgif/default.nix
index 4de882243fe..e826dee0d25 100644
--- a/pkgs/applications/misc/netsurf/libnsgif/default.nix
+++ b/pkgs/applications/misc/netsurf/libnsgif/default.nix
@@ -26,6 +26,6 @@ stdenv.mkDerivation rec {
     description = "GIF Decoder for netsurf browser";
     license = licenses.gpl2;
     maintainers = [ maintainers.vrthra ];
-    platforms = platforms.linux;
+    platforms = platforms.unix;
   };
 }
diff --git a/pkgs/applications/networking/browsers/vivaldi/default.nix b/pkgs/applications/networking/browsers/vivaldi/default.nix
index c8d8d411f2d..f3228b11eb9 100644
--- a/pkgs/applications/networking/browsers/vivaldi/default.nix
+++ b/pkgs/applications/networking/browsers/vivaldi/default.nix
@@ -17,11 +17,11 @@ let
   vivaldiName = if isSnapshot then "vivaldi-snapshot" else "vivaldi";
 in stdenv.mkDerivation rec {
   pname = "vivaldi";
-  version = "2.9.1705.31-1";
+  version = "2.9.1705.38-1";
 
   src = fetchurl {
     url = "https://downloads.vivaldi.com/${branch}/vivaldi-${branch}_${version}_amd64.deb";
-    sha256 = "113bycfygyx09bc5bgsmdniffp3282004yrl7gr16dssxrw52al2";
+    sha256 = "0jj2kfdl4788l132ncz3jf1pnjig7dc9gaxjmgv51n1ahmmx8shi";
   };
 
   unpackPhase = ''
diff --git a/pkgs/applications/networking/instant-messengers/vk-messenger/default.nix b/pkgs/applications/networking/instant-messengers/vk-messenger/default.nix
index 03bf3b3bbdd..983b8509dc2 100644
--- a/pkgs/applications/networking/instant-messengers/vk-messenger/default.nix
+++ b/pkgs/applications/networking/instant-messengers/vk-messenger/default.nix
@@ -1,19 +1,19 @@
 { stdenv, fetchurl, rpmextract, autoPatchelfHook
-, xorg, gtk2, gnome2, nss, alsaLib, udev, libnotify }:
+, xorg, gtk3, gnome2, nss, alsaLib, udev, libnotify }:
 
 let
-  version = "4.0.1";
+  version = "4.5.2";
 in stdenv.mkDerivation {
   pname = "vk-messenger";
   inherit version;
   src = {
     i686-linux = fetchurl {
       url = "https://desktop.userapi.com/rpm/master/vk-${version}.i686.rpm";
-      sha256 = "0mgppa9qnhix64zp40dc05yc9klsc7qiwcgw7pwq2wm7m3fz3nm8";
+      sha256 = "11xsdmvd2diq3m61si87x2c08nap0vakcypm90wjmdjwayg3fdlw";
     };
     x86_64-linux = fetchurl {
       url = "https://desktop.userapi.com/rpm/master/vk-${version}.x86_64.rpm";
-      sha256 = "0ra0y4dfx4gfa1r3lm6v42j7c9pf7a8vh12kxv3wkg3pvijwgdsm";
+      sha256 = "0j65d6mwj6rxczi0p9fsr6jh37jxw3a3h6w67xwgdvibb7lf3gbb";
     };
   }.${stdenv.system} or (throw "Unsupported system: ${stdenv.system}");
 
@@ -21,7 +21,7 @@ in stdenv.mkDerivation {
   buildInputs = (with xorg; [
     libXdamage libXtst libXScrnSaver libxkbfile
   ]) ++ [
-    gtk2 gnome2.GConf nss alsaLib
+    gtk3 nss alsaLib
   ];
   runtimeDependencies = [ udev.lib libnotify ];
 
@@ -49,6 +49,5 @@ in stdenv.mkDerivation {
     license = licenses.unfree;
     maintainers = [ maintainers.gnidorah ];
     platforms = ["i686-linux" "x86_64-linux"];
-    hydraPlatforms = [];
   };
 }
diff --git a/pkgs/applications/networking/instant-messengers/wire-desktop/default.nix b/pkgs/applications/networking/instant-messengers/wire-desktop/default.nix
index d79a24ea1c2..13ac4ceb138 100644
--- a/pkgs/applications/networking/instant-messengers/wire-desktop/default.nix
+++ b/pkgs/applications/networking/instant-messengers/wire-desktop/default.nix
@@ -18,12 +18,12 @@ let
   pname = "wire-desktop";
 
   version = {
-    x86_64-linux = "3.10.2904";
+    x86_64-linux = "3.11.2912";
     x86_64-darwin = "3.10.3215";
   }.${system} or throwSystem;
 
   sha256 = {
-    x86_64-linux = "1vrz4568mlhylx17jw4z452f0vrd8yd8qkbpkcvnsbhs6k066xcn";
+    x86_64-linux = "1d2wa13d750dd2vslnvzf0ibwjmf5s299pxq0rs2x98y2sabw3sl";
     x86_64-darwin = "0ygm3fgy9k1dp2kjfwsrrwq1i88wgxc6k8y80yz61ivdawgph9wa";
   }.${system} or throwSystem;
 
diff --git a/pkgs/applications/networking/p2p/qbittorrent/default.nix b/pkgs/applications/networking/p2p/qbittorrent/default.nix
index c5142c2f9e2..aebdeda6108 100644
--- a/pkgs/applications/networking/p2p/qbittorrent/default.nix
+++ b/pkgs/applications/networking/p2p/qbittorrent/default.nix
@@ -10,13 +10,13 @@ with lib;
 
 mkDerivation rec {
   pname = "qbittorrent";
-  version = "4.1.8";
+  version = "4.1.9.1";
 
   src = fetchFromGitHub {
     owner = "qbittorrent";
     repo = "qbittorrent";
     rev = "release-${version}";
-    sha256 = "1mx59mazfmd5yaqdgb6cm8hr5sbp2xgzz3y3yipq1fwq85dj3r5w";
+    sha256 = "19zgqlby7i1kr20wa4zd99qzd062a879xxxbmlf40rnqiqy4bhyi";
   };
 
   # NOTE: 2018-05-31: CMake is working but it is not officially supported
diff --git a/pkgs/applications/office/paperwork/default.nix b/pkgs/applications/office/paperwork/default.nix
index df5e495f936..3506ea8b551 100644
--- a/pkgs/applications/office/paperwork/default.nix
+++ b/pkgs/applications/office/paperwork/default.nix
@@ -61,7 +61,7 @@ python3Packages.buildPythonApplication rec {
   '';
 
   propagatedBuildInputs = with python3Packages; [
-    paperwork-backend pypillowfight gtk3 cairo pyxdg dateutil setuptools
+    paperwork-backend pypillowfight gtk3 cairo pyxdg dateutil setuptools pandas
   ];
 
   makeWrapperArgs = [
diff --git a/pkgs/applications/radio/sdrangel/default.nix b/pkgs/applications/radio/sdrangel/default.nix
index 346c6aeed8e..7cb64f92f3f 100644
--- a/pkgs/applications/radio/sdrangel/default.nix
+++ b/pkgs/applications/radio/sdrangel/default.nix
@@ -39,7 +39,7 @@ let
 
 in mkDerivation rec {
   pname = "sdrangel";
-  version = "4.11.7";
+  version = "4.11.12";
 
   src = fetchFromGitHub {
     owner = "f4exb";
diff --git a/pkgs/applications/science/biology/deeptools/default.nix b/pkgs/applications/science/biology/deeptools/default.nix
new file mode 100644
index 00000000000..78a6f483337
--- /dev/null
+++ b/pkgs/applications/science/biology/deeptools/default.nix
@@ -0,0 +1,42 @@
+{ lib
+, python
+}:
+with python.pkgs;
+buildPythonApplication rec {
+  pname = "deepTools";
+  version = "3.3.1";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "08p36p9ncj5s8qf1r7h83x4rnmi63l3yk6mnr3wgpg2qgvwl0hji";
+  };
+
+  propagatedBuildInputs = [
+    numpy
+    numpydoc
+    scipy
+    py2bit
+    pybigwig
+    pysam
+    matplotlib
+    plotly
+    deeptoolsintervals
+  ];
+
+  checkInputs = [ pytest ];
+
+  meta = with lib; {
+    homepage = "https://deeptools.readthedocs.io/en/develop";
+    description = "Tools for exploring deep DNA sequencing data";
+    longDescription = ''
+      deepTools contains useful modules to process the mapped reads data for multiple
+      quality checks, creating normalized coverage files in standard bedGraph and bigWig
+      file formats, that allow comparison between different files (for example, treatment and control).
+      Finally, using such normalized and standardized files, deepTools can create many
+      publication-ready visualizations to identify enrichments and for functional
+      annotations of the genome.
+    '';
+    license = licenses.gpl3;
+    maintainers = with maintainers; [ scalavision ];
+  };
+}
diff --git a/pkgs/applications/version-management/p4v/default.nix b/pkgs/applications/version-management/p4v/default.nix
index 0020c8c2189..317cbfde85b 100644
--- a/pkgs/applications/version-management/p4v/default.nix
+++ b/pkgs/applications/version-management/p4v/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, lib, qtbase, qtmultimedia, qtscript, qtsensors, qtwebkit, openssl, xkeyboard_config, wrapQtAppsHook }:
+{ stdenv, fetchurl, lib, qtbase, qtmultimedia, qtscript, qtsensors, qtwebkit, openssl_1_0_2, xkeyboard_config, wrapQtAppsHook }:
 
 stdenv.mkDerivation rec {
   pname = "p4v";
@@ -19,7 +19,7 @@ stdenv.mkDerivation rec {
       qtscript
       qtsensors
       qtwebkit
-      openssl
+      openssl_1_0_2
   ];
 
   dontWrapQtApps = true;
@@ -43,6 +43,6 @@ stdenv.mkDerivation rec {
     homepage = https://www.perforce.com;
     license = stdenv.lib.licenses.unfreeRedistributable;
     platforms = [ "x86_64-linux" ];
-    maintainers = [ stdenv.lib.maintainers.nioncode ];
+    maintainers = with stdenv.lib.maintainers; [ nathyong nioncode ];
   };
 }
diff --git a/pkgs/applications/version-management/sourcehut/builds.nix b/pkgs/applications/version-management/sourcehut/builds.nix
index 9b6583d6cb8..76edc1b3e64 100644
--- a/pkgs/applications/version-management/sourcehut/builds.nix
+++ b/pkgs/applications/version-management/sourcehut/builds.nix
@@ -4,7 +4,7 @@
 , srht, redis, celery, pyyaml, markdown }:
 
 let
-  version = "0.47.9";
+  version = "0.48.0";
 
   buildWorker = src: buildGoModule {
     inherit src version;
@@ -20,7 +20,7 @@ in buildPythonPackage rec {
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/builds.sr.ht";
     rev = version;
-    sha256 = "1zgaba58svhksxb1pzz8bym9p0pm7fnxsj5k6jz86095xmfijp34";
+    sha256 = "1z5bxsn67cqffixqsrnska86mw0a6494650wbi6dbp10z03870bs";
   };
 
   patches = [
diff --git a/pkgs/applications/version-management/sourcehut/core.nix b/pkgs/applications/version-management/sourcehut/core.nix
index a284873f003..67486bd28f3 100644
--- a/pkgs/applications/version-management/sourcehut/core.nix
+++ b/pkgs/applications/version-management/sourcehut/core.nix
@@ -1,17 +1,18 @@
 { stdenv, fetchgit, fetchNodeModules, buildPythonPackage
 , pgpy, flask, bleach, misaka, humanize, markdown, psycopg2, pygments, requests
 , sqlalchemy, flask_login, beautifulsoup4, sqlalchemy-utils, celery, alembic
+, importlib-metadata
 , sassc, nodejs
 , writeText }:
 
 buildPythonPackage rec {
   pname = "srht";
-  version = "0.54.3";
+  version = "0.54.4";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/core.sr.ht";
     rev = version;
-    sha256 = "1f4srhp5g6652anifs1vyijzi2v23l2rnfpf3x96j9r8rdap42rq";
+    sha256 = "0flxvn178hqd8ljz89ddis80zfnmzgimv4506w4dg2flbwzywy7z";
   };
 
   node_modules = fetchNodeModules {
@@ -47,6 +48,7 @@ buildPythonPackage rec {
     # Unofficial runtime dependencies?
     celery
     alembic
+    importlib-metadata
   ];
 
   PKGVER = version;
diff --git a/pkgs/applications/version-management/sourcehut/dispatch.nix b/pkgs/applications/version-management/sourcehut/dispatch.nix
index 7172cdab402..a61f35b9ee1 100644
--- a/pkgs/applications/version-management/sourcehut/dispatch.nix
+++ b/pkgs/applications/version-management/sourcehut/dispatch.nix
@@ -4,12 +4,12 @@
 
 buildPythonPackage rec {
   pname = "dispatchsrht";
-  version = "0.11.1";
+  version = "0.12.3";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/dispatch.sr.ht";
     rev = version;
-    sha256 = "1bi7vn0yr326mf2c63f2fahdlrx2c6a8d6p6bzy2ym2835qfcc0v";
+    sha256 = "0lpc8jpyz1rg3g98546wlhr27b15g32lds77hl42aixv5f5b8lc9";
   };
 
   patches = [
diff --git a/pkgs/applications/version-management/sourcehut/git.nix b/pkgs/applications/version-management/sourcehut/git.nix
index 9b0b5e2c8e4..b580e89c747 100644
--- a/pkgs/applications/version-management/sourcehut/git.nix
+++ b/pkgs/applications/version-management/sourcehut/git.nix
@@ -4,11 +4,19 @@
 , srht, pygit2, scmsrht }:
 
 let
-  version = "0.34.2";
+  version = "0.35.6";
+
+  buildShell = src: buildGoModule {
+    inherit src version;
+    pname = "git-srht-shell";
+    goPackagePath = "git.sr.ht/~sircmpwn/git.sr.ht/gitsrht-shell";
+
+    modSha256 = "1v4npijqgv09ssrxf1y1b3syb2fs7smy7k9rcj3ynsfrn9xgfd9y";
+  };
 
   buildDispatcher = src: buildGoModule {
     inherit src version;
-    pname = "git-sr-ht-dispatcher";
+    pname = "git-srht-dispatcher";
     goPackagePath = "git.sr.ht/~sircmpwn/git.sr.ht/gitsrht-dispatch";
 
     modSha256 = "1lmgmlin460g09dph2hw6yz25d4agqwjhrjv0qqsis7df9qpf3i1";
@@ -20,7 +28,7 @@ in buildPythonPackage rec {
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/git.sr.ht";
     rev = version;
-    sha256 = "1z10r2d9x71n1n36g55j4cswh0dqnzmgj2qiy1h92wwgq8azpiyy";
+    sha256 = "0j8caqbzdqkgc1bdhzz4k5hgh8lhsghfgwf46d19ryf83d8ggxqc";
   };
 
   patches = [
@@ -42,6 +50,7 @@ in buildPythonPackage rec {
 
   postInstall = ''
     mkdir -p $out/bin
+    cp ${buildShell "${src}/gitsrht-shell"}/bin/gitsrht-shell $out/bin/gitsrht-shell
     cp ${buildDispatcher "${src}/gitsrht-dispatch"}/bin/gitsrht-dispatch $out/bin/gitsrht-dispatch
   '';
 
diff --git a/pkgs/applications/version-management/sourcehut/hg.nix b/pkgs/applications/version-management/sourcehut/hg.nix
index dc9ced49cea..fd5c3145db0 100644
--- a/pkgs/applications/version-management/sourcehut/hg.nix
+++ b/pkgs/applications/version-management/sourcehut/hg.nix
@@ -4,12 +4,12 @@
 
 buildPythonPackage rec {
   pname = "hgsrht";
-  version = "0.16.0";
+  version = "0.16.2";
 
   src = fetchhg {
     url = "https://hg.sr.ht/~sircmpwn/hg.sr.ht";
     rev = version;
-    sha256 = "0ncrj1cbls9ix2ig3qqwbzs6q6cmpqy3zs21p9fw3idfw703j3g0";
+    sha256 = "02bzy31zplnlqg8rcls5n65q1h920lhy6f51w89w1kskdw7r2mhy";
   };
 
   patches = [
diff --git a/pkgs/applications/version-management/sourcehut/meta.nix b/pkgs/applications/version-management/sourcehut/meta.nix
index bac369088a6..a5458b0b864 100644
--- a/pkgs/applications/version-management/sourcehut/meta.nix
+++ b/pkgs/applications/version-management/sourcehut/meta.nix
@@ -5,12 +5,12 @@
 
 buildPythonPackage rec {
   pname = "metasrht";
-  version = "0.35.3";
+  version = "0.37.0";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/meta.sr.ht";
     rev = version;
-    sha256 = "1kcmlmdk9v59fr3r0g2q2gfkb735xza0wni9s942wh418dr66x2f";
+    sha256 = "1jf3h2v27cbam8bwiw3x35319pzp0r651p8mfhw150jvskyvmkmr";
   };
 
   nativeBuildInputs = srht.nativeBuildInputs;
diff --git a/pkgs/applications/version-management/sourcehut/paste.nix b/pkgs/applications/version-management/sourcehut/paste.nix
index 4a86285f50d..4e397c649f9 100644
--- a/pkgs/applications/version-management/sourcehut/paste.nix
+++ b/pkgs/applications/version-management/sourcehut/paste.nix
@@ -4,12 +4,12 @@
 
 buildPythonPackage rec {
   pname = "pastesrht";
-  version = "0.7.1";
+  version = "0.7.3";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/paste.sr.ht";
     rev = version;
-    sha256 = "19y9ghhi4llyg7kd3a888gbjc698vdamin4hb8dk1j6pd2f0qmjp";
+    sha256 = "15689gk37djcwdjb636d97k0il2zpdpksb95l9l4d43wipd7x5qi";
   };
 
   patches = [
diff --git a/pkgs/applications/version-management/sourcehut/scm.nix b/pkgs/applications/version-management/sourcehut/scm.nix
index baccfb1b94b..c5209cee46b 100644
--- a/pkgs/applications/version-management/sourcehut/scm.nix
+++ b/pkgs/applications/version-management/sourcehut/scm.nix
@@ -4,12 +4,12 @@
 
 buildPythonPackage rec {
   pname = "scmsrht";
-  version = "0.15.3";
+  version = "0.16.0";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/scm.sr.ht";
     rev = version;
-    sha256 = "1rzm3r280211w51sjngm5a3pdlzg07c64324k99bqs1fkc2yrfy6";
+    sha256 = "0jny8ihn49n7bpw5nhdrfha78yzpxp277l50y1lj142r59kwmh22";
   };
 
   nativeBuildInputs = srht.nativeBuildInputs;
diff --git a/pkgs/applications/version-management/sourcehut/todo.nix b/pkgs/applications/version-management/sourcehut/todo.nix
index aaee9b54477..a7703bd0729 100644
--- a/pkgs/applications/version-management/sourcehut/todo.nix
+++ b/pkgs/applications/version-management/sourcehut/todo.nix
@@ -5,12 +5,12 @@
 
 buildPythonPackage rec {
   pname = "todosrht";
-  version = "0.51.11";
+  version = "0.51.13";
 
   src = fetchgit {
     url = "https://git.sr.ht/~sircmpwn/todo.sr.ht";
     rev = version;
-    sha256 = "0x4aray1dappalmn2f4wqrhpa5k1idccnafbfhsnfi6nj718i33a";
+    sha256 = "19gywq5j7wlpk7j2whm2ivz0z0i3j50n7k7bx29pghndl7l43c18";
   };
 
   patches = [
diff --git a/pkgs/applications/video/smplayer/default.nix b/pkgs/applications/video/smplayer/default.nix
index 495fc6f6745..facb8fabe26 100644
--- a/pkgs/applications/video/smplayer/default.nix
+++ b/pkgs/applications/video/smplayer/default.nix
@@ -1,11 +1,12 @@
 { lib, mkDerivation, fetchurl, qmake, qtscript }:
 
 mkDerivation rec {
-  name = "smplayer-19.5.0";
+  pname = "smplayer";
+  version = "19.10.0";
 
   src = fetchurl {
-    url = "mirror://sourceforge/smplayer/${name}.tar.bz2";
-    sha256 = "1xda9pbrc3dfbs71n5l8yszlcywz9456mwkv52vmn8lszhvjpjxm";
+    url = "mirror://sourceforge/${pname}/${pname}-${version}.tar.bz2";
+    sha256 = "0sq7hr10b4pbbi0y1q4mxs24h2lb042nv4rqr03r72bp57353xsl";
   };
 
   buildInputs = [ qtscript ];
@@ -13,13 +14,12 @@ mkDerivation rec {
 
   dontUseQmakeConfigure = true;
 
-  preConfigure = ''
-    makeFlags="PREFIX=$out"
-  '';
+  makeFlags = [ "PREFIX=${placeholder "out"}" ];
 
   meta = {
     description = "A complete front-end for MPlayer";
-    homepage = http://smplayer.sourceforge.net/;
+    longDescription = "Either mplayer or mpv should also be installed for smplayer to play medias";
+    homepage = https://www.smplayer.info;
     license = lib.licenses.gpl3Plus;
     platforms = lib.platforms.linux;
   };
diff --git a/pkgs/applications/virtualization/x11docker/default.nix b/pkgs/applications/virtualization/x11docker/default.nix
index 1d18e4d14e8..c57a7f6e771 100644
--- a/pkgs/applications/virtualization/x11docker/default.nix
+++ b/pkgs/applications/virtualization/x11docker/default.nix
@@ -1,26 +1,22 @@
-{ stdenv, fetchFromGitHub, makeWrapper, nx-libs, xorg }:
+{ stdenv, fetchFromGitHub, makeWrapper, nx-libs, xorg, getopt, gnugrep, gawk, ps, mount, iproute }:
 stdenv.mkDerivation rec {
   pname = "x11docker";
-  version = "6.2.0";
+  version = "6.3.0";
   src = fetchFromGitHub {
     owner = "mviereck";
     repo = "x11docker";
     rev = "v${version}";
-    sha256 = "19q5vrhspxpjkdhhlgya2sa2fgjg8gyd3kmnb83nlfs46p8jx4f4";
+    sha256 = "0x2sx41y3ylzg511x52k3wh8mfbzp4ialpas6sn4ccagqxh2hc4y";
   };
   nativeBuildInputs = [ makeWrapper ];
-  buildInputs = [ nx-libs xorg.xhost xorg.xinit ];
 
   dontBuild = true;
 
-  PATH_PREFIX = "${nx-libs}/bin:${xorg.xdpyinfo}/bin:${xorg.xhost}/bin:${xorg.xinit}/bin";
-
+  # Don't install `x11docker-gui`, because requires `kaptain` dependency
   installPhase = ''
     install -D x11docker "$out/bin/x11docker";
-    #install -D x11docker-gui "$out/bin/x11docker-gui";
-    wrapProgram "$out/bin/x11docker" --prefix PATH : "${PATH_PREFIX}"
-    #wrapProgram "$out/bin/x11docker-gui" --prefix PATH : "${PATH_PREFIX}"
-    # GUI disabled because of missing `kaptain` dependency
+    wrapProgram "$out/bin/x11docker" \
+      --prefix PATH : "${stdenv.lib.makeBinPath [ getopt gnugrep gawk ps mount iproute nx-libs xorg.xdpyinfo xorg.xhost xorg.xinit ]}"
   '';
 
   meta = {
@@ -28,5 +24,6 @@ stdenv.mkDerivation rec {
     homepage = https://github.com/mviereck/x11docker;
     license = stdenv.lib.licenses.mit;
     maintainers = with stdenv.lib.maintainers; [ jD91mZM2 ];
+    platforms = stdenv.lib.platforms.linux;
   };
 }
diff --git a/pkgs/build-support/nix-prefetch-github/default.nix b/pkgs/build-support/nix-prefetch-github/default.nix
deleted file mode 100644
index 10a6daaf53f..00000000000
--- a/pkgs/build-support/nix-prefetch-github/default.nix
+++ /dev/null
@@ -1,29 +0,0 @@
-{ python3
-, fetchFromGitHub
-, stdenv
-}:
-
-python3.pkgs.buildPythonApplication rec {
-  pname = "nix-prefetch-github";
-  version = "2.3.1";
-
-  src = fetchFromGitHub {
-    owner = "seppeljordan";
-    repo = "nix-prefetch-github";
-    rev = "v${version}";
-    sha256 = "13wvq13iiva97a16kahfpxar5ppb015nnbn7d4v9s9jyxdickc2c";
-  };
-
-  propagatedBuildInputs = with python3.pkgs; [
-    attrs
-    click
-    effect
-    jinja2
-  ];
-  meta = with stdenv.lib; {
-    description = "Prefetch sources from github";
-    homepage = https://github.com/seppeljordan/nix-prefetch-github;
-    license = licenses.gpl3;
-    maintainers = [ maintainers.seppeljordan ];
-  };
-}
diff --git a/pkgs/data/fonts/liberation-sans-narrow/default.nix b/pkgs/data/fonts/liberation-sans-narrow/default.nix
index 4a14e095cf0..51af6a20bae 100644
--- a/pkgs/data/fonts/liberation-sans-narrow/default.nix
+++ b/pkgs/data/fonts/liberation-sans-narrow/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchFromGitHub, fontforge, pythonPackages, python }:
+{ stdenv, fetchFromGitHub, fontforge, python3Packages, python3 }:
 
 stdenv.mkDerivation rec {
   pname = "liberation-sans-narrow";
@@ -11,7 +11,7 @@ stdenv.mkDerivation rec {
     sha256 = "1qw554jbdnqkg6pjjl4cqkgsalq3398kzvww2naw30vykcz752bm";
   };
 
-  buildInputs = [ fontforge pythonPackages.fonttools python ];
+  buildInputs = [ fontforge python3Packages.fonttools python3 ];
 
   installPhase = ''
     find . -name '*Narrow*.ttf' -exec install -m444 -Dt $out/share/fonts/truetype {} \;
diff --git a/pkgs/data/fonts/rictydiminished-with-firacode/default.nix b/pkgs/data/fonts/rictydiminished-with-firacode/default.nix
index 2e83d5b12d4..8b6c3749962 100644
--- a/pkgs/data/fonts/rictydiminished-with-firacode/default.nix
+++ b/pkgs/data/fonts/rictydiminished-with-firacode/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchgit, fontforge, pythonFull }:
+{ stdenv, fetchgit, fontforge, python3 }:
 
 stdenv.mkDerivation rec {
   pname = "rictydiminished-with-firacode";
@@ -27,7 +27,7 @@ stdenv.mkDerivation rec {
 
   nativeBuildInputs = [
     fontforge
-    (pythonFull.withPackages (ps: [
+    (python3.withPackages (ps: [
       ps.jinja2
       ps.py3to2
       ps.fonttools
diff --git a/pkgs/data/themes/yaru/default.nix b/pkgs/data/themes/yaru/default.nix
index 2302aa301e3..f83dbc3ebcc 100644
--- a/pkgs/data/themes/yaru/default.nix
+++ b/pkgs/data/themes/yaru/default.nix
@@ -3,13 +3,13 @@
 
 stdenv.mkDerivation rec {
   pname = "yaru";
-  version = "19.10.2";
+  version = "19.10.4";
 
   src = fetchFromGitHub {
     owner = "ubuntu";
     repo = "yaru";
     rev = version;
-    sha256 = "1azyn8pr0kpbq4wlz91f5amqyxqq0x2mxkglzl488sf39fl0gnbj";
+    sha256 = "1dj6awlz13787783ds9mdid75rd4vvgpg52h6x19pxdga3k17s9b";
   };
 
   nativeBuildInputs = [ meson sassc pkg-config glib ninja python3 ];
diff --git a/pkgs/desktops/gnome-3/default.nix b/pkgs/desktops/gnome-3/default.nix
index aa50aa18c40..952f6eaf4f8 100644
--- a/pkgs/desktops/gnome-3/default.nix
+++ b/pkgs/desktops/gnome-3/default.nix
@@ -24,7 +24,6 @@ lib.makeScope pkgs.newScope (self: with self; {
   libsoup = pkgs.libsoup.override { gnomeSupport = true; };
   libchamplain = pkgs.libchamplain.override { libsoup = libsoup; };
   gnome3 = self // { recurseForDerivations = false; };
-  gegl_0_4 = pkgs.gegl_0_4.override { gtk = pkgs.gtk3; };
 
 # ISO installer
 # installerIso = callPackage ./installer.nix {};
@@ -359,4 +358,6 @@ lib.makeScope pkgs.newScope (self: with self; {
   nautilus-sendto = throw "deprecated 2019-09-17: abandoned";
 
   inherit (pkgs) vala; # added 2019-10-10
+
+  inherit (pkgs) gegl_0_4; # added 2019-10-31
 })
diff --git a/pkgs/desktops/gnome-3/devtools/devhelp/default.nix b/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
index 8d731d829b2..080a332d7df 100644
--- a/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
+++ b/pkgs/desktops/gnome-3/devtools/devhelp/default.nix
@@ -1,6 +1,22 @@
-{ stdenv, fetchurl, meson, ninja, pkgconfig, gnome3, gtk3, wrapGAppsHook
-, glib, amtk, appstream-glib, gobject-introspection, python3
-, webkitgtk, gettext, itstool, gsettings-desktop-schemas }:
+{ stdenv
+, fetchurl
+, meson
+, ninja
+, pkgconfig
+, gnome3
+, gtk3
+, wrapGAppsHook
+, glib
+, amtk
+, appstream-glib
+, gobject-introspection
+, python3
+, webkitgtk
+, gettext
+, itstool
+, gsettings-desktop-schemas
+, shared-mime-info
+}:
 
 stdenv.mkDerivation rec {
   pname = "devhelp";
@@ -11,10 +27,25 @@ stdenv.mkDerivation rec {
     sha256 = "0zpmn6fgkgiayvn4diia5df0s6s7dqrdnp3nrvpavsmgn0vhb4pg";
   };
 
-  nativeBuildInputs = [ meson ninja pkgconfig gettext itstool wrapGAppsHook appstream-glib gobject-introspection python3 ];
+  nativeBuildInputs = [
+    meson
+    ninja
+    pkgconfig
+    gettext
+    itstool
+    wrapGAppsHook
+    appstream-glib
+    gobject-introspection
+    python3
+  ];
+
   buildInputs = [
-    glib gtk3 webkitgtk amtk
-    gnome3.adwaita-icon-theme gsettings-desktop-schemas
+    glib
+    gtk3
+    webkitgtk
+    amtk
+    gnome3.adwaita-icon-theme
+    gsettings-desktop-schemas
   ];
 
   doCheck = true;
@@ -24,6 +55,14 @@ stdenv.mkDerivation rec {
     patchShebangs meson_post_install.py
   '';
 
+  preFixup = ''
+    gappsWrapperArgs+=(
+      # Fix pages being blank
+      # https://gitlab.gnome.org/GNOME/devhelp/issues/14
+      --prefix XDG_DATA_DIRS : "${shared-mime-info}/share"
+    )
+  '';
+
   passthru = {
     updateScript = gnome3.updateScript {
       packageName = "devhelp";
@@ -33,8 +72,8 @@ stdenv.mkDerivation rec {
 
   meta = with stdenv.lib; {
     description = "API documentation browser for GNOME";
-    homepage = https://wiki.gnome.org/Apps/Devhelp;
-    license = licenses.gpl2;
+    homepage = "https://wiki.gnome.org/Apps/Devhelp";
+    license = licenses.gpl3Plus;
     maintainers = gnome3.maintainers;
     platforms = platforms.linux;
   };
diff --git a/pkgs/desktops/gnome-3/extensions/night-theme-switcher/default.nix b/pkgs/desktops/gnome-3/extensions/night-theme-switcher/default.nix
new file mode 100644
index 00000000000..8d3a775e949
--- /dev/null
+++ b/pkgs/desktops/gnome-3/extensions/night-theme-switcher/default.nix
@@ -0,0 +1,21 @@
+{ stdenv, fetchgit }:
+
+stdenv.mkDerivation rec {
+  pname = "gnome-shell-extension-night-theme-switcher";
+  version = "2.1";
+
+  src = fetchgit {
+    url = "https://git.romainvigier.fr/Romain/nightthemeswitcher-gnome-shell-extension";
+    rev = "v${version}";
+    sha256 = "1md44vmc83cp35riszhdvysnvl8pmkcpf5j6n4i2b3wwcjwxqwfy";
+  };
+
+  makeFlags = [ "GSEXT_DIR_LOCAL=${placeholder "out"}/share/gnome-shell/extensions" ];
+
+  meta = with stdenv.lib; {
+    description = "Automatically change the GTK theme to dark variant when Night Light activates";
+    license = licenses.gpl3;
+    maintainers = with maintainers; [ jonafato ];
+    homepage = https://git.romainvigier.fr/Romain/nightthemeswitcher-gnome-shell-extension;
+  };
+}
diff --git a/pkgs/desktops/pantheon/apps/appcenter/default.nix b/pkgs/desktops/pantheon/apps/appcenter/default.nix
new file mode 100644
index 00000000000..db674f4fb7e
--- /dev/null
+++ b/pkgs/desktops/pantheon/apps/appcenter/default.nix
@@ -0,0 +1,92 @@
+{ stdenv
+, appstream
+, appstream-glib
+, dbus
+, desktop-file-utils
+, elementary-gtk-theme
+, elementary-icon-theme
+, fetchFromGitHub
+, fetchpatch
+, flatpak
+, gettext
+, glib
+, granite
+, gtk3
+, json-glib
+, libgee
+, libsoup
+, libxml2
+, meson
+, ninja
+, packagekit
+, pantheon
+, pkgconfig
+, python3
+, vala
+, wrapGAppsHook
+}:
+
+stdenv.mkDerivation rec {
+  pname = "appcenter";
+  version = "3.2.0";
+
+  src = fetchFromGitHub {
+    owner = "elementary";
+    repo = pname;
+    rev = version;
+    sha256 = "0xsxm0qgmnljd4s8m6xajzsjp9skpsa8wwlwqmc5yx34diad7zag";
+  };
+
+  passthru = {
+    updateScript = pantheon.updateScript {
+      repoName = pname;
+    };
+  };
+
+  nativeBuildInputs = [
+    appstream-glib
+    dbus # for pkgconfig
+    desktop-file-utils
+    gettext
+    meson
+    ninja
+    pkgconfig
+    python3
+    vala
+    wrapGAppsHook
+  ];
+
+  buildInputs = [
+    appstream
+    elementary-icon-theme
+    elementary-gtk-theme
+    flatpak
+    glib
+    granite
+    gtk3
+    json-glib
+    libgee
+    libsoup
+    libxml2
+    packagekit
+  ];
+
+  mesonFlags = [
+    "-Dhomepage=false"
+    "-Dpayments=false"
+    "-Dcurated=false"
+  ];
+
+  postPatch = ''
+    chmod +x meson/post_install.py
+    patchShebangs meson/post_install.py
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/elementary/appcenter;
+    description = "An open, pay-what-you-want app store for indie developers, designed for elementary OS";
+    license = licenses.gpl3Plus;
+    platforms = platforms.linux;
+    maintainers = pantheon.maintainers;
+  };
+}
diff --git a/pkgs/desktops/pantheon/apps/elementary-calendar/default.nix b/pkgs/desktops/pantheon/apps/elementary-calendar/default.nix
index 72983c8479c..4e5f69fc9e6 100644
--- a/pkgs/desktops/pantheon/apps/elementary-calendar/default.nix
+++ b/pkgs/desktops/pantheon/apps/elementary-calendar/default.nix
@@ -25,15 +25,15 @@
 
 stdenv.mkDerivation rec {
   pname = "elementary-calendar";
-  version = "unstable-2019-09-17";
+  version = "unstable-2019-10-29";
 
   repoName = "calendar";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = repoName;
-    rev = "46346e48b53e9d3d59d9f567b622532338f50f32"; # needed for libical 2.0 compat
-    sha256 = "04xzczcj5rbzqlhmf175d8p0wzw01s4658v5jllrp8nchmndb986";
+    rev = "7d201fc5ea9e8dc25c46427397594fcab2016ed6"; # needed for libical 2.0 compat
+    sha256 = "11bqf3nxrj1sfd0qq5h0jsmimc6mwkd2g7q9ycizn9x5ak2gb8xi";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/apps/elementary-camera/default.nix b/pkgs/desktops/pantheon/apps/elementary-camera/default.nix
index 279e9eff87a..aedc445b05f 100644
--- a/pkgs/desktops/pantheon/apps/elementary-camera/default.nix
+++ b/pkgs/desktops/pantheon/apps/elementary-camera/default.nix
@@ -23,7 +23,7 @@
 
 stdenv.mkDerivation rec {
   pname = "elementary-camera";
-  version = "1.0.4";
+  version = "1.0.5";
 
   repoName = "camera";
 
@@ -31,7 +31,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "1p532f961cjdg7szmxw7hw3av9v342hv5rx7in3bbhlc7adxflyc";
+    sha256 = "05amcljvc3w77a1b0c76y6rha8g0zm6lqflvg1g7jzz00jchx9d4";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/apps/elementary-feedback/default.nix b/pkgs/desktops/pantheon/apps/elementary-feedback/default.nix
new file mode 100644
index 00000000000..70d8f63c13c
--- /dev/null
+++ b/pkgs/desktops/pantheon/apps/elementary-feedback/default.nix
@@ -0,0 +1,70 @@
+{ stdenv
+, fetchFromGitHub
+, pantheon
+, pkgconfig
+, meson
+, ninja
+, vala
+, python3
+, gtk3
+, glib
+, granite
+, libgee
+, elementary-icon-theme
+, elementary-gtk-theme
+, gettext
+, wrapGAppsHook
+}:
+
+stdenv.mkDerivation rec {
+  pname = "elementary-feedback";
+  version = "1.0";
+
+  repoName = "feedback";
+
+  src = fetchFromGitHub {
+    owner = "elementary";
+    repo = repoName;
+    rev = version;
+    sha256 = "0rc4ifs4hd4cj0v028bzc45v64pwx21xylwrhb20jpw61ainfi8s";
+  };
+
+  passthru = {
+    updateScript = pantheon.updateScript {
+      inherit repoName;
+      attrPath = pname;
+    };
+  };
+
+  nativeBuildInputs = [
+    gettext
+    meson
+    ninja
+    pkgconfig
+    python3
+    vala
+    wrapGAppsHook
+  ];
+
+  buildInputs = [
+    elementary-icon-theme
+    granite
+    gtk3
+    elementary-gtk-theme
+    libgee
+    glib
+  ];
+
+  postPatch = ''
+    chmod +x meson/post_install.py
+    patchShebangs meson/post_install.py
+  '';
+
+  meta = with stdenv.lib; {
+    description = "GitHub Issue Reporter designed for elementary OS";
+    homepage = https://github.com/elementary/feedback;
+    license = licenses.gpl3Plus;
+    platforms = platforms.linux;
+    maintainers = pantheon.maintainers;
+  };
+}
diff --git a/pkgs/desktops/pantheon/apps/elementary-files/default.nix b/pkgs/desktops/pantheon/apps/elementary-files/default.nix
index 0bb2824b3d3..1b5de7c168e 100644
--- a/pkgs/desktops/pantheon/apps/elementary-files/default.nix
+++ b/pkgs/desktops/pantheon/apps/elementary-files/default.nix
@@ -23,13 +23,14 @@
 , zeitgeist
 , glib-networking
 , elementary-icon-theme
+, libcloudproviders
 , fetchpatch
 , wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
   pname = "elementary-files";
-  version = "4.1.9";
+  version = "4.2.0";
 
   repoName = "files";
 
@@ -39,7 +40,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "12p1li9a7kqdlgkq20svaly5kr661ww93qngaiic6zv1bdw2bpmv";
+    sha256 = "12f0hzb62nchksyqd2gwj3cv001rph24ggd9wywh9i1qwppx4b5k";
   };
 
   passthru = {
@@ -67,6 +68,7 @@ stdenv.mkDerivation rec {
     granite
     gtk3
     libcanberra
+    libcloudproviders
     libdbusmenu-gtk3
     libgee
     libnotify
diff --git a/pkgs/desktops/pantheon/apps/sideload/default.nix b/pkgs/desktops/pantheon/apps/sideload/default.nix
new file mode 100644
index 00000000000..1fcd486263b
--- /dev/null
+++ b/pkgs/desktops/pantheon/apps/sideload/default.nix
@@ -0,0 +1,73 @@
+{ stdenv
+, desktop-file-utils
+, elementary-gtk-theme
+, elementary-icon-theme
+, fetchFromGitHub
+, flatpak
+, gettext
+, glib
+, granite
+, gtk3
+, libgee
+, meson
+, ninja
+, pantheon
+, pkgconfig
+, python3
+, vala
+, libxml2
+, wrapGAppsHook
+}:
+
+stdenv.mkDerivation rec {
+  pname = "sideload";
+  version = "1.0.0";
+
+  src = fetchFromGitHub {
+    owner = "elementary";
+    repo = pname;
+    rev = version;
+    sha256 = "1qi4wm773bf1szi5a77g9lxjn305v1m85j4nb6il9q4qlh9b1cs5";
+  };
+
+  passthru = {
+    updateScript = pantheon.updateScript {
+      repoName = pname;
+    };
+  };
+
+  nativeBuildInputs = [
+    desktop-file-utils
+    gettext
+    meson
+    ninja
+    pkgconfig
+    python3
+    vala
+    wrapGAppsHook
+  ];
+
+  buildInputs = [
+    elementary-gtk-theme
+    elementary-icon-theme
+    flatpak
+    glib
+    granite
+    gtk3
+    libgee
+    libxml2
+  ];
+
+  postPatch = ''
+    chmod +x meson/post_install.py
+    patchShebangs meson/post_install.py
+  '';
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/elementary/sideload;
+    description = "Flatpak installer, designed for elementary OS";
+    license = licenses.gpl3Plus;
+    platforms = platforms.linux;
+    maintainers = pantheon.maintainers;
+  };
+}
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/default.nix b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/default.nix
index 3247aed4993..c179160ddab 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/default.nix
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/default.nix
@@ -11,17 +11,18 @@
 , gtk3
 , switchboard
 , pciutils
+, elementary-feedback
 }:
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-about";
-  version = "2.5.2";
+  version = "2.6.0";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "11diwz2aj45yqkxdija8ny0sgm0wl2905gl3799cdl12ss9ffndp";
+    sha256 = "12ysymk5y2k49yh3rzmra7jmimxrd54gz2f4ssc9i8w06xj5djp7";
   };
 
   passthru = {
@@ -46,17 +47,15 @@ stdenv.mkDerivation rec {
 
   patches = [
     (substituteAll {
-      src = ./lspci-path.patch;
+      src = ./fix-paths.patch;
       inherit pciutils;
+      elementary_feedback = elementary-feedback;
     })
-    ./remove-update-button.patch
   ];
 
-  PKG_CONFIG_SWITCHBOARD_2_0_PLUGSDIR = "${placeholder "out"}/lib/switchboard";
-
   meta = with stdenv.lib; {
     description = "Switchboard About Plug";
-    homepage = https://github.com/elementary/witchboard-plug-about;
+    homepage = https://github.com/elementary/switchboard-plug-about;
     license = licenses.gpl3Plus;
     platforms = platforms.linux;
     maintainers = pantheon.maintainers;
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/fix-paths.patch b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/fix-paths.patch
new file mode 100644
index 00000000000..d458689a325
--- /dev/null
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/fix-paths.patch
@@ -0,0 +1,26 @@
+diff --git a/src/Plug.vala b/src/Plug.vala
+index c32efcbe..0cdaeaca 100644
+--- a/src/Plug.vala
++++ b/src/Plug.vala
+@@ -178,7 +178,7 @@ public class About.Plug : Switchboard.Plug {
+ 
+         var bug_button = new Gtk.Button.with_label (_("Report a Problem"));
+         bug_button.clicked.connect (() => {
+-            var appinfo = new GLib.DesktopAppInfo ("io.elementary.feedback.desktop");
++            var appinfo = new GLib.DesktopAppInfo ("@elementary_feedback@/bin/io.elementary.feedback.desktop");
+             if (appinfo != null) {
+                 try {
+                     appinfo.launch (null, null);
+diff --git a/src/Views/HardwareView.vala b/src/Views/HardwareView.vala
+index f8113634..3794bad8 100644
+--- a/src/Views/HardwareView.vala
++++ b/src/Views/HardwareView.vala
+@@ -179,7 +179,7 @@ public class About.HardwareView : Gtk.Grid {
+ 
+         // Graphics
+         try {
+-            Process.spawn_command_line_sync ("lspci", out graphics);
++            Process.spawn_command_line_sync ("@pciutils@/bin/lspci", out graphics);
+ 
+             if ("VGA" in graphics) { //VGA-keyword indicates graphics-line
+                 string[] lines = graphics.split("\n");
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/lspci-path.patch b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/lspci-path.patch
deleted file mode 100644
index 352d84c4262..00000000000
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/lspci-path.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/src/Views/HardwareView.vala b/src/Views/HardwareView.vala
-index a3e449c..a95fe93 100644
---- a/src/Views/HardwareView.vala
-+++ b/src/Views/HardwareView.vala
-@@ -179,7 +179,7 @@ public class About.HardwareView : Gtk.Grid {
- 
-         // Graphics
-         try {
--            Process.spawn_command_line_sync ("lspci", out graphics);
-+            Process.spawn_command_line_sync ("@pciutils@/bin/lspci", out graphics);
- 
-             if ("VGA" in graphics) { //VGA-keyword indicates graphics-line
-                 string[] lines = graphics.split("\n");
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/remove-update-button.patch b/pkgs/desktops/pantheon/apps/switchboard-plugs/about/remove-update-button.patch
deleted file mode 100644
index 41433f9a76b..00000000000
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/about/remove-update-button.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-diff --git a/src/Plug.vala b/src/Plug.vala
-index 76fca34..3e79c1f 100644
---- a/src/Plug.vala
-+++ b/src/Plug.vala
-@@ -65,7 +65,6 @@ public class About.Plug : Switchboard.Plug {
-         search_results.set ("%s → %s".printf (display_name, _("Restore Default Settings")), "");
-         search_results.set ("%s → %s".printf (display_name, _("Suggest Translation")), "");
-         search_results.set ("%s → %s".printf (display_name, _("Report Problems")), "");
--        search_results.set ("%s → %s".printf (display_name, _("Updates")), "");
-         return search_results;
-     }
- 
-@@ -161,7 +160,7 @@ public class About.Plug : Switchboard.Plug {
-         var kernel_version_label = new Gtk.Label (kernel_version);
-         kernel_version_label.set_selectable (true);
- 
--        var gtk_version_label = new Gtk.Label (_("GTK+ %s").printf (gtk_version));        
-+        var gtk_version_label = new Gtk.Label (_("GTK+ %s").printf (gtk_version));
-         gtk_version_label.set_selectable (true);
- 
-         var website_label = new Gtk.LinkButton.with_label (website_url, _("Website"));
-@@ -202,16 +201,6 @@ public class About.Plug : Switchboard.Plug {
-             issue_dialog.run ();
-         });
- 
--        // Update button
--        var update_button = new Gtk.Button.with_label (_("Check for Updates"));
--        update_button.clicked.connect (() => {
--            try {
--                Process.spawn_command_line_async ("io.elementary.appcenter --show-updates");
--            } catch (Error e) {
--                warning (e.message);
--            }
--        });
--
-         // Restore settings button
-         var settings_restore_button = new Gtk.Button.with_label (_("Restore Default Settings"));
-         settings_restore_button.clicked.connect (settings_restore_clicked);
-@@ -224,7 +213,6 @@ public class About.Plug : Switchboard.Plug {
-         button_grid.add (settings_restore_button);
-         button_grid.add (translate_button);
-         button_grid.add (bug_button);
--        button_grid.add (update_button);
-         button_grid.set_child_non_homogeneous (help_button, true);
- 
-         var software_grid = new Gtk.Grid ();
-@@ -238,7 +226,7 @@ public class About.Plug : Switchboard.Plug {
-             software_grid.attach (based_off, 0, 2, 2, 1);
-         }
- 
--        software_grid.attach (kernel_version_label, 0, 3, 2, 1);        
-+        software_grid.attach (kernel_version_label, 0, 3, 2, 1);
-         software_grid.attach (gtk_version_label, 0, 4, 2, 1);
-         software_grid.attach (website_label, 0, 5, 2, 1);
- 
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/bluetooth/default.nix b/pkgs/desktops/pantheon/apps/switchboard-plugs/bluetooth/default.nix
index 9f1c75b7b43..ca29ab65afc 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/bluetooth/default.nix
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/bluetooth/default.nix
@@ -14,13 +14,13 @@
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-bluetooth";
-  version = "2.2.2";
+  version = "2.3.0";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "0rp9wa0yilc3wgwnybc6cryxphja7imixn45zhj475a4nb3afd0q";
+    sha256 = "1m8nzav976xs3sash2nbyrfn2sk7aah352ypihbp7bacid5wnhr7";
   };
 
   passthru = {
@@ -44,8 +44,6 @@ stdenv.mkDerivation rec {
     switchboard
   ];
 
-  PKG_CONFIG_SWITCHBOARD_2_0_PLUGSDIR = "${placeholder "out"}/lib/switchboard";
-
   meta = with stdenv.lib; {
     description = "Switchboard Bluetooth Plug";
     homepage = https://github.com/elementary/switchboard-plug-bluetooth;
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/clock-format.patch b/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/clock-format.patch
deleted file mode 100644
index 0fe0ac8b10c..00000000000
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/clock-format.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/src/DateTime1.vala b/src/DateTime1.vala
-index 5a80fbd..2e1f948 100644
---- a/src/DateTime1.vala
-+++ b/src/DateTime1.vala
-@@ -38,6 +38,6 @@ public class DateTime.Settings : Granite.Services.Settings {
-     public string clock_format { get; set; }
- 
-     public Settings () {
--        base ("io.elementary.desktop.wingpanel.datetime");
-+        base ("io.elementary.granite");
-     }
- }
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/default.nix b/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/default.nix
index c0c7bbdec2e..cafb4014407 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/default.nix
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/datetime/default.nix
@@ -16,13 +16,13 @@
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-datetime";
-  version = "2.1.5";
+  version = "2.1.6";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "1iz8skf5dw76a07ljc8v8lw2x2nrmq8j6sggm227cmxy60gadsdv";
+    sha256 = "09734c3qc0296zf14rdhl4p6ppga015rz9hhsvlcc3nvyw7kdqkc";
   };
 
   passthru = {
@@ -51,8 +51,6 @@ stdenv.mkDerivation rec {
       src = ./timezone.patch;
       tzdata = "${tzdata}/share/zoneinfo/zone.tab";
     })
-    # Use "clock-format" GSettings key that's been moved to granite
-    ./clock-format.patch
   ];
 
   PKG_CONFIG_SWITCHBOARD_2_0_PLUGSDIR = "${placeholder "out"}/lib/switchboard";
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/display/default.nix b/pkgs/desktops/pantheon/apps/switchboard-plugs/display/default.nix
index 76cfe61fc77..00524786f4b 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/display/default.nix
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/display/default.nix
@@ -13,13 +13,13 @@
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-display";
-  version = "2.1.8";
+  version = "2.1.9";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "1xpgkvcv3bylpaj7c80727vr55vilkgjvnlbw7d5pr56v6mv7n9j";
+    sha256 = "0g9apywxgkan82h933rjjdm9fhd8vak8mziwsbqlprdz310b2jb2";
   };
 
   passthru = {
@@ -42,8 +42,6 @@ stdenv.mkDerivation rec {
     switchboard
   ];
 
-  PKG_CONFIG_SWITCHBOARD_2_0_PLUGSDIR = "${placeholder "out"}/lib/switchboard";
-
   meta = with stdenv.lib; {
     description = "Switchboard Displays Plug";
     homepage = https://github.com/elementary/switchboard-plug-display;
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/default.nix b/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/default.nix
index fd67440a43c..5c72af92397 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/default.nix
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/default.nix
@@ -18,13 +18,13 @@
 
 stdenv.mkDerivation rec {
   pname = "switchboard-plug-security-privacy";
-  version = "2.2.1";
+  version = "2.2.2";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "0k2bq7l0m7qfpy1mkb3qvsinqd8n4lp0vwz3x64wlgfn2qipm1fn";
+    sha256 = "1dwq9rqswgnnglhrgcpvrp6shn3pb4x8f8f23x84sqakb430idp7";
   };
 
   passthru = {
@@ -51,8 +51,6 @@ stdenv.mkDerivation rec {
     zeitgeist
   ];
 
-  PKG_CONFIG_SWITCHBOARD_2_0_PLUGSDIR = "${placeholder "out"}/lib/switchboard";
-
   patches = [
     ./hardcode-gsettings.patch
   ];
diff --git a/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/hardcode-gsettings.patch b/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/hardcode-gsettings.patch
index ffaf1ecf5db..24a104248f8 100644
--- a/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/hardcode-gsettings.patch
+++ b/pkgs/desktops/pantheon/apps/switchboard-plugs/security-privacy/hardcode-gsettings.patch
@@ -1,25 +1,22 @@
 diff --git a/src/Views/FirewallPanel.vala b/src/Views/FirewallPanel.vala
-index 994c4d1..5702de2 100644
+index 0335c29..481b1c8 100644
 --- a/src/Views/FirewallPanel.vala
 +++ b/src/Views/FirewallPanel.vala
-@@ -49,10 +49,13 @@ public class SecurityPrivacy.FirewallPanel : Granite.SimpleSettingsPage {
+@@ -49,7 +49,11 @@ public class SecurityPrivacy.FirewallPanel : Granite.SimpleSettingsPage {
      }
  
      construct {
 -        settings = new Settings ("io.elementary.switchboard.security-privacy");
 +        SettingsSchemaSource sss = new SettingsSchemaSource.from_directory ("@SWITCHBOARD_SEC_PRIV_GSETTINGS_PATH@", SettingsSchemaSource.get_default (), true);
 +        SettingsSchema security_privacy_schema = sss.lookup ("io.elementary.switchboard.security-privacy", false);
++
 +        settings = new Settings.full (security_privacy_schema, null, null);
 +
          disabled_rules = new Gee.HashMap<string, UFWHelpers.Rule> ();
          load_disabled_rules ();
--        
-+
-         status_switch.notify["active"].connect (() => {
-             if (loading == false) {
-                 view.sensitive = status_switch.active;
+ 
 diff --git a/src/Views/LockPanel.vala b/src/Views/LockPanel.vala
-index 081cf10..42f6118 100644
+index 4f523f9..7135a83 100644
 --- a/src/Views/LockPanel.vala
 +++ b/src/Views/LockPanel.vala
 @@ -30,7 +30,10 @@ public class SecurityPrivacy.LockPanel : Granite.SimpleSettingsPage {
@@ -32,5 +29,5 @@ index 081cf10..42f6118 100644
 +
 +        locker = new Settings.full (locker_schema, null, null);
  
-         var lock_suspend_label = new Gtk.Label (_("Lock on sleep:"));
+         var lock_suspend_label = new Gtk.Label (_("Lock on suspend:"));
          var lock_suspend_switch = new Gtk.Switch ();
diff --git a/pkgs/desktops/pantheon/artwork/elementary-gtk-theme/default.nix b/pkgs/desktops/pantheon/artwork/elementary-gtk-theme/default.nix
index fe9db999bb6..34a87a6cb16 100644
--- a/pkgs/desktops/pantheon/artwork/elementary-gtk-theme/default.nix
+++ b/pkgs/desktops/pantheon/artwork/elementary-gtk-theme/default.nix
@@ -3,11 +3,12 @@
 , pantheon
 , meson
 , ninja
+, gettext
 }:
 
 stdenv.mkDerivation rec {
   pname = "elementary-gtk-theme";
-  version = "5.2.5";
+  version = "5.3.0";
 
   repoName = "stylesheet";
 
@@ -15,7 +16,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "0934rfdwkn4315mhayzba8a3b6i1xczp66gl6n45hh5c81gb2p65";
+    sha256 = "0kxzgqgzbkwi0h4r7zc5yl57k8cm165d1ki1nzmb442wp42q438y";
   };
 
   passthru = {
@@ -26,6 +27,7 @@ stdenv.mkDerivation rec {
   };
 
   nativeBuildInputs = [
+    gettext
     meson
     ninja
   ];
diff --git a/pkgs/desktops/pantheon/artwork/elementary-icon-theme/default.nix b/pkgs/desktops/pantheon/artwork/elementary-icon-theme/default.nix
index 7467bd124ac..1fba6a949d6 100644
--- a/pkgs/desktops/pantheon/artwork/elementary-icon-theme/default.nix
+++ b/pkgs/desktops/pantheon/artwork/elementary-icon-theme/default.nix
@@ -10,7 +10,7 @@
 
 stdenv.mkDerivation rec {
   pname = "elementary-icon-theme";
-  version = "5.0.4";
+  version = "5.1.0";
 
   repoName = "icons";
 
@@ -18,7 +18,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "0ha7biqvmkv68x1gi9bfcn5z0ld067pa5czx0pyf053pa86lg3hx";
+    sha256 = "1yrf92ysjh1yfm42wznlw0lh9zsm5whghwzx3b3wcdkwdhkdg24z";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/default.nix b/pkgs/desktops/pantheon/default.nix
index 11193fe872d..9e5391243bd 100644
--- a/pkgs/desktops/pantheon/default.nix
+++ b/pkgs/desktops/pantheon/default.nix
@@ -1,4 +1,4 @@
-{ pkgs, lib, gnome3 }:
+{ config, pkgs, lib, gnome3 }:
 
 
 lib.makeScope pkgs.newScope (self: with self; {
@@ -66,6 +66,8 @@ lib.makeScope pkgs.newScope (self: with self; {
 
   #### APPS
 
+  appcenter = callPackage ./apps/appcenter { };
+
   elementary-calculator = callPackage ./apps/elementary-calculator { };
 
   elementary-calendar = callPackage ./apps/elementary-calendar { };
@@ -76,6 +78,8 @@ lib.makeScope pkgs.newScope (self: with self; {
 
   elementary-files = callPackage ./apps/elementary-files { };
 
+  elementary-feedback = callPackage ./apps/elementary-feedback { };
+
   elementary-music = callPackage ./apps/elementary-music { };
 
   elementary-photos = callPackage ./apps/elementary-photos { };
@@ -86,12 +90,16 @@ lib.makeScope pkgs.newScope (self: with self; {
 
   elementary-videos = callPackage ./apps/elementary-videos { };
 
+  sideload = callPackage ./apps/sideload { };
+
   #### DESKTOP
 
   elementary-default-settings = callPackage ./desktop/elementary-default-settings { };
 
   elementary-greeter = callPackage ./desktop/elementary-greeter { };
 
+  elementary-onboarding = callPackage ./desktop/elementary-onboarding { };
+
   elementary-print-shim = callPackage ./desktop/elementary-print-shim { };
 
   elementary-session-settings = callPackage ./desktop/elementary-session-settings {
@@ -219,8 +227,10 @@ lib.makeScope pkgs.newScope (self: with self; {
 
   elementary-wallpapers = callPackage ./artwork/elementary-wallpapers { };
 
+} // lib.optionalAttrs (config.allowAliases or true) {
+
   ### ALIASES
 
-  vala = pkgs.vala; # added 2019-10-10
+  inherit (pkgs) vala; # added 2019-10-10
 
 })
diff --git a/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix b/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
index 5241aded066..440893935f8 100644
--- a/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
+++ b/pkgs/desktops/pantheon/desktop/elementary-greeter/default.nix
@@ -28,7 +28,7 @@
 
 stdenv.mkDerivation rec {
   pname = "elementary-greeter";
-  version = "5.0";
+  version = "5.0.1";
 
   repoName = "greeter";
 
@@ -36,7 +36,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "01c8acarxwpakyq69xm4bjwppjf8v3ijmns8masd8raxligb2v8b";
+    sha256 = "0qy6iw71p8hv6fpcr7p3hqbzlcpxrz18qdm1inannq68d0pxfx76";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/desktop/elementary-greeter/hardcode-fallback-background.patch b/pkgs/desktops/pantheon/desktop/elementary-greeter/hardcode-fallback-background.patch
index 556a0fc82a1..7d2afe7b16c 100644
--- a/pkgs/desktops/pantheon/desktop/elementary-greeter/hardcode-fallback-background.patch
+++ b/pkgs/desktops/pantheon/desktop/elementary-greeter/hardcode-fallback-background.patch
@@ -1,7 +1,7 @@
-diff --git a/src/Cards/BackgroundImage.vala b/src/Cards/BackgroundImage.vala
-index b57fb4d..ddfd56c 100644
---- a/src/Cards/BackgroundImage.vala
-+++ b/src/Cards/BackgroundImage.vala
+diff --git a/src/Widgets/BackgroundImage.vala b/src/Widgets/BackgroundImage.vala
+index ae9431c..f0f2a49 100644
+--- a/src/Widgets/BackgroundImage.vala
++++ b/src/Widgets/BackgroundImage.vala
 @@ -9,7 +9,7 @@ public class Greeter.BackgroundImage : Gtk.EventBox {
  
      public BackgroundImage (string? path) {
@@ -16,7 +16,7 @@ index b57fb4d..ddfd56c 100644
  
              try {
 -                full_pixbuf = new Gdk.Pixbuf.from_file ("/usr/share/backgrounds/elementaryos-default");
-+                full_pixbuf = new Gdk.Pixbuf.from_file ("@default_wallpaper");
++                full_pixbuf = new Gdk.Pixbuf.from_file ("@default_wallpaper@");
              } catch (GLib.Error e) {
                  critical (e.message);
              }
diff --git a/pkgs/desktops/pantheon/desktop/elementary-onboarding/default.nix b/pkgs/desktops/pantheon/desktop/elementary-onboarding/default.nix
new file mode 100644
index 00000000000..3ee55a141b8
--- /dev/null
+++ b/pkgs/desktops/pantheon/desktop/elementary-onboarding/default.nix
@@ -0,0 +1,79 @@
+{ stdenv
+, fetchFromGitHub
+, pantheon
+, fetchpatch
+, pkgconfig
+, meson
+, ninja
+, vala
+, python3
+, gtk3
+, glib
+, granite
+, libgee
+, elementary-icon-theme
+, elementary-gtk-theme
+, gettext
+, wrapGAppsHook
+}:
+
+stdenv.mkDerivation rec {
+  pname = "elementary-onboarding";
+  version = "1.0.1";
+
+  repoName = "onboarding";
+
+  src = fetchFromGitHub {
+    owner = "elementary";
+    repo = repoName;
+    rev = version;
+    sha256 = "025i9av4waqwp1gn8d6sjp8qdwg2j3jskxhmyf9qxbzwfc5msysg";
+  };
+
+  passthru = {
+    updateScript = pantheon.updateScript {
+      inherit repoName;
+      attrPath = pname;
+    };
+  };
+
+  nativeBuildInputs = [
+    gettext
+    meson
+    ninja
+    pkgconfig
+    python3
+    vala
+    wrapGAppsHook
+  ];
+
+  buildInputs = [
+    elementary-icon-theme
+    granite
+    gtk3
+    elementary-gtk-theme
+    libgee
+    glib
+  ];
+
+  patches = [
+    # Make sure we use our logo from /etc/os-release
+    (fetchpatch {
+      url = "https://github.com/elementary/onboarding/commit/03975bacb75741d3dd391a126217e415f43c6059.patch";
+      sha256 = "1yw7dysav90abxnmkv86bc60dyl8nvi0sgaiz8v39cc2x00rqsg1";
+    })
+  ];
+
+  postPatch = ''
+    chmod +x meson/post_install.py
+    patchShebangs meson/post_install.py
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Onboarding app for new users designed for elementary OS";
+    homepage = https://github.com/elementary/onboarding;
+    license = licenses.gpl3Plus;
+    platforms = platforms.linux;
+    maintainers = pantheon.maintainers;
+  };
+}
diff --git a/pkgs/desktops/pantheon/desktop/gala/default.nix b/pkgs/desktops/pantheon/desktop/gala/default.nix
index b80e93279c8..4b75b3bff56 100644
--- a/pkgs/desktops/pantheon/desktop/gala/default.nix
+++ b/pkgs/desktops/pantheon/desktop/gala/default.nix
@@ -26,13 +26,13 @@
 
 stdenv.mkDerivation rec {
   pname = "gala";
-  version = "unstable-2019-07-21"; # Is tracking https://github.com/elementary/gala/commits/stable/juno
+  version = "unstable-2019-10-31"; # Is tracking https://github.com/elementary/gala/commits/stable/juno
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
-    rev = "50694796d4c8f0ca92517d5a628b0efdf748279c";
-    sha256 = "17d0hd2145mrf8y5ws3xypdbwj72qv7hrrp6p6lm4k16xd96yznr";
+    rev = "0f0724c97ad49f470f41c4a25c63103f51122997";
+    sha256 = "09cl3k2am878iiy76bijb0ykrcafh944kz027jgi1y5yk4bwfjc4";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/applications-menu/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/applications-menu/default.nix
index ae138c9215c..a266223eced 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/applications-menu/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/applications-menu/default.nix
@@ -26,7 +26,7 @@
 
 stdenv.mkDerivation rec {
   pname = "wingpanel-applications-menu";
-  version = "2.4.3";
+  version = "2.4.4";
 
   repoName = "applications-menu";
 
@@ -34,7 +34,7 @@ stdenv.mkDerivation rec {
     owner = "elementary";
     repo = repoName;
     rev = version;
-    sha256 = "15mwfynaa57jii43x77iaz5gqjlylh5zxc70am8zgp8vhgzflvyd";
+    sha256 = "09ssxn264v6nzrxgk529kpdxq5j3b14z8mbwq0gni1bgjcla773d";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/bluetooth/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/bluetooth/default.nix
index 36d1cf0e77a..3a462219f1e 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/bluetooth/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/bluetooth/default.nix
@@ -12,8 +12,6 @@
 , wingpanel
 , libgee
 , libxml2
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -40,11 +38,9 @@ stdenv.mkDerivation rec {
     pkgconfig
     python3
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
index 74542b5c4c4..91549342052 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/datetime/default.nix
@@ -16,8 +16,6 @@
 , libxml2
 , libsoup
 , elementary-calendar
-, elementary-icon-theme
-, wrapGAppsHook
 , fetchurl
 }:
 
@@ -37,13 +35,13 @@ in
 
 stdenv.mkDerivation rec {
   pname = "wingpanel-indicator-datetime";
-  version = "2.1.3";
+  version = "2.2.0";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "1y7a4xjwl3bpls56ys6g3s6mh5b3qbjm2vw7b6n2i4x7a63c4cbh";
+    sha256 = "1whdx0vgm0qbbzsw8dg2liz3cbh3ad5ybkriy4lmx5ynyhpbz0sx";
   };
 
   passthru = {
@@ -59,11 +57,9 @@ stdenv.mkDerivation rec {
     pkgconfig
     python3
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     old-evolution-data-server
     granite
     gtk3
@@ -73,31 +69,11 @@ stdenv.mkDerivation rec {
     wingpanel
   ];
 
-  patches = [
-    # Use "clock-format" GSettings key that's been moved to granite
-    (fetchpatch {
-      url = "https://src.fedoraproject.org/rpms/wingpanel-indicator-datetime/raw/c8d515b76aa812c141212d5515621a6febd781a3/f/00-move-clock-format-settings-to-granite.patch";
-      sha256 = "1sq3aw9ckkm057rnrclnw9lyrxbpl37fyzfnbixi2q3ypr70n880";
-    })
-    # See: https://github.com/elementary/wingpanel-indicator-datetime/pull/117
-    (fetchpatch {
-      url = "https://github.com/elementary/wingpanel-indicator-datetime/commit/4859e72a52d8dac5cad87b192fc912fb013b0ecd.patch";
-      sha256 = "0jfhb5sax4sivdfx7il1rc1dvhy0yfv27qhvwbdy0hza9wf8q9k0";
-    })
-  ];
-
-  PKG_CONFIG_WINGPANEL_2_0_INDICATORSDIR = "${placeholder "out"}/lib/wingpanel";
-
   postPatch = ''
     chmod +x meson/post_install.py
     patchShebangs meson/post_install.py
   '';
 
-  # launches elementary-calendar on selection
-  preFixup = ''
-     gappsWrapperArgs+=( --prefix PATH : "${elementary-calendar}/bin" )
-  '';
-
   meta = with stdenv.lib; {
     description = "Date & Time Indicator for Wingpanel";
     homepage = https://github.com/elementary/wingpanel-indicator-datetime;
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/keyboard/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/keyboard/default.nix
index 5431b982f54..2f917b19f11 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/keyboard/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/keyboard/default.nix
@@ -13,8 +13,6 @@
 , libgee
 , xorg
 , libgnomekbd
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -40,11 +38,9 @@ stdenv.mkDerivation rec {
     libxml2
     pkgconfig
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/network/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/network/default.nix
index 6ba19ebf77e..01a815404a6 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/network/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/network/default.nix
@@ -11,8 +11,6 @@
 , networkmanagerapplet
 , wingpanel
 , libgee
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -37,11 +35,9 @@ stdenv.mkDerivation rec {
     ninja
     pkgconfig
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/nightlight/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/nightlight/default.nix
index 0327d5e78e2..3b50866c0ed 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/nightlight/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/nightlight/default.nix
@@ -10,8 +10,6 @@
 , wingpanel
 , libgee
 , libxml2
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -37,11 +35,9 @@ stdenv.mkDerivation rec {
     ninja
     pkgconfig
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/notifications/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/notifications/default.nix
index a4266a6f459..4dbf6528c70 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/notifications/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/notifications/default.nix
@@ -10,8 +10,6 @@
 , wingpanel
 , libgee
 , libwnck3
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -36,11 +34,9 @@ stdenv.mkDerivation rec {
     ninja
     pkgconfig
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/power/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/power/default.nix
index 9f9d4703060..b989bada571 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/power/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/power/default.nix
@@ -13,8 +13,6 @@
 , udev
 , wingpanel
 , libgee
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -40,12 +38,10 @@ stdenv.mkDerivation rec {
     pkgconfig
     python3
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
     bamf
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/session/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/session/default.nix
index f48638ff2b1..7efb03f9d66 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/session/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/session/default.nix
@@ -10,8 +10,6 @@
 , wingpanel
 , accountsservice
 , libgee
-, elementary-icon-theme
-, wrapGAppsHook
 }:
 
 stdenv.mkDerivation rec {
@@ -36,12 +34,10 @@ stdenv.mkDerivation rec {
     ninja
     pkgconfig
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
     accountsservice
-    elementary-icon-theme
     granite
     gtk3
     libgee
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/sound/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/sound/default.nix
index 038ab75094c..fa89cca68c0 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel-indicators/sound/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel-indicators/sound/default.nix
@@ -14,8 +14,6 @@
 , libcanberra-gtk3
 , libgee
 , libxml2
-, wrapGAppsHook
-, elementary-icon-theme
 }:
 
 stdenv.mkDerivation rec {
@@ -42,11 +40,9 @@ stdenv.mkDerivation rec {
     pkgconfig
     python3
     vala
-    wrapGAppsHook
   ];
 
   buildInputs = [
-    elementary-icon-theme
     granite
     gtk3
     libcanberra-gtk3
diff --git a/pkgs/desktops/pantheon/desktop/wingpanel/default.nix b/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
index 06f0fc23a39..1fc7304feb2 100644
--- a/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
+++ b/pkgs/desktops/pantheon/desktop/wingpanel/default.nix
@@ -20,13 +20,13 @@
 
 stdenv.mkDerivation rec {
   pname = "wingpanel";
-  version = "2.2.5";
+  version = "2.2.6";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "15pl3km8jfmlgrrb2fcabdd0rkc849arz6sc3vz6azzpln7gxbq7";
+    sha256 = "0q5jhg3gpcjfzfi7g33fv8pb916cqsgk6543b82yy97c20902ap9";
   };
 
   passthru = {
diff --git a/pkgs/desktops/pantheon/granite/default.nix b/pkgs/desktops/pantheon/granite/default.nix
index b93eb2f3f9b..ab673832857 100644
--- a/pkgs/desktops/pantheon/granite/default.nix
+++ b/pkgs/desktops/pantheon/granite/default.nix
@@ -1,6 +1,5 @@
 { stdenv
 , fetchFromGitHub
-, fetchpatch
 , python3
 , meson
 , ninja
@@ -17,30 +16,15 @@
 
 stdenv.mkDerivation rec {
   pname = "granite";
-  version = "5.2.3";
+  version = "5.2.5";
 
   src = fetchFromGitHub {
     owner = "elementary";
     repo = pname;
     rev = version;
-    sha256 = "10ddq1s2w4jvpzq813cylmqhh8pggzaz890fy3kzg07275i98gah";
+    sha256 = "0z40vhcp2w8s8rnc56pzvjc4s77bln8k84rwwypivjmk3lhpw1vi";
   };
 
-  patches = [
-    # Resolve the circular dependency between granite and the datetime wingpanel indicator
-    # See: https://github.com/elementary/granite/pull/242
-    (fetchpatch {
-      url = "https://src.fedoraproject.org/rpms/granite/raw/0550b44ed6400c9b1ff7e70871913747df2ff323/f/00-datetime-clock-format-gsettings.patch";
-      sha256 = "0i9yvdmn77x5fjdwd1raw6ym8js8yxa7w6ydc7syx7hcyls00dmq";
-    })
-
-    # Fix build latest vala.
-    (fetchpatch {
-      url = "https://github.com/elementary/granite/commit/fd26013c84afdeb6300ae2f4a574856753fc2b58.patch";
-      sha256 = "01nxqhj8gr61n6wx6ccrqdn25nmbrhhk437k21g4mxqx0gnih265";
-    })
-  ];
-
   passthru = {
     updateScript = pantheon.updateScript {
       repoName = pname;
diff --git a/pkgs/desktops/pantheon/update.sh b/pkgs/desktops/pantheon/update.sh
index 9bbbe260034..8d002fe47c2 100755
--- a/pkgs/desktops/pantheon/update.sh
+++ b/pkgs/desktops/pantheon/update.sh
@@ -114,13 +114,7 @@ EOF
     function get_latest_tag ( ) {
         repo_name="$1"
 
-        # Using github release api because sorting this repo just doesn't work because of old git sillyness
-        # Also too lazy to care to adapt `git ls-remote` command to work with it
-        if [ $repo_name == "switchboard-plug-pantheon-shell" ]; then
-            curl --silent --show-error --fail -X GET "https://api.github.com/repos/elementary/$repo_name/releases/latest" | jq -r '.tag_name'
-        else
-            git ls-remote --tags --sort="v:refname" "https://github.com/elementary/$repo_name" | tail -n1 | sed 's/.*\///; s/\^{}//'
-        fi
+        curl --silent --show-error --fail -X GET "https://api.github.com/repos/elementary/$repo_name/releases/latest" | jq -r '.tag_name'
     }
 
 #
diff --git a/pkgs/development/compilers/gcc/7/default.nix b/pkgs/development/compilers/gcc/7/default.nix
index 68c05d28978..39b3e4734fe 100644
--- a/pkgs/development/compilers/gcc/7/default.nix
+++ b/pkgs/development/compilers/gcc/7/default.nix
@@ -6,6 +6,7 @@
 , profiledCompiler ? false
 , staticCompiler ? false
 , enableShared ? true
+, enableLTO ? true
 , texinfo ? null
 , perl ? null # optional, for texi2pod (then pod2man)
 , gmp, mpfr, libmpc, gettext, which
@@ -257,7 +258,7 @@ stdenv.mkDerivation ({
 
     # Basic configuration
     [
-      "--enable-lto"
+      (if enableLTO then "--enable-lto" else "--disable-lto")
       "--disable-libstdcxx-pch"
       "--without-included-gettext"
       "--with-system-zlib"
diff --git a/pkgs/development/compilers/gcc/8/default.nix b/pkgs/development/compilers/gcc/8/default.nix
index b84b8958325..52f568b2ed9 100644
--- a/pkgs/development/compilers/gcc/8/default.nix
+++ b/pkgs/development/compilers/gcc/8/default.nix
@@ -6,6 +6,7 @@
 , profiledCompiler ? false
 , staticCompiler ? false
 , enableShared ? true
+, enableLTO ? true
 , texinfo ? null
 , perl ? null # optional, for texi2pod (then pod2man)
 , gmp, mpfr, libmpc, gettext, which
@@ -247,7 +248,7 @@ stdenv.mkDerivation ({
 
     # Basic configuration
     [
-      "--enable-lto"
+      (if enableLTO then "--enable-lto" else "--disable-lto")
       "--disable-libstdcxx-pch"
       "--without-included-gettext"
       "--with-system-zlib"
diff --git a/pkgs/development/compilers/ispc/default.nix b/pkgs/development/compilers/ispc/default.nix
index 762d1233bb6..0c44595b24b 100644
--- a/pkgs/development/compilers/ispc/default.nix
+++ b/pkgs/development/compilers/ispc/default.nix
@@ -20,7 +20,7 @@ stdenv.mkDerivation rec {
   # there are missing dependencies in the Makefile, causing sporadic build failures
   enableParallelBuilding = false;
 
-  doCheck = true;
+  doCheck = stdenv.isLinux;
 
   buildInputs = with llvmPackages; [
     which
@@ -67,7 +67,7 @@ stdenv.mkDerivation rec {
     homepage = https://ispc.github.io/ ;
     description = "Intel 'Single Program, Multiple Data' Compiler, a vectorised language";
     license = licenses.bsd3;
-    platforms = ["x86_64-linux"]; # TODO: buildable on more platforms?
+    platforms = ["x86_64-linux" "x86_64-darwin"]; # TODO: buildable on more platforms?
     maintainers = [ maintainers.aristid ];
   };
 }
diff --git a/pkgs/development/compilers/pakcs/curry-base.nix b/pkgs/development/compilers/pakcs/curry-base.nix
index 2d98699d283..b34a2146383 100644
--- a/pkgs/development/compilers/pakcs/curry-base.nix
+++ b/pkgs/development/compilers/pakcs/curry-base.nix
@@ -3,7 +3,7 @@
 }:
 mkDerivation {
   pname = "curry-base";
-  version = "1.0.0";
+  version = "1.1.0";
   src = ./.;
   libraryHaskellDepends = [
     base containers directory extra filepath mtl parsec pretty time
diff --git a/pkgs/development/compilers/pakcs/curry-frontend.nix b/pkgs/development/compilers/pakcs/curry-frontend.nix
index d94bef9ec7f..b169578c7c3 100644
--- a/pkgs/development/compilers/pakcs/curry-frontend.nix
+++ b/pkgs/development/compilers/pakcs/curry-frontend.nix
@@ -1,21 +1,23 @@
-{ mkDerivation, base, Cabal, containers, curry-base, directory
-, extra, filepath, mtl, network-uri, pretty, process, set-extra
-, stdenv, transformers
+{ mkDerivation, base, bytestring, Cabal, containers, curry-base
+, directory, extra, file-embed, filepath, mtl, network-uri, pretty
+, process, set-extra, stdenv, template-haskell, transformers
 }:
 mkDerivation {
   pname = "curry-frontend";
-  version = "1.0.2";
+  version = "1.0.4";
   src = ./.;
   isLibrary = true;
   isExecutable = true;
   enableSeparateDataOutput = true;
   libraryHaskellDepends = [
-    base containers curry-base directory extra filepath mtl network-uri
-    pretty process set-extra transformers
+    base bytestring containers curry-base directory extra file-embed
+    filepath mtl network-uri pretty process set-extra template-haskell
+    transformers
   ];
   executableHaskellDepends = [
-    base containers curry-base directory extra filepath mtl network-uri
-    pretty process set-extra transformers
+    base bytestring containers curry-base directory extra file-embed
+    filepath mtl network-uri pretty process set-extra template-haskell
+    transformers
   ];
   testHaskellDepends = [ base Cabal curry-base filepath ];
   homepage = "http://curry-language.org";
diff --git a/pkgs/development/compilers/pakcs/default.nix b/pkgs/development/compilers/pakcs/default.nix
index 0b46bd1f24d..94b6daa888e 100644
--- a/pkgs/development/compilers/pakcs/default.nix
+++ b/pkgs/development/compilers/pakcs/default.nix
@@ -4,13 +4,13 @@
 , curl, git, unzip, gnutar, coreutils, sqlite }:
 
 let
-  name = "pakcs-2.1.2";
+  name = "pakcs-2.2.0";
 
   # Don't switch to development release without a reason, because its
   # source updates without version bump. Prefer current release instead.
   src = fetchurl {
     url = "https://www.informatik.uni-kiel.de/~pakcs/download/${name}-src.tar.gz";
-    sha256 = "0i0nprli3knc7zlp5qkqkpiq3ny36v52hnvgph376l3ajjds7wf6";
+    sha256 = "0c0a6cp9lwha5i90kv9ya2zi1ggnvkf4gwjfzbffgwwa77s2wz2l";
   };
 
   curry-frontend = (haskellPackages.override {
diff --git a/pkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py b/pkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py
index e4a79d0c428..82b2aac39a9 100755
--- a/pkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py
+++ b/pkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py
@@ -6,9 +6,9 @@ You can pass in multiple files or paths.
 
 You'll likely want to use
 ``
-  $ ./update-python-libraries ../../pkgs/development/python-modules/*
+  $ ./update-python-libraries ../../pkgs/development/python-modules/**/default.nix
 ``
-to update all libraries in that folder.
+to update all non-pinned libraries in that folder.
 """
 
 import argparse
diff --git a/pkgs/development/libraries/SDL/find-headers.patch b/pkgs/development/libraries/SDL/find-headers.patch
index 5f75ae9e830..fd498117fd6 100644
--- a/pkgs/development/libraries/SDL/find-headers.patch
+++ b/pkgs/development/libraries/SDL/find-headers.patch
@@ -1,7 +1,8 @@
-diff -ru3 SDL-1.2.15/sdl-config.in SDL-1.2.15-new/sdl-config.in
---- SDL-1.2.15/sdl-config.in	2012-01-19 10:30:06.000000000 +0400
-+++ SDL-1.2.15-new/sdl-config.in	2016-08-22 05:32:52.716397920 +0300
-@@ -42,7 +42,11 @@
+diff --git a/sdl-config.in b/sdl-config.in
+index e0fcc0c..bf7928a 100644
+--- a/sdl-config.in
++++ b/sdl-config.in
+@@ -42,14 +42,18 @@ while test $# -gt 0; do
        echo @SDL_VERSION@
        ;;
      --cflags)
@@ -13,4 +14,13 @@ diff -ru3 SDL-1.2.15/sdl-config.in SDL-1.2.15-new/sdl-config.in
 +      echo $SDL_CFLAGS @SDL_CFLAGS@
        ;;
  @ENABLE_SHARED_TRUE@    --libs)
- @ENABLE_SHARED_TRUE@      echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_LIBS@
+-@ENABLE_SHARED_TRUE@      echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_LIBS@
++@ENABLE_SHARED_TRUE@      echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_LIBS@ $SDL_LIB_PATH
+ @ENABLE_SHARED_TRUE@      ;;
+ @ENABLE_STATIC_TRUE@@ENABLE_SHARED_TRUE@    --static-libs)
+ @ENABLE_STATIC_TRUE@@ENABLE_SHARED_FALSE@    --libs|--static-libs)
+-@ENABLE_STATIC_TRUE@      echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_STATIC_LIBS@
++@ENABLE_STATIC_TRUE@      echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_STATIC_LIBS@ $SDL_LIB_PATH
+ @ENABLE_STATIC_TRUE@      ;;
+     *)
+       echo "${usage}" 1>&2
diff --git a/pkgs/development/libraries/SDL/setup-hook.sh b/pkgs/development/libraries/SDL/setup-hook.sh
index 20382f18f52..e8f96fdd1ac 100644
--- a/pkgs/development/libraries/SDL/setup-hook.sh
+++ b/pkgs/development/libraries/SDL/setup-hook.sh
@@ -1,6 +1,7 @@
 addSDLPath () {
   if [ -e "$1/include/SDL" ]; then
     export SDL_PATH="$SDL_PATH $1/include/SDL"
+    export SDL_LIB_PATH="$SDL_LIB_PATH -L$1/lib"
   fi
 }
 
diff --git a/pkgs/development/libraries/SDL_Pango/default.nix b/pkgs/development/libraries/SDL_Pango/default.nix
new file mode 100644
index 00000000000..e330ccef611
--- /dev/null
+++ b/pkgs/development/libraries/SDL_Pango/default.nix
@@ -0,0 +1,32 @@
+{ stdenv, fetchpatch, fetchurl, SDL, autoreconfHook, pango, pkgconfig }:
+
+stdenv.mkDerivation rec {
+  pname = "SDL_Pango";
+  version = "0.1.2";
+
+  src = fetchurl {
+    url = "mirror://sourceforge/sdlpango/${pname}-${version}.tar.gz";
+    sha256 = "197baw1dsg0p4pljs5k0fshbyki00r4l49m1drlpqw6ggawx6xbz";
+  };
+
+  patches = [ 
+    (fetchpatch {
+      url = https://sources.debian.org/data/main/s/sdlpango/0.1.2-6/debian/patches/api_additions.patch;
+      sha256 = "00p5ry5gd3ixm257p9i2c4jg0qj8ipk8nf56l7c9fma8id3zxyld";
+    })
+    ./fixes.patch
+  ];
+
+  preConfigure = "autoreconf -i -f";
+
+  nativeBuildInputs = [ pkgconfig autoreconfHook ];
+  buildInputs = [ SDL pango ];
+
+  meta = with stdenv.lib; {
+    description = "Connects the Pango rendering engine to SDL";
+    license = licenses.lgpl21Plus;
+    platforms = platforms.all;
+    homepage = http://sdlpango.sourceforge.net/;
+    maintainers = with maintainers; [ puckipedia ];
+  };
+}
diff --git a/pkgs/development/libraries/SDL_Pango/fixes.patch b/pkgs/development/libraries/SDL_Pango/fixes.patch
new file mode 100644
index 00000000000..9703c0d4918
--- /dev/null
+++ b/pkgs/development/libraries/SDL_Pango/fixes.patch
@@ -0,0 +1,148 @@
+diff --git a/SDL_Pango.pc.in b/SDL_Pango.pc.in
+index 750d091..3af38ff 100644
+--- a/SDL_Pango.pc.in
++++ b/SDL_Pango.pc.in
+@@ -6,6 +6,6 @@ includedir=@includedir@
+ Name: SDL_Pango

+ Description: SDL library for internationalized text rendering

+ Version: @VERSION@

+-Requires: pango

++Requires: pango pangoft2
+ Libs: -L${libdir} -lSDL_Pango

+ Cflags: -I${includedir}
+\ No newline at end of file
+diff --git a/src/SDL_Pango.c b/src/SDL_Pango.c
+index b969bc1..cc2c3f5 100644
+--- a/src/SDL_Pango.c
++++ b/src/SDL_Pango.c
+@@ -231,6 +231,41 @@
+ 

+ #include "SDL_Pango.h"

+ 

++const SDLPango_Matrix _MATRIX_WHITE_BACK
++    = {255, 0, 0, 0,
++       255, 0, 0, 0,
++       255, 0, 0, 0,
++       255, 255, 0, 0,};
++const SDLPango_Matrix *MATRIX_WHITE_BACK = &_MATRIX_WHITE_BACK;
++
++const SDLPango_Matrix _MATRIX_BLACK_BACK
++    = {0, 255, 0, 0,
++       0, 255, 0, 0,
++       0, 255, 0, 0,
++       255, 255, 0, 0,};
++const SDLPango_Matrix *MATRIX_BLACK_BACK = &_MATRIX_BLACK_BACK;
++
++const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_BLACK_LETTER
++    = {0, 0, 0, 0,
++       0, 0, 0, 0,
++       0, 0, 0, 0,
++       0, 255, 0, 0,};
++const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_BLACK_LETTER = &_MATRIX_TRANSPARENT_BACK_BLACK_LETTER;
++
++const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_WHITE_LETTER
++    = {255, 255, 0, 0,
++       255, 255, 0, 0,
++       255, 255, 0, 0,
++       0, 255, 0, 0,};
++const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_WHITE_LETTER = &_MATRIX_TRANSPARENT_BACK_WHITE_LETTER;
++
++const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER
++    = {255, 255, 0, 0,
++       255, 255, 0, 0,
++       255, 255, 0, 0,
++       0, 0, 0, 0,};
++const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER = &_MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER;
++
+ //! non-zero if initialized

+ static int IS_INITIALIZED = 0;

+ 

+diff --git a/src/SDL_Pango.h b/src/SDL_Pango.h
+index 6ebdf78..b7e5e58 100644
+--- a/src/SDL_Pango.h
++++ b/src/SDL_Pango.h
+@@ -47,57 +47,32 @@ typedef struct _SDLPango_Matrix {
+     Uint8 m[4][4];  /*! Matrix variables */

+ } SDLPango_Matrix;

+ 

+-const SDLPango_Matrix _MATRIX_WHITE_BACK

+-    = {255, 0, 0, 0,

+-       255, 0, 0, 0,

+-       255, 0, 0, 0,

+-       255, 255, 0, 0,};

+ 

+ /*!

+     Specifies white back and black letter.

+ */

+-const SDLPango_Matrix *MATRIX_WHITE_BACK = &_MATRIX_WHITE_BACK;

++extern const SDLPango_Matrix *MATRIX_WHITE_BACK;
+ 

+-const SDLPango_Matrix _MATRIX_BLACK_BACK

+-    = {0, 255, 0, 0,

+-       0, 255, 0, 0,

+-       0, 255, 0, 0,

+-       255, 255, 0, 0,};

+ /*!

+     Specifies black back and white letter.

+ */

+-const SDLPango_Matrix *MATRIX_BLACK_BACK = &_MATRIX_BLACK_BACK;

++extern const SDLPango_Matrix *MATRIX_BLACK_BACK;
+ 

+-const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_BLACK_LETTER

+-    = {0, 0, 0, 0,

+-       0, 0, 0, 0,

+-       0, 0, 0, 0,

+-       0, 255, 0, 0,};

+ /*!

+     Specifies transparent back and black letter.

+ */

+-const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_BLACK_LETTER = &_MATRIX_TRANSPARENT_BACK_BLACK_LETTER;

++extern const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_BLACK_LETTER;
+ 

+-const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_WHITE_LETTER

+-    = {255, 255, 0, 0,

+-       255, 255, 0, 0,

+-       255, 255, 0, 0,

+-       0, 255, 0, 0,};

+ /*!

+     Specifies transparent back and white letter.

+ */

+-const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_WHITE_LETTER = &_MATRIX_TRANSPARENT_BACK_WHITE_LETTER;

++extern const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_WHITE_LETTER;
+ 

+-const SDLPango_Matrix _MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER

+-    = {255, 255, 0, 0,

+-       255, 255, 0, 0,

+-       255, 255, 0, 0,

+-       0, 0, 0, 0,};

+ /*!

+     Specifies transparent back and transparent letter.

+     This is useful for KARAOKE like rendering.

+ */

+-const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER = &_MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER;

++extern const SDLPango_Matrix *MATRIX_TRANSPARENT_BACK_TRANSPARENT_LETTER;
+ 

+ /*!

+     Specifies direction of text. See Pango reference for detail

+@@ -186,7 +161,8 @@ extern DECLSPEC void SDLCALL SDLPango_SetBaseDirection(
+     SDLPango_Direction direction);

+ 

+ 

+-#ifdef __FT2_BUILD_UNIX_H__

++

++#ifdef __PANGO_H__

+ 

+ extern DECLSPEC void SDLCALL SDLPango_CopyFTBitmapToSurface(

+     const FT_Bitmap *bitmap,

+@@ -194,11 +170,8 @@ extern DECLSPEC void SDLCALL SDLPango_CopyFTBitmapToSurface(
+     const SDLPango_Matrix *matrix,

+     SDL_Rect *rect);

+ 

+-#endif	/* __FT2_BUILD_UNIX_H__ */

+ 

+ 

+-#ifdef __PANGO_H__

+-

+ extern DECLSPEC PangoFontMap* SDLCALL SDLPango_GetPangoFontMap(

+     SDLPango_Context *context);

+ 

diff --git a/pkgs/development/libraries/gegl/4.0.nix b/pkgs/development/libraries/gegl/4.0.nix
index 0e3f79b1814..2edb47cb9bb 100644
--- a/pkgs/development/libraries/gegl/4.0.nix
+++ b/pkgs/development/libraries/gegl/4.0.nix
@@ -1,31 +1,123 @@
-{ stdenv, fetchurl, pkgconfig, glib, babl, libpng, cairo, libjpeg, which
-, librsvg, pango, gtk, bzip2, json-glib, gettext, autoreconfHook, libraw
-, gexiv2, libwebp, libintl }:
+{ stdenv
+, fetchurl
+, fetchpatch
+, pkgconfig
+, vala
+, gobject-introspection
+, gtk-doc
+, docbook_xsl
+, docbook_xml_dtd_43
+, glib
+, babl
+, libpng
+, cairo
+, libjpeg
+, librsvg
+, lensfun
+, libspiro
+, netsurf
+, pango
+, poly2tri-c
+, bzip2
+, json-glib
+, gettext
+, meson
+, ninja
+, libraw
+, gexiv2
+, libwebp
+, luajit
+, openexr
+, OpenCL
+}:
 
 stdenv.mkDerivation rec {
   pname = "gegl";
-  version = "0.4.16";
+  version = "0.4.18";
 
   outputs = [ "out" "dev" "devdoc" ];
   outputBin = "dev";
 
   src = fetchurl {
-    url = "https://download.gimp.org/pub/gegl/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.bz2";
-    sha256 = "0njydcr6qdmfzh4fxx544681qxdpf7y6b2f47jcypn810dlxy4h1";
+    url = "https://download.gimp.org/pub/gegl/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
+    sha256 = "0r6akqnrkvxizyhyi8sv40mxm7j4bcwjb6mqjpxy0zzbbfsdyin9";
   };
 
-  enableParallelBuilding = true;
+  patches = [
+    # Fix arch detection.
+    # https://gitlab.gnome.org/GNOME/gegl/merge_requests/53
+    (fetchpatch {
+      url = "https://gitlab.gnome.org/GNOME/gegl/commit/6bcf95fd0f32cf5e8b1ddbe17b14d9ad049bded8.patch";
+      sha256 = "0aqdr3y5mr47wq44jnhp97188bvpjlf56zrlmn8aazdf07r2apma";
+    })
 
-  doCheck = true;
+    # Fix Darwin build.
+    # https://gitlab.gnome.org/GNOME/gegl/merge_requests/54
+    (fetchpatch {
+      url = "https://gitlab.gnome.org/GNOME/gegl/commit/2bc06bfedee4fb25f6a966c8235b75292e24e55f.patch";
+      sha256 = "1psls61wsrdq5pzpvj22mrm46lpzrw3wkx6li7dv6fyb65wz2n4d";
+    })
+  ];
+
+  nativeBuildInputs = [
+    pkgconfig
+    gettext
+    meson
+    ninja
+    vala
+    gobject-introspection
+    gtk-doc
+    docbook_xsl
+    docbook_xml_dtd_43
+  ];
 
   buildInputs = [
-    libpng cairo libjpeg librsvg pango gtk bzip2
-    libraw libwebp gexiv2
+    libpng
+    cairo
+    libjpeg
+    librsvg
+    lensfun
+    libspiro
+    netsurf.libnsgif
+    pango
+    poly2tri-c
+    bzip2
+    libraw
+    libwebp
+    gexiv2
+    luajit
+    openexr
+  ] ++ stdenv.lib.optional stdenv.isDarwin OpenCL;
+
+  # for gegl-4.0.pc
+  propagatedBuildInputs = [
+    glib
+    json-glib
+    babl
   ];
 
-  propagatedBuildInputs = [ glib json-glib babl ]; # for gegl-4.0.pc
+  mesonFlags = [
+    "-Ddocs=true"
+    "-Dmrg=disabled" # not sure what that is
+    "-Dsdl2=disabled"
+    "-Dpygobject=disabled"
+    "-Dlibav=disabled"
+    "-Dlibv4l=disabled"
+    "-Dlibv4l2=disabled"
+    "-Dumfpack=disabled"
+  ];
+
+  # TODO: Fix missing math symbols in gegl seamless clone.
+  # It only appears when we use packaged poly2tri-c instead of vendored one.
+  NIX_CFLAGS_COMPILE = [ "-lm" ];
+
+  postPatch = ''
+    chmod +x tests/opencl/opencl_test.sh tests/buffer/buffer-tests-run.sh
+    patchShebangs tests/ff-load-save/tests_ff_load_save.sh tests/opencl/opencl_test.sh tests/buffer/buffer-tests-run.sh tools/xml_insert.sh
+  '';
 
-  nativeBuildInputs = [ pkgconfig gettext which autoreconfHook libintl ];
+  # tests fail to connect to the com.apple.fonts daemon in sandboxed mode
+  doCheck = !stdenv.isDarwin;
 
   meta = with stdenv.lib; {
     description = "Graph-based image processing framework";
diff --git a/pkgs/development/libraries/gnu-efi/default.nix b/pkgs/development/libraries/gnu-efi/default.nix
index af225cc50f2..6ae1f47e38c 100644
--- a/pkgs/development/libraries/gnu-efi/default.nix
+++ b/pkgs/development/libraries/gnu-efi/default.nix
@@ -1,4 +1,6 @@
-{ stdenv, fetchurl, pciutils }: with stdenv.lib;
+{ stdenv, buildPackages, fetchurl, pciutils }:
+
+with stdenv.lib;
 
 stdenv.mkDerivation rec {
   pname = "gnu-efi";
@@ -15,14 +17,9 @@ stdenv.mkDerivation rec {
 
   makeFlags = [
     "PREFIX=\${out}"
-    "CC=${stdenv.cc.targetPrefix}gcc"
-    "AS=${stdenv.cc.targetPrefix}as"
-    "LD=${stdenv.cc.targetPrefix}ld"
-    "AR=${stdenv.cc.targetPrefix}ar"
-    "RANLIB=${stdenv.cc.targetPrefix}ranlib"
-    "OBJCOPY=${stdenv.cc.targetPrefix}objcopy"
-  ] ++ stdenv.lib.optional stdenv.isAarch32 "ARCH=arm"
-    ++ stdenv.lib.optional stdenv.isAarch64 "ARCH=aarch64";
+    "HOSTCC=${buildPackages.stdenv.cc.targetPrefix}cc"
+    "CROSS_COMPILE=${stdenv.cc.targetPrefix}"
+  ];
 
   meta = with stdenv.lib; {
     description = "GNU EFI development toolchain";
diff --git a/pkgs/development/libraries/hunspell/dictionaries.nix b/pkgs/development/libraries/hunspell/dictionaries.nix
index 3e1799d82cd..fb64aa81d1a 100644
--- a/pkgs/development/libraries/hunspell/dictionaries.nix
+++ b/pkgs/development/libraries/hunspell/dictionaries.nix
@@ -722,4 +722,14 @@ in rec {
       platforms = platforms.all;
     };
   };
+
+  /* RUSSIAN */
+
+  ru_RU = ru-ru;
+  ru-ru = mkDictFromLibreOffice {
+    shortName = "ru-ru";
+    dictFileName = "ru_RU";
+    shortDescription = "Russian (Russian)";
+    license = with stdenv.lib.licenses; [ mpl20 lgpl3 ];
+  };
 }
diff --git a/pkgs/development/libraries/kmsxx/default.nix b/pkgs/development/libraries/kmsxx/default.nix
index 71e88559dee..70058db4c0a 100644
--- a/pkgs/development/libraries/kmsxx/default.nix
+++ b/pkgs/development/libraries/kmsxx/default.nix
@@ -1,25 +1,25 @@
-{ stdenv, fetchFromGitHub, cmake, pkgconfig, libdrm, python }:
+{ stdenv, fetchFromGitHub, cmake, pkgconfig, libdrm
+, withPython ? false, python }:
 
 stdenv.mkDerivation {
   pname = "kmsxx";
-  version = "2018-10-23";
+  version = "2019-10-28";
 
   src = fetchFromGitHub {
     owner = "tomba";
     repo = "kmsxx";
     fetchSubmodules = true;
-    rev = "c0093c91f0fa2fd6a5b9d1b206a6f44dcd55bfb5";
-    sha256 = "03rv92r938nxb4k4gwcvxy76jnhxdx6x60b58jws83285hd9rgkf";
+    rev = "d29da28c7f2a0212d834136fe64fb8ca96a0a235";
+    sha256 = "0r94qjyy3s36s32s1xkzij0g2pfwigmyrshw8ni2xli7mg87g1zm";
   };
 
   enableParallelBuilding = true;
 
+  cmakeFlags = stdenv.lib.optional (!withPython) "-DKMSXX_ENABLE_PYTHON=OFF";
+
   nativeBuildInputs = [ cmake pkgconfig ];
   buildInputs = [ libdrm python ];
 
-  pythonPath = [ ];
-  passthru.python = python;
-
   meta = with stdenv.lib; {
     description = "C++11 library, utilities and python bindings for Linux kernel mode setting";
     homepage = https://github.com/tomba/kmsxx;
diff --git a/pkgs/development/libraries/libjpeg-turbo/default.nix b/pkgs/development/libraries/libjpeg-turbo/default.nix
index cb32b22f45e..f05ac6d521b 100644
--- a/pkgs/development/libraries/libjpeg-turbo/default.nix
+++ b/pkgs/development/libraries/libjpeg-turbo/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, cmake, nasm }:
+{ stdenv, fetchurl, cmake, nasm, enableStatic ? false }:
 
 stdenv.mkDerivation rec {
 
@@ -19,7 +19,7 @@ stdenv.mkDerivation rec {
   nativeBuildInputs = [ cmake nasm ];
 
   cmakeFlags = [
-    "-DENABLE_STATIC=0"
+    "-DENABLE_STATIC=${if enableStatic then "1" else "0"}"
   ];
 
   doInstallCheck = true;
diff --git a/pkgs/development/libraries/mm-common/default.nix b/pkgs/development/libraries/mm-common/default.nix
index f590653df6b..9a789a58cca 100644
--- a/pkgs/development/libraries/mm-common/default.nix
+++ b/pkgs/development/libraries/mm-common/default.nix
@@ -1,14 +1,26 @@
-{ stdenv, fetchurl, gnome3 }:
+{ stdenv
+, fetchurl
+, gnome3
+, meson
+, python3
+, ninja
+}:
 
 stdenv.mkDerivation rec {
   pname = "mm-common";
-  version = "0.9.12";
+  version = "1.0.0";
 
   src = fetchurl {
     url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${pname}-${version}.tar.xz";
-    sha256 = "02vwgv404b56wxy0gnm9xq9fvzgn9dhfqcy2hhl78ljv3v7drzyf";
+    sha256 = "1m4w33da9f4rx2d6kdj3ix3kl0gn16ml82v2mdn4hljr3q29nzdr";
   };
 
+  nativeBuildInputs = [
+    meson
+    python3
+    ninja
+  ];
+
   passthru = {
     updateScript = gnome3.updateScript {
       packageName = pname;
@@ -25,7 +37,7 @@ stdenv.mkDerivation rec {
       control repository. An installation of mm-common is not required for
       building tarball releases, unless configured to use maintainer-mode.
     '';
-    homepage = https://www.gtkmm.org;
+    homepage = "https://www.gtkmm.org";
     license = licenses.gpl2Plus;
     maintainers = gnome3.maintainers;
     platforms = platforms.linux;
diff --git a/pkgs/development/libraries/poly2tri-c/default.nix b/pkgs/development/libraries/poly2tri-c/default.nix
new file mode 100644
index 00000000000..a3e42b3ae4b
--- /dev/null
+++ b/pkgs/development/libraries/poly2tri-c/default.nix
@@ -0,0 +1,42 @@
+{ stdenv
+, fetchFromGitHub
+, autoreconfHook
+, pkgconfig
+, glib
+}:
+
+stdenv.mkDerivation rec {
+  pname = "poly2tri-c";
+  version = "0.1.0";
+
+  outputs = [ "bin" "out" "dev" ];
+
+  src = fetchFromGitHub {
+    owner = "Paul-Browne";
+    repo = "poly2tri-c";
+    rev = "p2tc-${version}";
+    sha256 = "158vm3wqfxs22b74kqc4prlvjny38qqm3kz5wrgasmx0qciwh0g8";
+  };
+
+  nativeBuildInputs = [
+    autoreconfHook
+    pkgconfig
+  ];
+
+  buildInputs = [
+    glib
+  ];
+
+  NIX_CFLAGS_COMPILE = [
+    "--std=gnu99"
+    "-Wno-error"
+  ];
+
+  meta = with stdenv.lib; {
+    description = "Library for generating, refining and rendering 2-Dimensional Constrained Delaunay Triangulations";
+    homepage = "https://code.google.com/archive/p/poly2tri-c/";
+    license = licenses.bsd3;
+    maintainers = with stdenv.lib.maintainers; [ jtojnar ];
+    platforms = platforms.unix;
+  };
+}
diff --git a/pkgs/development/libraries/protobuf/3.10.nix b/pkgs/development/libraries/protobuf/3.10.nix
index 3549d7af75e..5ecb8e67f84 100644
--- a/pkgs/development/libraries/protobuf/3.10.nix
+++ b/pkgs/development/libraries/protobuf/3.10.nix
@@ -1,6 +1,6 @@
 { callPackage, ... }:
 
 callPackage ./generic-v3.nix {
-  version = "3.10.0";
-  sha256 = "0cjwfm9v2gv6skzrq4m7w28810p2h3m1jj4kw6df3x8vvg7q842c";
+  version = "3.10.1";
+  sha256 = "1kbi2i1m5c7ss02ip8h0bdzvns4dgxx30a5c0iiph8g2ns02lr33";
 }
diff --git a/pkgs/development/libraries/protobuf/3.9.nix b/pkgs/development/libraries/protobuf/3.9.nix
index a2f3e0e0164..e74d5c527b1 100644
--- a/pkgs/development/libraries/protobuf/3.9.nix
+++ b/pkgs/development/libraries/protobuf/3.9.nix
@@ -1,6 +1,6 @@
 { callPackage, ... }:
 
 callPackage ./generic-v3.nix {
-  version = "3.9.1";
-  sha256 = "0vv85xb65dx6fa76fsnyps13kaamvwfzd8hr6ii1payr73x4zy2h";
+  version = "3.9.2";
+  sha256 = "080zxa9w1pxp5y05aiwc0c8mlqkkh98wmid4l7m99cliphsd4qnn";
 }
diff --git a/pkgs/development/libraries/wolfssl/default.nix b/pkgs/development/libraries/wolfssl/default.nix
index 780d7df47cb..1bad9c5eb2a 100644
--- a/pkgs/development/libraries/wolfssl/default.nix
+++ b/pkgs/development/libraries/wolfssl/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "wolfssl";
-  version = "4.1.0";
+  version = "4.2.0";
 
   src = fetchFromGitHub {
     owner = "wolfSSL";
     repo = "wolfssl";
     rev = "v${version}-stable";
-    sha256 = "16d1dzbdx6x7czbxf6i1rlb5mv59yzzpnha7qgwab3yq62rlsgw3";
+    sha256 = "16s7jx2brgii6jbpmr30ggkc7rrf388jl26g357sm7ggwliiwask";
   };
 
   configureFlags = [ "--enable-all" ];
diff --git a/pkgs/development/ocaml-modules/mlgmpidl/default.nix b/pkgs/development/ocaml-modules/mlgmpidl/default.nix
index d25a5f4ce06..2733ad2b0fb 100644
--- a/pkgs/development/ocaml-modules/mlgmpidl/default.nix
+++ b/pkgs/development/ocaml-modules/mlgmpidl/default.nix
@@ -2,12 +2,12 @@
 
 stdenv.mkDerivation rec {
   name = "ocaml${ocaml.version}-mlgmpidl-${version}";
-  version = "1.2.10";
+  version = "1.2.11";
   src = fetchFromGitHub {
     owner = "nberth";
     repo = "mlgmpidl";
     rev = version;
-    sha256 = "181vpqx8zdairq645b8qpkzj4fnkb508iavk7sqzskag1s8613qn";
+    sha256 = "1rycl84sdvgb5avdsya9iz8brx92y2zcb6cn4w1j0164j6q2ril9";
   };
 
   buildInputs = [ perl gmp mpfr ocaml findlib camlidl ];
diff --git a/pkgs/development/perl-modules/alien-sdl.patch b/pkgs/development/perl-modules/alien-sdl.patch
new file mode 100644
index 00000000000..b00f7dcce81
--- /dev/null
+++ b/pkgs/development/perl-modules/alien-sdl.patch
@@ -0,0 +1,30 @@
+diff --git a/inc/My/Builder/Unix.pm b/inc/My/Builder/Unix.pm
+index 15291d5..5c5ab24 100644
+--- a/inc/My/Builder/Unix.pm
++++ b/inc/My/Builder/Unix.pm
+@@ -48,7 +48,7 @@ sub get_additional_libs {
+ 
+ sub can_build_binaries_from_sources {
+   my $self = shift;
+-  return 1; # yes we can
++  return 0; # no we can't
+ }
+ 
+ sub build_binaries {
+diff --git a/t/004_get_header_version.t b/t/004_get_header_version.t
+index d4146ff..27f53ea 100644
+--- a/t/004_get_header_version.t
++++ b/t/004_get_header_version.t
+@@ -1,8 +1,11 @@
+ # t/004_config.t
+ 
+-use Test::More tests => 1;
++use Test::More;
+ use Alien::SDL;
+ 
++Test::More::plan( skip_all => 'NixOS doesn\'t have SDL headers in this location' );
++
++
+ like( Alien::SDL->get_header_version('SDL_version.h'), qr/([0-9]+\.)*[0-9]+/, "Testing SDL_version.h" );
+ #like( Alien::SDL->get_header_version('SDL_net.h'), qr/([0-9]+\.)*[0-9]+/, "Testing SDL_net.h" );
+ #like( Alien::SDL->get_header_version('SDL_image.h'), qr/([0-9]+\.)*[0-9]+/, "Testing SDL_image.h" );
diff --git a/pkgs/development/python-modules/deeptoolsintervals/default.nix b/pkgs/development/python-modules/deeptoolsintervals/default.nix
new file mode 100644
index 00000000000..eef8d51ae91
--- /dev/null
+++ b/pkgs/development/python-modules/deeptoolsintervals/default.nix
@@ -0,0 +1,28 @@
+{ lib
+, buildPythonPackage
+, fetchPypi
+, pytest
+, zlib
+, lzma
+}:
+
+buildPythonPackage rec {
+  pname = "deeptoolsintervals";
+  version = "0.1.9";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "1xnl80nblysj6dylj4683wgrfa425rkx4dp5k65hvwdns9pw753x";
+  };
+
+  buildInputs = [ zlib lzma ];
+
+  checkInputs = [ pytest ];
+
+  meta = with lib; {
+    homepage = "https://deeptools.readthedocs.io/en/develop";
+    description = "Helper library for deeptools";
+    license = licenses.mit;
+    maintainers = with maintainers; [ scalavision ];
+  };
+}
diff --git a/pkgs/development/python-modules/koji/default.nix b/pkgs/development/python-modules/koji/default.nix
index 033ab821135..47c42a1df45 100644
--- a/pkgs/development/python-modules/koji/default.nix
+++ b/pkgs/development/python-modules/koji/default.nix
@@ -1,19 +1,19 @@
-{ stdenv, fetchurl, buildPythonPackage, pycurl, six, rpm, dateutil }:
+{ stdenv, fetchurl, buildPythonPackage, isPy3k, pycurl, six, rpm, dateutil }:
 
 buildPythonPackage rec {
   pname = "koji";
-  version = "1.13.0";
+  version = "1.14.3";
   format = "other";
 
   src = fetchurl {
     url = "https://releases.pagure.org/koji/${pname}-${version}.tar.bz2";
-    sha256 = "18b18rcbdqqw33g7h20hf5bpbci2ixdi05yda1fvpv30c1kkzd8w";
+    sha256 = "0a3kn3qvspvx15imgzzzjsbvw6bqmbk29apbliqwifa9cj7pvb40";
   };
 
   propagatedBuildInputs = [ pycurl six rpm dateutil ];
 
   # Judging from SyntaxError
-  #disabled = isPy3k;
+  disabled = isPy3k;
 
   makeFlags = "DESTDIR=$(out)";
 
@@ -24,7 +24,9 @@ buildPythonPackage rec {
   '';
 
   meta = {
-    maintainers = [ ];
+    description = "An RPM-based build system";
+    homepage = https://pagure.io/koji;
+    license = stdenv.lib.licenses.lgpl21;
     platforms = stdenv.lib.platforms.unix;
   };
 }
diff --git a/pkgs/development/python-modules/license-expression/default.nix b/pkgs/development/python-modules/license-expression/default.nix
index 2bf204a9a62..177949fbd51 100644
--- a/pkgs/development/python-modules/license-expression/default.nix
+++ b/pkgs/development/python-modules/license-expression/default.nix
@@ -4,13 +4,13 @@
 
 buildPythonPackage rec {
   pname = "license-expression";
-  version = "0.999";
+  version = "1.0";
 
   src = fetchFromGitHub {
     owner = "nexB";
     repo = "license-expression";
     rev = "v${version}";
-    sha256 = "0q8sha38w7ajg7ar0rmbqrwv0n58l8yzyl96cqwcbvp578fn3ir0";
+    sha256 = "15dk3j5sr8iypzqqa8wa12b2a84f6ssbfvam1c1vzz00y2y5v3ic";
   };
   postPatch = "patchShebangs ./configure";
 
diff --git a/pkgs/development/python-modules/moderngl_window/default.nix b/pkgs/development/python-modules/moderngl_window/default.nix
new file mode 100644
index 00000000000..a3c93978ff6
--- /dev/null
+++ b/pkgs/development/python-modules/moderngl_window/default.nix
@@ -0,0 +1,38 @@
+{ lib
+, buildPythonPackage
+, fetchFromGitHub
+, isPy3k
+, numpy
+, moderngl
+, pyglet
+, pillow
+, pyrr
+, pytest
+}:
+
+buildPythonPackage rec {
+  pname = "moderngl_window";
+  version = "1.2.0";
+
+  src = fetchFromGitHub {
+    owner = "moderngl";
+    repo = pname;
+    rev = version;
+    sha256 = "054w77lyc2nc0dyx76zsrbq2b3xbywdijhb62b2qqm99ldr1k1x5";
+  };
+
+  propagatedBuildInputs = [ numpy moderngl pyglet pillow pyrr ];
+
+  disabled = !isPy3k;
+
+  # Tests need a display to run.
+  doCheck = false;
+
+  meta = with lib; {
+    homepage = "https://github.com/moderngl/moderngl_window";
+    description = "Cross platform helper library for ModernGL making window creation and resource loading simple";
+    license = licenses.mit;
+    platforms = platforms.linux; # should be mesaPlatforms, darwin build breaks.
+    maintainers = with maintainers; [ c0deaddict ];
+  };
+}
diff --git a/pkgs/development/python-modules/nix-prefetch-github/default.nix b/pkgs/development/python-modules/nix-prefetch-github/default.nix
index 71a7701c019..f73fb6dac33 100644
--- a/pkgs/development/python-modules/nix-prefetch-github/default.nix
+++ b/pkgs/development/python-modules/nix-prefetch-github/default.nix
@@ -9,11 +9,11 @@
 
 buildPythonPackage rec {
   pname = "nix-prefetch-github";
-  version = "2.3.1";
+  version = "2.3.2";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "1jkvmj33xinff0sb47yg33n131yi93pyq86skqc78xd38j6c8q9s";
+    sha256 = "18xj618zjs13ib7f996fnl0xiqig0w48yns45nvy3xab55wximdx";
   };
 
   propagatedBuildInputs = [
diff --git a/pkgs/development/python-modules/pg8000/1_12.nix b/pkgs/development/python-modules/pg8000/1_12.nix
index 444da7adc23..efeee5e077f 100644
--- a/pkgs/development/python-modules/pg8000/1_12.nix
+++ b/pkgs/development/python-modules/pg8000/1_12.nix
@@ -7,11 +7,11 @@
 
 buildPythonPackage rec {
   pname = "pg8000";
-  version = "1.13.2";
+  version = "1.12.5";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "eebcb4176a7e407987e525a07454882f611985e0becb2b73f76efb93bbdc0aab";
+    sha256 = "1yc3knh28cx3rjb2ifg5kmqqa78yyyw2gzzslbm9fj0mzh5aq1sx";
   };
 
   propagatedBuildInputs = [ pytz six ];
diff --git a/pkgs/development/python-modules/pre-commit/default.nix b/pkgs/development/python-modules/pre-commit/default.nix
index 18b548faf21..27d56bab06e 100644
--- a/pkgs/development/python-modules/pre-commit/default.nix
+++ b/pkgs/development/python-modules/pre-commit/default.nix
@@ -14,12 +14,12 @@
 
 buildPythonApplication rec {
   pname = "pre-commit";
-  version = "1.18.3";
+  version = "1.20.0";
 
   src = fetchPypi {
     inherit version;
     pname = "pre_commit";
-    sha256 = "0gqzx5n5kps7z45rgydciz0sq1m09b4g49vclhvybi57pn3hag0x";
+    sha256 = "0vmv3hrivm0sm81cn59n2pmw8h323sg4sgncl910djby2a3jc5cz";
   };
 
   propagatedBuildInputs = [
diff --git a/pkgs/development/python-modules/py2bit/default.nix b/pkgs/development/python-modules/py2bit/default.nix
new file mode 100644
index 00000000000..7699ccab3a2
--- /dev/null
+++ b/pkgs/development/python-modules/py2bit/default.nix
@@ -0,0 +1,27 @@
+{ lib
+, buildPythonPackage
+, fetchPypi
+, pytest
+}:
+
+buildPythonPackage rec {
+  pname = "py2bit";
+  version = "0.3.0";
+
+  checkInput = [ pytest ];
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "1vw2nvw1yrl7ikkqsqs1pg239yr5nspvd969r1x9arms1k25a1a5";
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/deeptools/py2bit";
+    description = "File access to 2bit files";
+    longDescription = ''
+        A python extension, written in C, for quick access to 2bit files. The extension uses lib2bit for file access.
+    '';
+    license = licenses.mit;
+    maintainers = with maintainers; [ scalavision ];
+  };
+}
diff --git a/pkgs/development/python-modules/pyatmo/default.nix b/pkgs/development/python-modules/pyatmo/default.nix
index bd1caba1d27..56467d1e4a5 100644
--- a/pkgs/development/python-modules/pyatmo/default.nix
+++ b/pkgs/development/python-modules/pyatmo/default.nix
@@ -1,6 +1,7 @@
 { lib
 , buildPythonPackage
 , fetchPypi
+, requests
 }:
 
 buildPythonPackage rec {
@@ -12,6 +13,8 @@ buildPythonPackage rec {
     sha256 = "2c76740e5adbf8b14d8f41d4f84ce23c0e8e738b18b926dc60858c35bf2fa8f2";
   };
 
+  propagatedBuildInputs = [ requests ];
+
   # Upstream provides no unit tests.
   doCheck = false;
 
diff --git a/pkgs/development/python-modules/pybigwig/default.nix b/pkgs/development/python-modules/pybigwig/default.nix
new file mode 100644
index 00000000000..be54a38cd99
--- /dev/null
+++ b/pkgs/development/python-modules/pybigwig/default.nix
@@ -0,0 +1,33 @@
+{ lib
+, buildPythonPackage
+, fetchPypi
+, pytest
+, numpy
+, zlib
+}:
+
+buildPythonPackage rec {
+  pname = "pyBigWig";
+  version = "0.3.17";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "157x6v48y299zm382krf1dw08fdxg95im8lnabhp5vc94s04zxj1";
+  };
+
+  buildInputs = [ zlib ];
+
+  checkInputs = [ numpy pytest ];
+
+  meta = with lib; {
+    homepage = "https://github.com/deeptools/pyBigWig";
+    description = "File access to bigBed files, and read and write access to bigWig files";
+    longDescription = ''
+      A python extension, written in C, for quick access to bigBed files
+      and access to and creation of bigWig files. This extension uses
+      libBigWig for local and remote file access.
+    '';
+    license = licenses.mit;
+    maintainers = with maintainers; [ scalavision ];
+  };
+}
diff --git a/pkgs/development/python-modules/pyglet/default.nix b/pkgs/development/python-modules/pyglet/default.nix
index e303f3415d7..1e7beddda7f 100644
--- a/pkgs/development/python-modules/pyglet/default.nix
+++ b/pkgs/development/python-modules/pyglet/default.nix
@@ -43,6 +43,8 @@ buildPythonPackage rec {
                 path = '${gtk2-x11}/lib/libgdk-x11-2.0${ext}'
             elif name == 'gdk_pixbuf-2.0':
                 path = '${gdk-pixbuf}/lib/libgdk_pixbuf-2.0${ext}'
+            elif name == 'Xext':
+                path = '${xorg.libXext}/lib/libXext${ext}'
             if path is not None:
                 return ctypes.cdll.LoadLibrary(path)
         raise Exception("Could not load library {}".format(names))
diff --git a/pkgs/development/python-modules/pykde4/default.nix b/pkgs/development/python-modules/pykde4/default.nix
index d2c66c8cd2c..5be43a412e5 100644
--- a/pkgs/development/python-modules/pykde4/default.nix
+++ b/pkgs/development/python-modules/pykde4/default.nix
@@ -19,7 +19,7 @@ in stdenv.mkDerivation rec {
   pname = "pykde4";
 
   src = fetchurl {
-    url = "mirror://kde/stable/${version}/src/${pname}-${version}-${version}.tar.xz";
+    url = "mirror://kde/stable/${version}/src/${pname}-${version}.tar.xz";
     sha256 = "1z40gnkyjlv6ds3cmpzvv99394rhmydr6rxx7qj33m83xnsxgfbz";
   };
 
diff --git a/pkgs/development/python-modules/solo-python/default.nix b/pkgs/development/python-modules/solo-python/default.nix
index 7b2b578eed8..829874f25ad 100644
--- a/pkgs/development/python-modules/solo-python/default.nix
+++ b/pkgs/development/python-modules/solo-python/default.nix
@@ -1,21 +1,22 @@
-{ lib, buildPythonPackage, fetchFromGitHub
+{ lib, buildPythonPackage, fetchFromGitHub, pythonOlder
 , click, ecdsa, fido2, intelhex, pyserial, pyusb, requests}:
 
  buildPythonPackage rec {
   pname = "solo-python";
-  version = "0.0.15";
+  version = "0.0.18";
   format = "flit";
+  disabled = pythonOlder "3.6"; # only python>=3.6 is supported
 
   src = fetchFromGitHub {
     owner = "solokeys";
     repo = pname;
     rev = version;
-    sha256 = "14na9s65hxzx141bdv0j7rx1wi3cv85jzpdivsq1rwp6hdhiazr1";
+    sha256 = "01mgppjvxlr93vrgz7bzisghpg1vqyaj4cg5wngk0h499iyx4d9q";
   };
 
-  # TODO: remove ASAP
+  # replaced pinned fido, with unrestricted fido version
   patchPhase = ''
-    substituteInPlace pyproject.toml --replace "fido2 == 0.7.0" "fido2 >= 0.7.0"
+    sed -i '/fido2/c\"fido2",' pyproject.toml
   '';
 
   propagatedBuildInputs = [
@@ -28,6 +29,20 @@
     requests
   ];
 
+  # allow for writable directory for darwin
+  preBuild = ''
+    export HOME=$TMPDIR
+  '';
+
+  # repo doesn't contain tests, ensure imports aren't broken
+  pythonImportsCheck = [
+    "solo"
+    "solo.cli"
+    "solo.commands"
+    "solo.fido2"
+    "solo.operations"
+  ];
+
   meta = with lib; {
     description = "Python tool and library for SoloKeys";
     homepage = "https://github.com/solokeys/solo-python";
diff --git a/pkgs/development/python-modules/spacy/default.nix b/pkgs/development/python-modules/spacy/default.nix
index 89e720482e7..23f2a6967da 100644
--- a/pkgs/development/python-modules/spacy/default.nix
+++ b/pkgs/development/python-modules/spacy/default.nix
@@ -26,19 +26,13 @@
 
 buildPythonPackage rec {
   pname = "spacy";
-  version = "2.2.1";
+  version = "2.2.2";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "1a833dx8i4s106fk42x4dnayaq5p3qxaxnc012xij991i09v2pxn";
+    sha256 = "193r7rrqxfj4jqzk4aqgbycficzmc606vkc4ffc46zs3myhlf6sa";
   };
 
-  prePatch = ''
-    substituteInPlace setup.cfg \
-      --replace "plac<1.0.0,>=0.9.6" "plac>=0.9.6" \
-      --replace "thinc>=7.1.1,<7.2.0" "thinc~=7.0"
-  '';
-
   propagatedBuildInputs = [
    numpy
    murmurhash
diff --git a/pkgs/development/python-modules/sqlalchemy-utils/default.nix b/pkgs/development/python-modules/sqlalchemy-utils/default.nix
index ef30b6917a3..3db00057c90 100644
--- a/pkgs/development/python-modules/sqlalchemy-utils/default.nix
+++ b/pkgs/development/python-modules/sqlalchemy-utils/default.nix
@@ -5,12 +5,12 @@
 
 buildPythonPackage rec {
   pname = "sqlalchemy-utils";
-  version = "0.34.2";
+  version = "0.35.0";
 
   src = fetchPypi {
     inherit version;
     pname = "SQLAlchemy-Utils";
-    sha256 = "126c9p8rnnb043w57ah7idqfryczbz4vi9lzsz2cgiaig6fv52b6";
+    sha256 = "0phsdcnm21qvxd00zmjd6yxbm1s0i7b1q8zrgfy8cqv9xpmz1w01";
   };
 
   propagatedBuildInputs = [
diff --git a/pkgs/development/python-modules/srsly/default.nix b/pkgs/development/python-modules/srsly/default.nix
index 17cd3e8c503..2b87c38b085 100644
--- a/pkgs/development/python-modules/srsly/default.nix
+++ b/pkgs/development/python-modules/srsly/default.nix
@@ -12,11 +12,11 @@
 
 buildPythonPackage rec {
   pname = "srsly";
-  version = "0.1.0";
+  version = "0.2.0";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "1l9yjp1w2vrkrynxrlrc0v47i2iq9059k4ni44nz23573xbdrh2w";
+    sha256 = "0gha1xfh64mapvgn0sghnjsvmjdrh5rywhs3j3bhkvwk42kf40ma";
   };
 
   propagatedBuildInputs = lib.optional (pythonOlder "3.4") pathlib;
diff --git a/pkgs/development/python-modules/thinc/default.nix b/pkgs/development/python-modules/thinc/default.nix
index a841001ca72..c8a6b5efe84 100644
--- a/pkgs/development/python-modules/thinc/default.nix
+++ b/pkgs/development/python-modules/thinc/default.nix
@@ -28,11 +28,11 @@
 
 buildPythonPackage rec {
   pname = "thinc";
-  version = "7.2.0";
+  version = "7.3.1";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "808caccafab95aa74c21695248b26279792cd7d07d94fd97f181020f318f024a";
+    sha256 = "1f9bg7iyhwnk8jfras8d4wzq0ypn5na0bdbwkl7y2mr06yrdd0ff";
   };
 
   buildInputs = lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [
@@ -65,11 +65,6 @@ buildPythonPackage rec {
     pytest
   ];
 
-  prePatch = ''
-    substituteInPlace setup.py \
-      --replace "plac>=0.9.6,<1.0.0" "plac>=0.9.6"
-  '';
-
   # Cannot find cython modules.
   doCheck = false;
 
diff --git a/pkgs/development/python-modules/wasabi/default.nix b/pkgs/development/python-modules/wasabi/default.nix
index 01a9a4034d5..6cbb2aa48db 100644
--- a/pkgs/development/python-modules/wasabi/default.nix
+++ b/pkgs/development/python-modules/wasabi/default.nix
@@ -6,11 +6,11 @@
 
 buildPythonPackage rec {
   pname = "wasabi";
-  version = "0.2.2";
+  version = "0.3.0";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "0xxjc9bvvcaz1qq1jyhcxyl2v39jz8d8dz4zhpfbc7dz53kq6b7r";
+    sha256 = "0f18x27qrr29rgxyiy1k9b469i37n80h0x9vd9i22pyg8wxx67q5";
   };
 
   checkInputs = [
diff --git a/pkgs/development/python-modules/xdis/default.nix b/pkgs/development/python-modules/xdis/default.nix
index cec21c44657..d120f17780b 100644
--- a/pkgs/development/python-modules/xdis/default.nix
+++ b/pkgs/development/python-modules/xdis/default.nix
@@ -6,14 +6,14 @@
 
 buildPythonPackage rec {
   pname = "xdis";
-  version = "4.0.4";
+  version = "4.1.2";
   disabled = isPy27;
 
   src = fetchFromGitHub {
     owner = "rocky";
     repo = "python-xdis";
     rev = version;
-    sha256 = "1m54d61ka9wgq0iqlzmsikzxa6qmwvnwsgm2kxb3vw5ic1psv4pv";
+    sha256 = "0icqhafsnmcs6628cg3jjgq0d3x835nqmhljcz93yi457hfqd2lp";
   };
 
   checkInputs = [ pytest ];
diff --git a/pkgs/development/ruby-modules/with-packages/default.nix b/pkgs/development/ruby-modules/with-packages/default.nix
index ac0a33f4561..7d49b0e0134 100644
--- a/pkgs/development/ruby-modules/with-packages/default.nix
+++ b/pkgs/development/ruby-modules/with-packages/default.nix
@@ -64,6 +64,8 @@ let
           rm -f $out/bin/$(basename "$i")
           makeWrapper "$i" $out/bin/$(basename "$i") --set GEM_PATH ${gemEnv}/${ruby.gemPath}
         done
+
+        ln -s ${ruby}/nix-support $out/nix-support
       '';
 
       passthru = {
diff --git a/pkgs/development/tools/clj-kondo/default.nix b/pkgs/development/tools/clj-kondo/default.nix
index 919061c6d96..9b2e80c7674 100644
--- a/pkgs/development/tools/clj-kondo/default.nix
+++ b/pkgs/development/tools/clj-kondo/default.nix
@@ -2,7 +2,7 @@
 
 stdenv.mkDerivation rec{
   pname = "clj-kondo";
-  version = "2019.07.31-alpha";
+  version = "2019.10.26";
 
   reflectionJson = fetchurl {
     name = "reflection.json";
@@ -12,7 +12,7 @@ stdenv.mkDerivation rec{
 
   src = fetchurl {
     url = "https://github.com/borkdude/${pname}/releases/download/v${version}/${pname}-${version}-standalone.jar";
-    sha256 = "03ipl7br9pgx2hdbiaxv9ip0ibafkyzkc8qlx8xyi528bcfi54bf";
+    sha256 = "1pq03g4bkslpa3jv7vrnw3sy6wnqdgnavl8qyb4lb1y96pmk9hd1";
   };
 
   dontUnpack = true;
@@ -46,6 +46,6 @@ stdenv.mkDerivation rec{
     homepage = https://github.com/borkdude/clj-kondo;
     license = licenses.epl10;
     platforms = graalvm8.meta.platforms;
-    maintainers = with maintainers; [ jlesquembre ];
+    maintainers = with maintainers; [ jlesquembre bandresen ];
   };
 }
diff --git a/pkgs/development/tools/ocaml/ocp-indent/default.nix b/pkgs/development/tools/ocaml/ocp-indent/default.nix
index 7ecc15da2b5..6f8d80df564 100644
--- a/pkgs/development/tools/ocaml/ocp-indent/default.nix
+++ b/pkgs/development/tools/ocaml/ocp-indent/default.nix
@@ -1,12 +1,12 @@
 { lib, fetchzip, buildDunePackage, cmdliner }:
 
 buildDunePackage rec {
-  version = "1.7.0";
+  version = "1.8.1";
   pname = "ocp-indent";
 
   src = fetchzip {
     url = "https://github.com/OCamlPro/ocp-indent/archive/${version}.tar.gz";
-    sha256 = "006x3fsd61vxnxj4chlakyk3b2s10pb0bdl46g0ghf3j8h33x7hc";
+    sha256 = "0h4ysh36q1fxc40inhsdq2swqpfm15lpilqqcafs5ska42pn7s68";
   };
 
   minimumOCamlVersion = "4.02";
diff --git a/pkgs/development/tools/rust/cargo-geiger/default.nix b/pkgs/development/tools/rust/cargo-geiger/default.nix
new file mode 100644
index 00000000000..2512a9ec4f4
--- /dev/null
+++ b/pkgs/development/tools/rust/cargo-geiger/default.nix
@@ -0,0 +1,39 @@
+{ stdenv, lib, fetchFromGitHub
+, rustPlatform, pkgconfig
+, openssl, Security }:
+
+rustPlatform.buildRustPackage rec {
+  pname = "cargo-geiger";
+  version = "0.7.3";
+
+  src = fetchFromGitHub {
+    owner = "anderejd";
+    repo = pname;
+    rev = "${pname}-${version}";
+    sha256 = "1lm8dx19svdpg99zbpfcm1272n18y63sq756hf6k99zi51av17xc";
+  };
+
+  cargoSha256 = "16zvm2y0j7ywv6fx0piq99g8q1sayf3qipd6adrwyqyg8rbf4cw6";
+
+  # Multiple tests require internet connectivity, so they are disabled here.
+  # If we ever get cargo-insta (https://crates.io/crates/insta) in tree,
+  # we might be able to run these with something like
+  # `cargo insta review` in the `preCheck` phase.
+  checkPhase = ''
+    cargo test -- \
+    --skip test_package::case_2 \
+    --skip test_package::case_3 \
+    --skip test_package::case_6
+  '';
+
+  buildInputs = [ openssl ] ++ lib.optionals stdenv.isDarwin [ Security ];
+  nativeBuildInputs = [ pkgconfig ];
+
+  meta = with lib; {
+    description = "Detects usage of unsafe Rust in a Rust crate and its dependencies.";
+    homepage = https://github.com/anderejd/cargo-geiger;
+    license = with licenses; [ asl20 /* or */ mit ];
+    maintainers = with maintainers; [ evanjs ];
+    platforms = platforms.all;
+  };
+}
diff --git a/pkgs/development/tools/vala-lint/default.nix b/pkgs/development/tools/vala-lint/default.nix
new file mode 100644
index 00000000000..92fb6ebcc68
--- /dev/null
+++ b/pkgs/development/tools/vala-lint/default.nix
@@ -0,0 +1,51 @@
+{ stdenv
+, fetchFromGitHub
+, glib
+, meson
+, ninja
+, pantheon
+, pkgconfig
+, vala
+, gettext
+, wrapGAppsHook
+}:
+
+stdenv.mkDerivation rec {
+  pname = "vala-lint-unstable";
+  version = "2019-10-11";
+
+  src = fetchFromGitHub {
+    owner = "vala-lang";
+    repo = "vala-lint";
+    rev = "a077bbec30dea128616a23583ce3f8364ff2ef11";
+    sha256 = "0w0rmaj4v42wc4vq2lfjnj6airag5ahv6522xkw3j1nmccxq3s72";
+  };
+
+  nativeBuildInputs = [
+    gettext
+    meson
+    ninja
+    pkgconfig
+    vala
+    wrapGAppsHook
+  ];
+
+  buildInputs = [
+    glib
+  ];
+
+  # See https://github.com/vala-lang/vala-lint/issues/133
+  doCheck = false;
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/vala-lang/vala-lint;
+    description = "Check Vala code files for code-style errors";
+    longDescription = ''
+      Small command line tool and library for checking Vala code files for code-style errors.
+      Based on the elementary Code-Style guidelines.
+    '';
+    license = licenses.gpl2Plus;
+    platforms = platforms.linux;
+    maintainers = pantheon.maintainers;
+  };
+}
diff --git a/pkgs/development/tools/yq/default.nix b/pkgs/development/tools/yq/default.nix
index f93a24d56f9..e9b54e67f5e 100644
--- a/pkgs/development/tools/yq/default.nix
+++ b/pkgs/development/tools/yq/default.nix
@@ -2,7 +2,7 @@
 
 buildPythonApplication rec {
   pname = "yq";
-  version = "2.7.2";
+  version = "2.8.1";
 
   propagatedBuildInputs = [ pyyaml xmltodict jq ];
 
@@ -11,7 +11,7 @@ buildPythonApplication rec {
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "1fwvwy75n4rqzh6sxyp2jmjqc7939s0xmrhxw7zhdy6iacggvnpp";
+    sha256 = "042p3s011635rbjax9wvwjdrb1kyzw38a6qn59b0j0k7krz6rlr4";
   };
 
   meta = with lib; {
diff --git a/pkgs/development/web/nodejs/nodejs.nix b/pkgs/development/web/nodejs/nodejs.nix
index 6dc68750075..ea23ad06cd2 100644
--- a/pkgs/development/web/nodejs/nodejs.nix
+++ b/pkgs/development/web/nodejs/nodejs.nix
@@ -53,12 +53,30 @@ in
     };
 
     buildInputs = optionals stdenv.isDarwin [ CoreServices ApplicationServices ]
-      ++ [ python2 zlib libuv openssl http-parser icu ];
+      ++ [ zlib libuv openssl http-parser icu ];
 
-    nativeBuildInputs = [ which utillinux pkgconfig ]
+    nativeBuildInputs = [ which utillinux pkgconfig python2 ]
       ++ optionals stdenv.isDarwin [ xcbuild ];
 
-    configureFlags = sharedConfigureFlags ++ [ "--without-dtrace" ] ++ extraConfigFlags;
+    configureFlags = let
+      isCross = stdenv.hostPlatform != stdenv.buildPlatform;
+      host = stdenv.hostPlatform.platform;
+      isArm = stdenv.hostPlatform.isArm;
+    in sharedConfigureFlags ++ [
+      "--without-dtrace"
+    ] ++ (optionals isCross [
+      "--cross-compiling"
+      "--without-intl"
+      "--without-snapshot"
+    ]) ++ (optionals (isCross && isArm && hasAttr "fpu" host.gcc) [
+      "--with-arm-fpu=${host.gcc.fpu}"
+    ]) ++ (optionals (isCross && isArm && hasAttr "float-abi" host.gcc) [
+      "--with-arm-float-abi=${host.gcc.float-abi}"
+    ]) ++ (optionals (isCross && isArm) [
+      "--dest-cpu=arm"
+    ]) ++ extraConfigFlags;
+
+    configurePlatforms = [];
 
     dontDisableStatic = true;
 
@@ -96,7 +114,7 @@ in
     postInstall = ''
       PATH=$out/bin:$PATH patchShebangs $out
 
-      ${optionalString enableNpm ''
+      ${optionalString (enableNpm && stdenv.hostPlatform == stdenv.buildPlatform) ''
         mkdir -p $out/share/bash-completion/completions/
         $out/bin/npm completion > $out/share/bash-completion/completions/npm
         for dir in "$out/lib/node_modules/npm/man/"*; do
diff --git a/pkgs/games/frozen-bubble/default.nix b/pkgs/games/frozen-bubble/default.nix
new file mode 100644
index 00000000000..3b562ee44f2
--- /dev/null
+++ b/pkgs/games/frozen-bubble/default.nix
@@ -0,0 +1,25 @@
+{ stdenv, fetchurl, perlPackages, pkgconfig, SDL, SDL_mixer, SDL_Pango, glib }:
+
+perlPackages.buildPerlModule {
+  pname = "frozen-bubble";
+  version = "2.212";
+
+  src = fetchurl {
+    url = "mirror://cpan/authors/id/K/KT/KTHAKORE/Games-FrozenBubble-2.212.tar.gz";
+    sha256 = "721e04ff69c5233060656bfbf4002aa1aeadd96c95351f0c57bb85b6da35a305";
+  };
+  patches = [ ./fix-compilation.patch ];
+
+  nativeBuildInputs = [ pkgconfig ];
+
+  buildInputs =  [ glib SDL SDL_mixer SDL_Pango perlPackages.SDL perlPackages.FileSlurp ];
+  propagatedBuildInputs = with perlPackages; [ AlienSDL CompressBzip2 FileShareDir FileWhich IPCSystemSimple LocaleMaketextLexicon ];
+
+  perlPreHook = "export LD=$CC";
+
+  meta = {
+    description = "Puzzle with Bubbles";
+    license = stdenv.lib.licenses.gpl2;
+    maintainers = with stdenv.lib.maintainers; [ puckipedia ];
+  };
+}
diff --git a/pkgs/games/frozen-bubble/fix-compilation.patch b/pkgs/games/frozen-bubble/fix-compilation.patch
new file mode 100644
index 00000000000..e87dd0668dc
--- /dev/null
+++ b/pkgs/games/frozen-bubble/fix-compilation.patch
@@ -0,0 +1,33 @@
+diff --git a/Build.PL b/Build.PL
+index b029d1e..8737395 100644
+--- a/Build.PL
++++ b/Build.PL
+@@ -16,13 +16,14 @@ use Games::FrozenBubble;
+ my $prefix = Alien::SDL->config('prefix');
+ my $cflags = '-I'
+   . File::Spec->catfile( $prefix, 'include' )
++  . ' ' . `pkg-config --cflags SDL_mixer`
+   ;
+ $cflags .= ' -fnested-functions' if $^O =~ /darwin/;
+ ###!!! this looks strange, you perhaps meant "$cflags .= ..."
+ ###!!! I intended Alien::SDL to add -I$prefix/include automatically, please tell me when it does not work (kmx)
+ my $devnull = File::Spec->devnull();
+ my @cflags =  ExtUtils::CBuilder->new->split_like_shell( $cflags );
+-my @linkers = ( ExtUtils::CBuilder->new->split_like_shell( Alien::SDL->config('libs', '-lSDL_mixer', '-lSDL_Pango') ) );
++my @linkers = ( ExtUtils::CBuilder->new->split_like_shell( Alien::SDL->config('libs', '-lSDL_Pango',`pkg-config --libs SDL_mixer`) ) );
+ push @linkers, '-liconv'
+   if $^O =~ /win/i;    ###!!! really only Win needs this? ; BEWARE this matches also 'darwin', 'cygwin'!!!!
+ 
+diff --git a/inc/My/Builder.pm b/inc/My/Builder.pm
+index 2ebaf91..c420b9a 100644
+--- a/inc/My/Builder.pm
++++ b/inc/My/Builder.pm
+@@ -123,7 +123,7 @@ sub ACTION_server {
+             push @ofiles, $cbuilder->compile(
+                 source               => catfile($server_directory, $cfile),
+                 extra_compiler_flags => [
+-                    qw(-g -Wall -Werror -pipe), # verbatim from Makefile
++                    qw(-g -pipe), # verbatim from Makefile
+                     '-I' . $server_directory, # does not seem to be necessary
+                     $cbuilder->split_like_shell(`pkg-config glib-2.0 --cflags`),
+                     $cbuilder->split_like_shell(`pkg-config glib-2.0 --libs`),
diff --git a/pkgs/games/openjk/default.nix b/pkgs/games/openjk/default.nix
index 9109d2667c3..fd12c901583 100644
--- a/pkgs/games/openjk/default.nix
+++ b/pkgs/games/openjk/default.nix
@@ -21,13 +21,13 @@ let
   };
 in stdenv.mkDerivation {
   pname = "OpenJK";
-  version = "2019-06-24";
+  version = "2019-10-25";
 
   src = fetchFromGitHub {
     owner = "JACoders";
     repo = "OpenJK";
-    rev = "e8b5c135eccb05ddae67e00ff944001f373fddd4";
-    sha256 = "0qkbn59swhnb0anvy9gq945rkb58j6axlcfgb7sff0m4swqw2394";
+    rev = "e9116155052ef6a22135a1806a10e959aa9a1e00";
+    sha256 = "1f1bz1g2ksw4m3rnbh6fdsawcrpbfjdmq1gs2xj0q450yb840l3z";
   };
 
   dontAddPrefix = true;
diff --git a/pkgs/games/openmw/tes3mp.nix b/pkgs/games/openmw/tes3mp.nix
index 2bc34a6ec9d..4bbddfbb1df 100644
--- a/pkgs/games/openmw/tes3mp.nix
+++ b/pkgs/games/openmw/tes3mp.nix
@@ -24,20 +24,20 @@ let
   coreScripts = fetchFromGitHub {
     owner = "TES3MP";
     repo = "CoreScripts";
-    # usually latest master
-    rev = "71e15fa3b1d5131b6607ba1589f41c06672ce376";
-    sha256 = "1kwii8rpsxjmz4dh06wb0qaix17hq5s1qsvysv6n6209vlclfxjg";
+    # usually latest in stable branch (e.g. 0.7.0)
+    rev = "506146f5b2297242b713a030a589966156df1e8e";
+    sha256 = "0p4a4bgigyxfmaczf3jnz6ik4hgvdaafzc4614hbmbm1qbn8wpf9";
   };
 in openmw.overrideAttrs (oldAttrs: rec {
-  version = "2019-06-09";
+  version = "2019-07-01";
   name = "openmw-tes3mp-${version}";
 
   src = fetchFromGitHub {
     owner = "TES3MP";
     repo = "openmw-tes3mp";
     # usually latest in stable branch (e.g. 0.7.0)
-    rev = "01804af100785bc2c162d568258d9662012627a3";
-    sha256 = "0j99v9vvmic0bqw3y4550k1dy058lwvs9s9qcjmxh1wkqkvrpdnp";
+    rev = "94a9292cc676a037496f98877b62da80cde2ac47";
+    sha256 = "0kc45xs33rsxac1aba248slzvljx90ybdk4ag9jwjjmsjmy7w2w5";
   };
 
   nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ makeWrapper ];
diff --git a/pkgs/games/openxray/default.nix b/pkgs/games/openxray/default.nix
index d8ff0dd8d9e..9960d94a247 100644
--- a/pkgs/games/openxray/default.nix
+++ b/pkgs/games/openxray/default.nix
@@ -4,13 +4,13 @@
 
 stdenv.mkDerivation rec {
   pname = "OpenXRay";
-  version = "510";
+  version = "558";
 
   src = fetchFromGitHub {
     owner = "OpenXRay";
     repo = "xray-16";
     rev = version;
-    sha256 = "0q142l6xvgnd6ycncqld69izxclynqrs73aq89pfy1r1nzhd60ay";
+    sha256 = "1wnkx9g0ww4f5pljrb0wzs054jzkig1i5hlz1p509rfvnhc50afp";
     fetchSubmodules = true;
   };
 
diff --git a/pkgs/games/quakespasm/vulkan.nix b/pkgs/games/quakespasm/vulkan.nix
index 114f862888d..e8678253b40 100644
--- a/pkgs/games/quakespasm/vulkan.nix
+++ b/pkgs/games/quakespasm/vulkan.nix
@@ -2,14 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "vkquake";
-  majorVersion = "1.01";
-  version = "${majorVersion}.0";
+  version = "1.02.1";
 
   src = fetchFromGitHub {
     owner = "Novum";
     repo = "vkQuake";
     rev = version;
-    sha256 = "1iwin8j5kbyrknbkhjgpy8nmm7pxqzr0daa9gn7p38qhg2mh0a39";
+    sha256 = "0fk9jqql0crnf0s12cxnris392ajciyw1zbz17qgs5hdyivp9vdx";
   };
 
   sourceRoot = "source/Quake";
diff --git a/pkgs/games/sdlmame/default.nix b/pkgs/games/sdlmame/default.nix
deleted file mode 100644
index 7811b4b7373..00000000000
--- a/pkgs/games/sdlmame/default.nix
+++ /dev/null
@@ -1,42 +0,0 @@
-{ stdenv, fetchurl, alsaLib, qt48, SDL, fontconfig, freetype, SDL_ttf, xorg }:
-
-stdenv.mkDerivation rec {
-  version = "0.151.u0-1";
-  pname = "sdlmame";
-
-  src = if stdenv.hostPlatform.system == "x86_64-linux"
-    then fetchurl {
-      url    = "http://seblu.net/a/archive/packages/s/sdlmame/${pname}-${version}-x86_64.pkg.tar.xz";
-      sha256 = "1j9vjxhrhsskrlk5wr7al4wk2hh3983kcva42mqal09bmc8qg3m9";
-    }
-    else fetchurl {
-      url    = "http://seblu.net/a/archive/packages/s/sdlmame/${pname}-${version}-i686.pkg.tar.xz";
-      sha256 = "1i38j9ml66pyxzm0zzf1fv4lb40f6w47cdgaw846q91pzakkkqn7";
-    };
-
-  buildPhase = ''
-    sed -i "s|/usr|$out|" bin/sdlmame
-  '';
-
-  installPhase = ''
-    patchelf \
-      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
-      --set-rpath "${stdenv.lib.makeLibraryPath [ alsaLib qt48 SDL fontconfig freetype SDL_ttf xorg.libX11 xorg.libXinerama stdenv.cc.cc ]}" \
-      share/sdlmame/sdlmame
-
-    mkdir -p "$out/bin"
-    cp -r bin/sdlmame "$out/bin"
-    cp -r share "$out"
-  '';
-
-  dontPatchELF = true;
-  dontStrip    = true;
-
-  meta = with stdenv.lib; {
-    homepage    = http://sdlmame.lngn.net;
-    description = "A port of the popular Multiple Arcade Machine Emulator using SDL with OpenGL support";
-    license     = "MAME";
-    maintainers = with maintainers; [ lovek323 ];
-    platforms   = [ "x86_64-linux" "i686-linux" ];
-  };
-}
diff --git a/pkgs/misc/emulators/mame/default.nix b/pkgs/misc/emulators/mame/default.nix
new file mode 100644
index 00000000000..499d7dd6c4a
--- /dev/null
+++ b/pkgs/misc/emulators/mame/default.nix
@@ -0,0 +1,59 @@
+{ stdenv, mkDerivation, fetchFromGitHub, makeDesktopItem
+, python, pkgconfig, SDL2, SDL2_ttf, alsaLib, which, qtbase, libXinerama }:
+
+let
+  majorVersion = "0";
+  minorVersion = "215";
+
+  desktopItem = makeDesktopItem {
+    name = "MAME";
+    exec = "mame${stdenv.lib.optionalString stdenv.is64bit "64"}";
+    desktopName = "MAME";
+    genericName = "MAME is a multi-purpose emulation framework";
+    categories = "System;Emulator;";
+  };
+in mkDerivation {
+  pname = "mame";
+  version = "${majorVersion}.${minorVersion}";
+
+  src = fetchFromGitHub {
+    owner = "mamedev";
+    repo = "mame";
+    rev = "mame${majorVersion}${minorVersion}";
+    sha256 = "1phz846p3zzgzrbfiq2vn79iqar2dbf7iv6wfkrp32sdkkvp7l3h";
+  };
+
+  hardeningDisable = [ "fortify" ];
+  NIX_CFLAGS_COMPILE = [ "-Wno-error=maybe-uninitialized" ];
+
+  makeFlags = [ "TOOLS=1" ];
+
+  buildInputs = [ SDL2 SDL2_ttf alsaLib qtbase libXinerama ];
+  nativeBuildInputs = [ python pkgconfig which ];
+
+  installPhase = ''
+    dest=$out/opt/mame
+
+    make -f dist.mak PTR64=${if stdenv.is64bit then "1" else "0"}
+    mkdir -p $dest
+    mv build/release/${if stdenv.is64bit then "x64" else "x32"}/Release/mame/* $dest
+
+    mkdir -p $out/bin
+    find $dest -maxdepth 1 -executable -type f -exec mv -t $out/bin {} \;
+
+    mkdir -p $out/share/man/man{1,6}
+    mv $dest/docs/man/*.1 $out/share/man/man1
+    mv $dest/docs/man/*.6 $out/share/man/man6
+
+    mkdir -p $out/share
+    ln -s ${desktopItem}/share/applications $out/share
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Is a multi-purpose emulation framework";
+    homepage = https://www.mamedev.org/;
+    license = with licenses; [ bsd3 gpl2Plus ];
+    platforms = [ "x86_64-linux" "i686-linux" ];
+    maintainers = with maintainers; [ gnidorah ];
+  };
+}
diff --git a/pkgs/misc/emulators/mess/default.nix b/pkgs/misc/emulators/mess/default.nix
deleted file mode 100644
index fc63bf705f4..00000000000
--- a/pkgs/misc/emulators/mess/default.nix
+++ /dev/null
@@ -1,49 +0,0 @@
-{ stdenv, fetchurl, unzip, pkgconfig, SDL, gtk2, GConf, libGLU_combined
-, expat, zlib }:
-
-let
-
-  version = "139";
-
-  mameSrc = fetchurl {
-    url = "https://github.com/mamedev/mame/releases/download/mame0139/mame0${version}s.zip";
-    sha256 = "1mpkwxfz38cgxzvlni2y3fxas3b8qmnzj2ik2zzbd8mr622jdp79";
-  };
-
-  messSrc = fetchurl {
-    url = "http://www.progettosnaps.net/MESS/src/mess0${version}s.zip";
-    name = "mess0139s.zip";
-    sha256 = "1v892cg6wn8cdwc8pf1gcqqdb1v1v295r6jw2hf58svwx3h27xyy";
-  };
-
-in
-
-stdenv.mkDerivation {
-  name = "mess-0.${version}";
-
-  unpackPhase =
-    ''
-      unzip ${mameSrc}
-      # Yes, the MAME distribution is a zip file containing a zip file...
-      unzip mame.zip
-      unzip -o ${messSrc}
-    '';
-
-  makeFlags = "TARGET=mess BUILD_EXPAT= BUILD_ZLIB= NOWERROR=1";
-
-  buildInputs =
-    [ unzip pkgconfig SDL gtk2 GConf libGLU_combined expat zlib ];
-
-  installPhase =
-    ''
-      mkdir -p $out/bin
-      cp mess* $out/bin/mess
-    '';
-
-  meta = {
-    homepage = https://www.mess.org/;
-    license = "non-commercial";
-    description = "Multi Emulator Super System, an emulator of many game consoles and computer systems";
-    broken = true;
-  };
-}
diff --git a/pkgs/misc/emulators/retroarch/cores.nix b/pkgs/misc/emulators/retroarch/cores.nix
index e55cefdd320..ced26333f4c 100644
--- a/pkgs/misc/emulators/retroarch/cores.nix
+++ b/pkgs/misc/emulators/retroarch/cores.nix
@@ -1,7 +1,7 @@
-{ stdenv, fetchgit, fetchFromGitLab, cmake, pkgconfig, makeWrapper, python27, retroarch
+{ stdenv, fetchgit, fetchFromGitHub, fetchFromGitLab, cmake, pkgconfig, makeWrapper, python27, python37, retroarch
 , alsaLib, fluidsynth, curl, hidapi, libGLU_combined, gettext, glib, gtk2, portaudio, SDL
 , ffmpeg, pcre, libevdev, libpng, libjpeg, udev, libvorbis
-, miniupnpc, sfml, xorg, zlib }:
+, miniupnpc, sfml, xorg, zlib, nasm, libpcap, boost }:
 
 let
 
@@ -11,7 +11,7 @@ let
   stdenv.lib.makeOverridable stdenv.mkDerivation rec {
 
     name = "libretro-${core}-${version}";
-    version = "2017-06-04";
+    version = "2019-09-29";
     inherit src;
 
     buildInputs = [ makeWrapper retroarch zlib ] ++ a.extraBuildInputs or [];
@@ -38,7 +38,6 @@ let
       inherit description;
       homepage = https://www.libretro.com/;
       inherit license;
-      inherit broken;
       maintainers = with maintainers; [ edwtjo hrdinka MP2E ];
       platforms = platforms.unix;
     };
@@ -59,12 +58,83 @@ in with stdenv.lib.licenses;
     core = "4do";
     src = fetchRetro {
       repo = core + "-libretro";
-      rev = "52d881743dd8614d96b4de8bd153cb725b87d474";
-      sha256 = "1n42f70vni2zavppayaq8xmsyx5cn40qi4zk4pgq1w3hh2q8mj72";
+      rev = "b6ad4bc8548f2f3792cd929ccf26d9078b73a1c0";
+      sha256 = "0j2bd9cnnd5k99l9qr4wd5q9b4ciplia6ywp90xg6422s1im2iw0";
     };
     description = "Port of 4DO/libfreedo to libretro";
     license = "Non-commercial";
   }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  atari800 = (mkLibRetroCore rec {
+    core = "atari800";
+    src = fetchRetro {
+      repo = "libretro-" + core;
+      rev = "efc0bc71e3cb8a4f957d07fe808cc002ed9c13b9";
+      sha256 = "150hmazi4p5p18gpjmkrn1k9j719cd9gy7jn0jiy3jbk2cxxsjn6";
+    };
+    description = "Port of Atari800 to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-snes = (mkLibRetroCore rec {
+    core = "mednafen-snes";
+    src = fetchRetro {
+      repo = "beetle-bsnes-libretro";
+      rev = "6aee84d454570bb17dff5975df28febdbcb72938";
+      sha256 = "0nk9xlypg3jhpbwd9z5bjbgzlkz842hy9rq14k1nwn0qz6d88kld";
+    };
+    description = "Port of Mednafen's SNES core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-gba = (mkLibRetroCore rec {
+    core = "mednafen-gba";
+    src = fetchRetro {
+      repo = "beetle-gba-libretro";
+      rev = "135afdbb9591655a3e016b75abba07e481f6d406";
+      sha256 = "0fc0x24qn4y7pz3mp1mm1ain31aj9pznp1irr0k7hvazyklzy9g3";
+    };
+    description = "Port of Mednafen's GameBoy Advance core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-lynx = (mkLibRetroCore rec {
+    core = "mednafen-lynx";
+    src = fetchRetro {
+      repo = "beetle-lynx-libretro";
+      rev = "928f7cf5b39f0363e55667572ff455e37489998e";
+      sha256 = "0f03wzdr6f0fpy889i9a2834jg5lvcriyl98pajp75m7whm9r9cc";
+    };
+    description = "Port of Mednafen's Lynx core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-ngp = (mkLibRetroCore rec {
+    core = "mednafen-ngp";
+    src = fetchRetro {
+      repo = "beetle-ngp-libretro";
+      rev = "6130e4057c3d8f9172f0c49bb9b6c61bd1a572d5";
+      sha256 = "10k7spjrhggjgzb370bwv7fgk0nb6xri9ym6cm4qvnrkcwxm7i9p";
+    };
+    description = "Port of Mednafen's NeoGeo Pocket core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
     buildPhase = "make";
   };
 
@@ -72,26 +142,42 @@ in with stdenv.lib.licenses;
     core = "mednafen-pce-fast";
     src = fetchRetro {
       repo = "beetle-pce-fast-libretro";
-      rev = "2954e645d668ee73d93803dc30da4462fc7a459b";
-      sha256 = "0p0k7kqfd6xg1qh6vgzgwp122miprb2bpzljgxd9kvigxihsl6f7";
+      rev = "7bbbdf111c1ce52ab4a97e911ebdaa6836ee881a";
+      sha256 = "1p0kk5a2yi05yl0hspzv9q0n96yx9riaaacbmnq76li0i3ihkf6l";
     };
     description = "Port of Mednafen's PC Engine core to libretro";
     license = gpl2;
   }); in der.override {
+    makefile = "Makefile";
     buildPhase = "make";
     name = "beetle-pce-fast-${der.version}";
   };
+  
+  beetle-pcfx = (mkLibRetroCore rec {
+    core = "mednafen-pcfx";
+    src = fetchRetro {
+      repo = "beetle-pcfx-libretro";
+      rev = "e04f695202a7295e4b6f2122ae947279ac9df007";
+      sha256 = "0pdlz05pjqxp19da13dr3wd20hgxw8z5swhflyf7ksjgvz5rxb4r";
+    };
+    description = "Port of Mednafen's PCFX core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
 
   beetle-psx = let der = (mkLibRetroCore {
     core = "mednafen-psx";
     src = fetchRetro {
       repo = "beetle-psx-libretro";
-      rev = "76862abefdde9097561e2b795e75b49247deff17";
-      sha256 = "1k4b7g50ajzchjrm6d3v68hvri4k3hzvacn2l99i5yq3hxp7vs7x";
+      rev = "f55db8655408104a6e20af667657423f08566c85";
+      sha256 = "17iz8r2wy8zqh63j78ijwxasdnmg8dh9mmqn1qr4hvf4fj53ckk8";
     };
     description = "Port of Mednafen's PSX Engine core to libretro";
     license = gpl2;
   }); in der.override {
+    makefile = "Makefile";
     buildPhase = "make";
     name = "beetle-psx-${der.version}";
   };
@@ -100,27 +186,84 @@ in with stdenv.lib.licenses;
     core = "mednafen-saturn";
     src = fetchRetro {
       repo = "beetle-saturn-libretro";
-      rev = "3f1661b39ef249e105e6e2e655854ad0c87cd497";
-      sha256 = "1d1brysynwr6inlwfgv7gwkl3i9mf4lsaxd9wm2szw86g4diyn4c";
+      rev = "3313cc6760c14cffa9226e0cfd41debc11df8bdd";
+      sha256 = "1z2zfn5cpsr3x6bvr562vqvmp4pjjhv5a6jcp09gfsy2gkyispr2";
     };
     description = "Port of Mednafen's Saturn core to libretro";
     license = gpl2;
   }); in der.override {
+    makefile = "Makefile";
     buildPhase = "make";
     name = "beetle-saturn-${der.version}";
-    meta.platforms = [ "x86_64-linux" ];
+    meta.platforms = [ "x86_64-linux" "aarch64-linux" ];
+  };
+  
+  beetle-supergrafx = (mkLibRetroCore rec {
+    core = "mednafen-supergrafx";
+    src = fetchRetro {
+      repo = "beetle-supergrafx-libretro";
+      rev = "857e41146e3b0a51def3baea49d2eec80f18102b";
+      sha256 = "0r3v4qy4rx4mnr7w4s779f6f2bjyp69m42blimacl1l9f6hmcv5h";
+    };
+    description = "Port of Mednafen's SuperGrafx core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-wswan = (mkLibRetroCore rec {
+    core = "mednafen-wswan";
+    src = fetchRetro {
+      repo = "beetle-wswan-libretro";
+      rev = "925cb8c77af1678ceab24f04c2790cb95389def1";
+      sha256 = "0kqsqn655z6nnr2s1xdbf37ds99gyhqfd7dx0wmx3sy1fshjg5wm";
+    };
+    description = "Port of Mednafen's WonderSwan core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  beetle-vb = (mkLibRetroCore rec {
+    core = "mednafen-vb";
+    src = fetchRetro {
+      repo = "beetle-vb-libretro";
+      rev = "9066cdafa29ac054243a679baded49212661f47b";
+      sha256 = "0gsniz5kk4xdiprcfyqjcss2vkrphi48wbr29gqvpf7l8gpnwx8p";
+    };
+    description = "Port of Mednafen's VirtualBoy core to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  bluemsx = (mkLibRetroCore rec {
+    core = "bluemsx";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "ddd89ff1fa534816e48521bd930b721f2d39975a";
+      sha256 = "0hiqhc1ckj3ydy0q1v8hwjkkyh2564f7wlqypmshjcc47n296xyf";
+    };
+    description = "Port of BlueMSX to libretro";
+    license = gpl2;
+  }).override {
+    buildPhase = "make";
   };
 
   bsnes-mercury = let bname = "bsnes-mercury"; in (mkLibRetroCore {
     core = bname + "-accuracy";
     src = fetchRetro {
       repo = bname;
-      rev = "e89c9a2e0a12d588366ee4f5c76b7d75139d938b";
-      sha256 = "0vkn1f38vwazpp3kbvvv8c467ghak6yfx00s48wkxwvhmak74a3s";
+      rev = "4a382621da58ae6da850f1bb003ace8b5f67968c";
+      sha256 = "0z8psz24nx8497vpk2wya9vs451rzzw915lkw3qiq9bzlzg9r2wv";
     };
     description = "Fork of bsnes with HLE DSP emulation restored";
     license = gpl3;
   }).override {
+    makefile = "Makefile";
     buildPhase = "make && cd out";
   };
 
@@ -128,55 +271,88 @@ in with stdenv.lib.licenses;
     core = "desmume";
     src = fetchRetro {
       repo = core;
-      rev = "ce1f93abb4c3aa55099f56298e5438a03a3c2bbd";
-      sha256 = "064gzfbr7yizmvi91ry5y6bzikj633kdqhvzycb9f1g6kspf8yyl";
+      rev = "e8cf461f83eebb195f09e70090f57b07d1bcdd9f";
+      sha256 = "0rc8s5226wn39jqs5yxi30jc1snc0p106sfym7kgi98hy5na8yab";
     };
     description = "libretro wrapper for desmume NDS emulator";
     license = gpl2;
+    extraBuildInputs = [ libpcap libGLU_combined xorg.libX11 ];
   }).override {
+    makefile = "desmume/src/frontend/libretro/Makefile.libretro";
+    configurePhase = "cd desmume/src/frontend/libretro";
+    buildPhase = "make";
+  };
+
+  desmume2015 = (mkLibRetroCore rec {
+    core = "desmume2015";
+    src = fetchRetro {
+      repo = core;
+      rev = "c27bb71aa28250f6da1576e069b4b8cc61986beb";
+      sha256 = "1m7g1wwpnnprmki3rixknggjmxbp7d4hwxgkqr041shmrm0rhafd";
+    };
+    description = "libretro wrapper for desmume NDS emulator from 2015";
+    license = gpl2;
+    extraBuildInputs = [ libpcap libGLU_combined xorg.libX11 ];
+  }).override {
+    makefile = "desmume/Makefile.libretro";
     configurePhase = "cd desmume";
+    buildPhase = "make";
   };
 
   dolphin = (mkLibRetroCore {
     core = "dolphin";
     src = fetchRetro {
       repo = "dolphin";
-      rev = "a6ad451fdd4ac8753fd1a8e2234ec34674677754";
-      sha256 = "1cshlfmhph8dl3vgvn37imvp2b7xs2cx1r1ifp5js5psvhycrbz3";
+      rev = "11a7ed402c7178da1d9d57c6e5e5a05a4dc6a2c8";
+      sha256 = "11jrcczkbyns01rvxb5rd22fbkbfn2h81f6pfxbhi13fl4ljim9x";
     };
     description = "Port of Dolphin to libretro";
     license = gpl2Plus;
     broken = true;
 
     extraBuildInputs = [
-      cmake curl libGLU_combined pcre pkgconfig sfml miniupnpc
-      gettext glib gtk2 hidapi
+      cmake curl libGLU_combined pcre pkgconfig sfml
+      gettext hidapi
       libevdev udev
-    ] ++ (with xorg; [ libSM libX11 libXi libpthreadstubs libxcb xcbutil libXinerama libXxf86vm ]);
+    ] ++ (with xorg; [ libSM libX11 libXi libpthreadstubs libxcb xcbutil libXext libXrandr libXinerama libXxf86vm ]);
   }).override {
     cmakeFlags = [
-        "-DLINUX_LOCAL_DEV=true"
-        "-DGTK2_GDKCONFIG_INCLUDE_DIR=${gtk2.out}/lib/gtk-2.0/include"
-        "-DGTK2_GLIBCONFIG_INCLUDE_DIR=${glib.out}/lib/glib-2.0/include"
-        "-DGTK2_INCLUDE_DIRS=${gtk2.dev}/include/gtk-2.0"
+      "-DCMAKE_BUILD_TYPE=Release"
+      "-DLIBRETRO=ON"
+      "-DLIBRETRO_STATIC=1"
+      "-DENABLE_QT=OFF"
+      "-DENABLE_LTO=OFF"
+      "-DUSE_UPNP=OFF"
+      "-DUSE_DISCORD_PRESENCE=OFF" 
     ];
     dontUseCmakeBuildDir = "yes";
-    buildPhase = ''
-      cd Source/Core/DolphinLibretro
-      make
-    '';
+    buildPhase = "make";
+  };
+
+  dosbox = (mkLibRetroCore rec {
+    core = "dosbox";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "e4ed503b14ed59d5d745396ef1cc7d52cf912328";
+      sha256 = "13bx0ln9hwn6hy4sv0ivqmjgjbfq8svx15dsa24hwd8lkf0kakl4";
+    };
+    description = "Port of DOSBox to libretro";
+    license = gpl2;
+  }).override {
+    buildPhase = "make";
   };
 
   fba = (mkLibRetroCore rec {
     core = "fba";
     src = fetchRetro {
       repo = core + "-libretro";
-      rev = "9146c18ac989c619256d1cb8954d49e728e44ea3";
-      sha256 = "159dww8mxi95xz4ypw38vsn1g4k6z8sv415qqf0qriydwhw6mh2m";
+      rev = "89245384c7d181e286d6f34995253419f946becb";
+      sha256 = "1pg351qhbq5x8qmaq6c30v8ynic8jv3gbxy2kq5iknka80g1lkck";
     };
     description = "Port of Final Burn Alpha to libretro";
     license = "Non-commercial";
   }).override {
+    makefile = "svn-current/trunk/makefile.libretro";
     buildPhase = ''
       cd svn-current/trunk \
       && make -f makefile.libretro \
@@ -188,19 +364,34 @@ in with stdenv.lib.licenses;
     core = "fceumm";
     src = fetchRetro {
       repo = "libretro-" + core;
-      rev = "45f773a1c221121746bbe2680e3aaaf92776a87e";
-      sha256 = "0jnwh1338q710x47bzrx319g5xbq9ipv35kyjlbkrzhqjq1blz0b";
+      rev = "0e315e0ca0093ebda06a97835cec6ad4af81db7a";
+      sha256 = "12bvvxmvafjvrvwxl5gzr583g48s0isx2fgvjgkrx175vk2amaf4";
     };
     description = "FCEUmm libretro port";
     license = gpl2;
   };
 
+  flycast = (mkLibRetroCore rec {
+    core = "flycast";
+    src = fetchRetro {
+      repo = core;
+      rev = "45a15205dfc05cfc4df2488cad7c2b4988c5aa0f";
+      sha256 = "18glxd57kddq6p2bwq0qknyq6bv8dxklqks4w2jy2yccvwxdxy2i";
+    };
+    description = "Flycast libretro port";
+    license = gpl2;
+    extraBuildInputs = [ libGLU_combined ];
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
   gambatte = mkLibRetroCore rec {
     core = "gambatte";
     src = fetchRetro {
       repo = core + "-libretro";
-      rev = "db7af6cf6ea39fd5e39eea137ff752649599a4e4";
-      sha256 = "0h7hyj630nk1s32wx02y4q9x2lp6wbnh6nkc9ihf4pygcsignmwr";
+      rev = "4d9ad7b29946ec0a914b2d6a735b6c2704ed1f23";
+      sha256 = "156pvvlch5izbgbw4ddxhiwgzpp52irr3nqaz813i5f02fiq5wya";
     };
     description = "Gambatte libretro port";
     license = gpl2;
@@ -210,13 +401,56 @@ in with stdenv.lib.licenses;
     core = "genesis-plus-gx";
     src = fetchRetro {
       repo = "Genesis-Plus-GX";
-      rev = "365a28c7349b691e6aaa3ad59b055261c42bd130";
-      sha256 = "0s11ddpnb44q4xjkl7dylldhi9y5zqywqavpk0bbwyj84r1cbz3c";
+      rev = "0e4357bd64533d7fd93b5f01620b92595025fab5";
+      sha256 = "1nryy00844h3ra97j40g38lj7036ibm2l8002qid7r5r9kggclqx";
     };
     description = "Enhanced Genesis Plus libretro port";
     license = "Non-commercial";
   };
 
+  gpsp = (mkLibRetroCore rec {
+    core = "gpsp";
+    src = fetchRetro {
+      repo = core;
+      rev = "24af89596e6484ff5a7a08efecfa8288cfbc02f3";
+      sha256 = "1jc5i70cab5f23yc9sfv8iyvmwmc4sb33f413il2vlhsfdxklyk7";
+    };
+    description = "Port of gpSP to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  handy = (mkLibRetroCore rec {
+    core = "handy";
+    src = fetchRetro {
+      repo = "libretro-" + core;
+      rev = "6b19a4fad1b394f6a1351c88f60991d4878ff05b";
+      sha256 = "0lhkrwh3rirdidxb8kfcg8wk9gjsc7g6qpkv74h6f09rb4y75w1y";
+    };
+    description = "Port of Handy to libretro";
+    license = "Handy-License";
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  hatari = (mkLibRetroCore rec {
+    core = "hatari";
+    src = fetchRetro {
+      repo = core;
+      rev = "ec1b59c4b6c7ca7d0d23d60cfe2cb61911b11173";
+      sha256 = "1pm821s2cz93xr7qx7dv0imr44bi4pvdvlnjl486p83vff9yawfg";
+    };
+    description = "Port of Hatari to libretro";
+    license = gpl2;
+    extraBuildInputs = [ cmake SDL ];
+  }).override {
+    makefile = "Makefile.libretro";
+    buildPhase = "make";
+  };
+
   higan-sfc = (mkLibRetroCore {
     core = "higan-sfc";
     src = fetchFromGitLab {
@@ -227,6 +461,8 @@ in with stdenv.lib.licenses;
     };
     description = "Accurate SNES / Super Famicom emulator";
     license = gpl3;
+    broken = true;
+
   }).override {
     makefile = "GNUmakefile";
     buildPhase = "cd higan && make compiler=g++ target=libretro binary=library && cd out";
@@ -236,8 +472,8 @@ in with stdenv.lib.licenses;
     core = "mame";
     src = fetchRetro {
       repo = "mame";
-      rev = "9f9e6b6c9bde4d50c72e9a5c80496a1fec6b8aa9";
-      sha256 = "0lfj8bjchkcvyb5x0x29cg10fkfklxndk80947k4qfysclijxpkv";
+      rev = "f4aac49f3d56fbd653628ac456c23ac9a6b857ae";
+      sha256 = "1pjpnwdj73319hgcjhganzrcz2zn4fnjydah989haqh3id5j3zam";
     };
     description = "Port of MAME to libretro";
     license = gpl2Plus;
@@ -249,68 +485,205 @@ in with stdenv.lib.licenses;
       # make -C 3rdparty/genie/build/gmake.linux -f genie.make obj/Release/src/host/lua-5.3.0/src/lgc.o
       mkdir -p 3rdparty/genie/build/gmake.linux/obj/Release/src/host/lua-5.3.0/src
     '';
+    buildPhase = "make -f Makefile.libretro";
+  };
+
+  mame2000 = (mkLibRetroCore rec {
+    core = "mame2000";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "0a8a174f5e755cdd476895207003c5d07cfa6af2";
+      sha256 = "03k0cfgd4wfl31dv5xb6xjd4h7sh0k0qw6wbspwi0lgswmhz97bb";
+    };
+    description = "Port of MAME ~2000 to libretro";
+    license = gpl2Plus;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  mame2003 = (mkLibRetroCore rec {
+    core = "mame2003";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "170d5b6490953d40edc39defe69945d005f8ec03";
+      sha256 = "0slsf59sn5lijr1mrx5ffc9z81ra1wcw7810mb52djqyvm15r9zl";
+    };
+    description = "Port of MAME ~2003 to libretro";
+    license = gpl2Plus;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  mame2003-plus = (mkLibRetroCore rec {
+    core = "mame2003-plus";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "d9a56a3af908ae9100b4c9feebff4b918363f241";
+      sha256 = "1c16chfs4b2j1x1bmrklh8ssqki850k787qwq7b95dyxksj2bpx1";
+    };
+    description = "Port of MAME ~2003+ to libretro";
+    license = gpl2Plus;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  mame2010 = (mkLibRetroCore rec {
+    core = "mame2010";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "4ced2c31f1100eefc7f4483b474b8a680a3b3f2b";
+      sha256 = "1a8ijj0sixr6xrqfgimna0ipfj2bb2kvj4mb45hb8a18mwn6y0mc";
+    };
+    description = "Port of MAME ~2010 to libretro";
+    license = gpl2Plus;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  mame2015 = (mkLibRetroCore rec {
+    core = "mame2015";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "e3a28398f54cd6b2c24b7165d215b046b79c10f5";
+      sha256 = "1fgwi37zgp2s92bkz03gch3ivgyjgdi3xycrd8z7x87gi20a79x9";
+    };
+    description = "Port of MAME ~2015 to libretro";
+    license = gpl2Plus;
+    extraBuildInputs = [ python27 alsaLib ];
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  mame2016 = (mkLibRetroCore rec {
+    core = "mame2016";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "ea4c1ffa75eb3fb0096158b71706b8b84d86d12c";
+      sha256 = "1qyvdymmjv5q0k3najgfdxzf1yr6bnysnsl19v753yj29xs4hwzp";
+    };
+    description = "Port of MAME ~2016 to libretro";
+    license = gpl2Plus;
+    extraBuildInputs = [ python27 alsaLib ];
+  }).override {
+    postPatch = ''
+      # Prevent the failure during the parallel building of:
+      # make -C 3rdparty/genie/build/gmake.linux -f genie.make obj/Release/src/host/lua-5.3.0/src/lgc.o
+      mkdir -p 3rdparty/genie/build/gmake.linux/obj/Release/src/host/lua-5.3.0/src
+    '';
+    buildPhase = "make -f Makefile.libretro";
+  };
+
+  mesen = (mkLibRetroCore rec {
+    core = "mesen";
+    src = fetchFromGitHub {
+      owner = "SourMesen";
+      repo = core;
+      rev = "942633dd3dbb73cc3abd748f6d5440c78abbea09";
+      sha256 = "0a95wd64vnblksacapxwxla9j2iw8a5hbdm111cldrni12q87iq2";
+    };
+    description = "Port of Mesen to libretro";
+    license = gpl3;
+  }).override {
+    makefile = "Libretro/Makefile";
+    buildPhase = "cd Libretro && make";
   };
 
   mgba = mkLibRetroCore rec {
     core = "mgba";
     src = fetchRetro {
       repo = core;
-      rev = "fdaaaee661e59f28c94c7cfa4e82e70b71e24a9d";
-      sha256 = "1b30sa861r4bhbqkx6vkklh4iy625bpzki2ks4ivvjns1ijczvc7";
+      rev = "4865aaabc2a46c635f218f7b51f8fc5cc2c4c8ac";
+      sha256 = "1mdzwcsl5bafmgqfh0a1bgfgilisffxsygcby0igsq2bgkal47mm";
     };
     description = "Port of mGBA to libretro";
     license = mpl20;
   };
 
   mupen64plus = (mkLibRetroCore rec {
-    core = "mupen64plus";
+    core = "mupen64plus-next";
     src = fetchRetro {
-      repo = core + "-libretro";
-      rev = "407bcd40b3a42bff6b856a6d6f88a7d5d670bf9e";
-      sha256 = "0q5kvjz7rpk7mp75cdywqjgmy10c0h7ky26hh1x90d39y94idcd8";
+      repo = "mupen64plus-libretro-nx"; # + "-libretro-nx";
+      rev = "f77c16f9f1dd911fd2254becc8a28adcdafe8aa1";
+      sha256 = "0j6vrkwch9lwmlhyz7fp1ha0bby54gvbwk91hwbv35f6dvs0aw0d";
     };
     description = "Libretro port of Mupen64 Plus, GL only";
     license = gpl2;
 
-    extraBuildInputs = [ libGLU_combined libpng ];
+    extraBuildInputs = [ libGLU_combined libpng nasm xorg.libX11 ];
   }).override {
-    buildPhase = "make WITH_DYNAREC=${if stdenv.hostPlatform.system == "x86_64-linux" then "x86_64" else "x86"}";
+    makefile = "Makefile";
+    buildPhase = "make";
   };
 
   nestopia = (mkLibRetroCore rec {
     core = "nestopia";
     src = fetchRetro {
       repo = core;
-      rev = "ecfa170a582e5b8ec11225ca645843fa064955ca";
-      sha256 = "17ac7dhasch6f4lpill8c5scsvaix0jvbf1cp797qbll4hk84f2q";
+      rev = "7f48c211c281880d122981da119a4455a9bebbde";
+      sha256 = "05p3a559633dzw222rs1fh48v657mdyirl1qfqzkhqiar9rxf31g";
     };
     description = "nestopia undead libretro port";
     license = gpl2;
   }).override {
+    makefile = "libretro/Makefile";
     buildPhase = "cd libretro && make";
   };
-
+ 
+  o2em = (mkLibRetroCore rec {
+    core = "o2em";
+    src = fetchRetro {
+      repo = "libretro-" + core;
+      rev = "d6731b9b2592654ce4f1b64c1b1da17b32e7c94c";
+      sha256 = "0809qw16y7ablxfayf0lbzvq7wqdmjp0afdb0vcgv193vvhhp58q";
+    };
+    description = "Port of O2EM to libretro";
+    license = artistic1;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+ 
   parallel-n64 = (mkLibRetroCore rec {
     core = "parallel-n64";
     src = fetchRetro {
       repo = core;
-      rev = "3276db27547bf7ca85896427f0b82d4658694d88";
-      sha256 = "19396v50azrb52ifjk298zgcbxn8dvfvp6zwrnzsk6mp8ff7qcqw";
+      rev = "30f4fd3c2456145763eb76aead7485a1b86ba6bd";
+      sha256 = "0kbyzmscmfi6f842clzaff4k6xcb5410fwhv8n6vv42xk6ljfvgh";
     };
     description = "Parallel Mupen64plus rewrite for libretro.";
     license = gpl2;
 
     extraBuildInputs = [ libGLU_combined libpng ];
   }).override {
-    buildPhase = "make WITH_DYNAREC=${if stdenv.hostPlatform.system == "x86_64-linux" then "x86_64" else "x86"}";
+    makefile = "Makefile";
+    buildPhase = "make";
   };
 
+  pcsx_rearmed = (mkLibRetroCore rec {
+    core = "pcsx_rearmed";
+    src = fetchRetro {
+      repo = core;
+      rev = "eb6943ee04b0f30a6f1cebfe399a94bacd1dfb45";
+      sha256 = "0xikdirvjal4mdr5y9dl9gcxhdilqzq43f909b0z8vc069vj1wjz";
+    };
+    description = "Port of PCSX ReARMed to libretro";
+    license = gpl2;
+  }).override {
+    configurePhase = "rm configure";
+    buildPhase = "make -f Makefile.libretro";
+  };
+  
   picodrive = (mkLibRetroCore rec {
     core = "picodrive";
     src = fetchRetro {
       repo = core;
-      rev = "cbc93b68dca1d72882d07b54bbe1ef25b980558a";
-      sha256 = "0fl9r6jj2x9231md5zc4scra79j5hfn1n2z67scff1375xg1k64h";
+      rev = "28dcfd6f43434e6828ee647223a0576bfe858c24";
+      sha256 = "19a1b6q8fhf7wxzyf690va1ixzlxlzyslv1zxm0ll5pfsqf2y3gx";
     };
     description = "Fast MegaDrive/MegaCD/32X emulator";
     license = "MAME";
@@ -321,18 +694,38 @@ in with stdenv.lib.licenses;
     configurePhase = "./configure";
   };
 
+  play = (mkLibRetroCore rec {
+    core = "play";
+    src = fetchRetro {
+      repo = "play-";
+      rev = "fedc1e1c2918a7490a881cdb4ec951a828c19671";
+      sha256 = "0hwxx7h61gd29a2gagwjbvxk2hgwdk1wxg4nx90zrizb8nczwnl6";
+    };
+    description = "Port of Play! to libretro";
+    license = bsd2;
+    extraBuildInputs = [ cmake boost ];
+  }).override {
+    cmakeFlags = [ "-DBUILD_PLAY=OFF -DBUILD_LIBRETRO_CORE=ON" ];
+    buildPhase = "make";
+  };
+
   ppsspp = (mkLibRetroCore rec {
     core = "ppsspp";
-    src = fetchRetro {
-      repo = "libretro-" + core;
-      rev = "5f7bcf7bfc15f83d405bcecd7a163a55ad1e7573";
-      sha256 = "06k1gzmypz61dslynrw4b5i161rhj43y6wnr2nhbzvwcv5bw8w8r";
+    src = fetchgit {
+      url = "https://github.com/hrydgard/ppsspp";
+      rev = "bf1777f7d3702e6a0f71c7ec1fc51976e23c2327";
+      sha256 = "17sym0vk72lzbh9a1501mhw98c78x1gq7k1fpy69nvvb119j37wa";
     };
     description = "ppsspp libretro port";
     license = gpl2;
-    extraBuildInputs = [ libGLU_combined ffmpeg ];
+    extraBuildInputs = [ cmake libGLU_combined ffmpeg python37 xorg.libX11 ];
   }).override {
-    buildPhase = "cd libretro && make";
+    cmakeFlags = "-DLIBRETRO=ON";
+    makefile = "Makefile";
+    buildPhase = ''
+      make \
+      && mv lib/ppsspp_libretro${stdenv.hostPlatform.extensions.sharedLibrary} ppsspp_libretro${stdenv.hostPlatform.extensions.sharedLibrary}
+    '';
   };
 
   prboom = (mkLibRetroCore rec {
@@ -348,30 +741,31 @@ in with stdenv.lib.licenses;
     buildPhase = "make";
   };
 
-  quicknes = (mkLibRetroCore {
-    core = "quicknes";
+  prosystem = (mkLibRetroCore rec {
+    core = "prosystem";
     src = fetchRetro {
-      repo = "QuickNES_Core";
-      rev = "8613b48cee97f1472145bbafa76e543854b2bbd5";
-      sha256 = "18lizdb9zjlfhh8ibvmcscldlf3mw4aj8nds3pah68cd2lw170w1";
+      repo = core + "-libretro";
+      rev = "cb4aa3ee72f98b0891a7bac5c9dac458cdba4d34";
+      sha256 = "0yvzmks9zz1hf7mv6cd2qin1p3yx00dbrcxlm0yysy5q5jiigblg";
     };
-    description = "QuickNES libretro port";
-    license = lgpl21Plus;
+    description = "Port of ProSystem to libretro";
+    license = gpl2;
   }).override {
+    makefile = "Makefile";
     buildPhase = "make";
   };
 
-  reicast = (mkLibRetroCore rec {
-    core = "reicast";
+  quicknes = (mkLibRetroCore rec {
+    core = "quicknes";
     src = fetchRetro {
-      repo = core + "-emulator";
-      rev = "40d4e8af2dd67a3f317c14224873c8ec0e1f9d11";
-      sha256 = "0d8wzpv7pcyh437gmvi439vim26wyrjmi5hj97wvyvggywjwrx8m";
+      repo = "QuickNES_Core";
+      rev = "cd302d998d102c9461a924b81817e48b9ea1518f";
+      sha256 = "1sczs1jqcbhpkb5xpcqqdcnxlz7bqmanm4gdnnc12c19snl7999b";
     };
-    description = "Reicast libretro port";
-    license = gpl2;
-    extraBuildInputs = [ libGLU_combined ];
+    description = "QuickNES libretro port";
+    license = lgpl21Plus;
   }).override {
+    makefile = "Makefile";
     buildPhase = "make";
   };
 
@@ -379,13 +773,14 @@ in with stdenv.lib.licenses;
     core = "scummvm";
     src = fetchRetro {
       repo = core;
-      rev = "de8d7e58caa23f071ce9d1bc5133f45d16c3ff1c";
-      sha256 = "097i2dq3hw14hicsplrs36j1qa3r45vhzny5v4aw6qw4aj34hksy";
+      rev = "e07a6ede61c364fb87630fa7507a4f8482d882e0";
+      sha256 = "0i88z53q28lwzmadxincab4m66qbzcbmasgildybj8db0z2z8jm0";
     };
     description = "Libretro port of ScummVM";
     license = gpl2;
     extraBuildInputs = [ fluidsynth libjpeg libvorbis libGLU_combined SDL ];
   }).override {
+    makefile = "backends/platform/libretro/build/Makefile";
     buildPhase = "cd backends/platform/libretro/build && make";
   };
 
@@ -393,50 +788,85 @@ in with stdenv.lib.licenses;
     core = "snes9x";
     src = fetchRetro {
       repo = core;
-      rev = "db4bfaba3b0d5a067fe9aea323503656837a8d9a";
-      sha256 = "02f04ss45km32lp68diyfkix1gryx89qy8cc80189ipwnx80pgip";
+      rev = "29b78df8c9f0f48ed4605d08a187a134b3b316d6";
+      sha256 = "004h1pkxvbn4zlh8bqs6z17k04jw5wzbwklpgvmb7hbxshsi4qid";
     };
     description = "Port of SNES9x git to libretro";
     license = "Non-commercial";
   }).override {
+    makefile = "libretro/Makefile";
     buildPhase = "cd libretro && make";
   };
 
-  snes9x-next = (mkLibRetroCore rec {
-    core = "snes9x-next";
+  snes9x2002 = (mkLibRetroCore rec {
+    core = "snes9x2002";
+    src = fetchRetro {
+      repo = core;
+      rev = "354bcb5acea0aa45b56ae553e0b2b4f10792dfeb";
+      sha256 = "05gvjjxy6ci5pax3frd9g8k9mkqskab5g6rvfjab7cc4zrxrg23f";
+    };
+    description = "Optimized port/rewrite of SNES9x 1.39 to Libretro";
+    license = "Non-commercial";
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  snes9x2005 = (mkLibRetroCore rec {
+    core = "snes9x2005";
+    src = fetchRetro {
+      repo = core;
+      rev = "e5cadd2f21fb64e8c7194ad006b39e6f555c4a5b";
+      sha256 = "1q0xrw3f8zm2k19sva8cz28yx815w8a6y1xsl0i6bb3cai3q1hyx";
+    };
+    description = "Optimized port/rewrite of SNES9x 1.43 to Libretro";
+    license = "Non-commercial";
+  }).override {
+    makefile = "Makefile";
+    buildPhase = ''
+      make USE_BLARGG_APU=1 \
+      && mv snes9x2005_plus_libretro${stdenv.hostPlatform.extensions.sharedLibrary} snes9x2005_libretro${stdenv.hostPlatform.extensions.sharedLibrary}
+    '';
+  };
+
+  snes9x2010 = (mkLibRetroCore rec {
+    core = "snes9x2010";
     src = fetchRetro {
       repo = core;
-      rev = "b2a69de0df1eb39ed362806f9c9633f4544272af";
-      sha256 = "1vhgsrg9l562nincfvpj2h2dqkkblg1qmh0v47jqlqgmgl2b1zij";
+      rev = "e945cbae0f8c472e1567a319817c9228b775dd71";
+      sha256 = "1pj5p4a2hy7hk90bzy4vnkz3b6nc8n1niqibgwhyfsc22xlxqsfr";
     };
     description = "Optimized port/rewrite of SNES9x 1.52+ to Libretro";
     license = "Non-commercial";
   }).override {
     buildPhase = ''
       make -f Makefile.libretro
-      mv snes9x2010_libretro${stdenv.hostPlatform.extensions.sharedLibrary} snes9x_next_libretro${stdenv.hostPlatform.extensions.sharedLibrary}
     '';
   };
 
   stella = (mkLibRetroCore rec {
     core = "stella";
     src = fetchRetro {
-      repo = core + "-libretro";
-      rev = "bbe65db0e344dcb38905586bd853076b65963e5a";
-      sha256 = "18r1yyfzvjq2hq04d94y37kzsq6aywh1aim69a3imk8kh46gwrh0";
+      repo = core + "2014-libretro";
+      rev = "6d74ad9a0fd779145108cf1213229798d409ed37";
+      sha256 = "0b1nsk92rr64xxj8jc9vpjqgrmm3554096zl031ymr94j5cc87q9";
     };
     description = "Port of Stella to libretro";
     license = gpl2;
   }).override {
-    buildPhase = "make";
+    makefile = "Makefile";
+    buildPhase = ''
+      make \
+      && mv stella2014_libretro${stdenv.hostPlatform.extensions.sharedLibrary} stella_libretro${stdenv.hostPlatform.extensions.sharedLibrary}
+    '';
   };
 
   vba-next = mkLibRetroCore rec {
     core = "vba-next";
     src = fetchRetro {
       repo = core;
-      rev = "e7734756d228ea604f8fa872cea1bba987780791";
-      sha256 = "03s4rh7dbbhbfc4pfdvr9jcbxrp4ijg8yp49s1xhr7sxsblj2vpv";
+      rev = "3580ae6acb1a90c4e982e57597458da07eca4f41";
+      sha256 = "0fz8z04kf9g1i5x5slyvx5kb07garzxvhcqnwmqn5j574xh1lc6d";
     };
     description = "VBA-M libretro port with modifications for speed";
     license = gpl2;
@@ -446,13 +876,55 @@ in with stdenv.lib.licenses;
     core = "vbam";
     src = fetchRetro {
       repo = core + "-libretro";
-      rev = "1b82fc2d761f027567632692f787482d1e287ec2";
-      sha256 = "043djmqvh2grc25hwjw4b5kfx57b89ryp6fcl8v632sm35l3dd6z";
+      rev = "9ccdeac3aa9db00720bb80eff5c9924362144efa";
+      sha256 = "0rq89i9f483j93shhp2p3vqsnb2abpwz6wdnsycfwxgblczmi22y";
     };
     description = "vanilla VBA-M libretro port";
     license = gpl2;
   }).override {
+    makefile = "src/libretro/Makefile";
     buildPhase = "cd src/libretro && make";
   };
 
+  vecx = (mkLibRetroCore rec {
+    core = "vecx";
+    src = fetchRetro {
+      repo = "libretro-" + core;
+      rev = "26585ee701499550e484c11f005db18e926827d9";
+      sha256 = "0vz2aksc8mqnw55f2bvvawj21mxf60fp93r0sr55hdccn9h7355k";
+    };
+    description = "Port of Vecx to libretro";
+    license = gpl3;
+  }).override {
+    buildPhase = "make";
+  };
+
+  virtualjaguar = (mkLibRetroCore rec {
+    core = "virtualjaguar";
+    src = fetchRetro {
+      repo = core + "-libretro";
+      rev = "7bdd8658880b53bf2bcbae0741323fe18f9041f5";
+      sha256 = "0zbrsfhvx293ijazy1w19qha19hprsi0zv8295sa0gq8kyh0xhyw";
+    };
+    description = "Port of VirtualJaguar to libretro";
+    license = gpl3;
+  }).override {
+    makefile = "Makefile";
+    buildPhase = "make";
+  };
+
+  yabause = (mkLibRetroCore rec {
+    core = "yabause";
+    src = fetchRetro {
+      repo = core;
+      rev = "08d09cb88a69ee4c2986693fb813e0eb58d71481";
+      sha256 = "0z55yam1l7m21kbjwn44sp4md9g7p95b27vcxr7i0v08gnkwwvv1";
+    };
+    description = "Port of Yabause to libretro";
+    license = gpl2;
+  }).override {
+    makefile = "yabause/src/libretro/Makefile";
+    buildPhase = "cd yabause/src/libretro && make";
+  };
+
 }
diff --git a/pkgs/misc/vscode-extensions/cpptools/default.nix b/pkgs/misc/vscode-extensions/cpptools/default.nix
index 70d08aa18a0..08fee83d8ce 100644
--- a/pkgs/misc/vscode-extensions/cpptools/default.nix
+++ b/pkgs/misc/vscode-extensions/cpptools/default.nix
@@ -83,8 +83,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
   mktplcRef = {
     name = "cpptools";
     publisher = "ms-vscode";
-    version = "0.26.0";
-    sha256 = "1njclj07amj9n187k3rbjvddkhmsc4aljdbsgjxpj58fv7zdy7kq";
+    version = "0.26.1";
+    sha256 = "09khm0byxa9mv8qbqrikd7akz3p816ra5z8l86xqkmbm6j1k4wpc";
   };
 
   buildInputs = [
diff --git a/pkgs/os-specific/linux/brillo/default.nix b/pkgs/os-specific/linux/brillo/default.nix
new file mode 100644
index 00000000000..3ad4acf127b
--- /dev/null
+++ b/pkgs/os-specific/linux/brillo/default.nix
@@ -0,0 +1,34 @@
+{ stdenv, fetchFromGitLab , go-md2man, coreutils, substituteAll }:
+
+stdenv.mkDerivation rec {
+  pname = "brillo";
+  version = "1.4.8";
+
+  src = fetchFromGitLab {
+    owner= "cameronnemo";
+    repo= "brillo";
+    rev= "v${version}";
+    sha256 = "0wxvg541caiwm3bjwbmk7xcng7jd9xsiga2agxwp7gpkrlp74j9f";
+  };
+
+  patches = [
+    (substituteAll {
+      src = ./udev-rule.patch;
+      inherit coreutils;
+    })
+  ];
+
+  nativeBuildInputs = [ go-md2man ];
+
+  makeFlags = [ "PREFIX=$(out)" "AADIR=$(out)/etc/apparmor.d" ];
+
+  installTargets = "install-dist";
+
+  meta = with stdenv.lib; {
+    description = "Backlight and Keyboard LED control tool";
+    homepage = https://gitlab.com/cameronnemo/brillo;
+    license = [ licenses.gpl3 licenses.bsd0 ];
+    platforms = platforms.linux;
+    maintainers = [ maintainers.alexarice ];
+  };
+}
diff --git a/pkgs/os-specific/linux/brillo/udev-rule.patch b/pkgs/os-specific/linux/brillo/udev-rule.patch
new file mode 100644
index 00000000000..7b1cf484067
--- /dev/null
+++ b/pkgs/os-specific/linux/brillo/udev-rule.patch
@@ -0,0 +1,13 @@
+diff --git a/contrib/udev.in b/contrib/udev.in
+index 0625952..a6c940e 100644
+--- a/contrib/udev.in
++++ b/contrib/udev.in
+@@ -1,4 +1,4 @@
+-ACTION=="add", SUBSYSTEM=="backlight", RUN+="/bin/chgrp @group@ /sys/class/backlight/%k/brightness"
+-ACTION=="add", SUBSYSTEM=="backlight", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
+-ACTION=="add", SUBSYSTEM=="leds", RUN+="/bin/chgrp @group@ /sys/class/leds/%k/brightness"
+-ACTION=="add", SUBSYSTEM=="leds", RUN+="/bin/chmod g+w /sys/class/leds/%k/brightness"
++ACTION=="add", SUBSYSTEM=="backlight", RUN+="@coreutils@/bin/chgrp @group@ /sys/class/backlight/%k/brightness"
++ACTION=="add", SUBSYSTEM=="backlight", RUN+="@coreutils@/bin/chmod g+w /sys/class/backlight/%k/brightness"
++ACTION=="add", SUBSYSTEM=="leds", RUN+="@coreutils@/bin/chgrp @group@ /sys/class/leds/%k/brightness"
++ACTION=="add", SUBSYSTEM=="leds", RUN+="@coreutils@/bin/chmod g+w /sys/class/leds/%k/brightness"
diff --git a/pkgs/os-specific/linux/digimend/default.nix b/pkgs/os-specific/linux/digimend/default.nix
new file mode 100644
index 00000000000..40f801881fc
--- /dev/null
+++ b/pkgs/os-specific/linux/digimend/default.nix
@@ -0,0 +1,45 @@
+{ stdenv, fetchFromGitHub, kernel }:
+
+assert stdenv.lib.versionAtLeast kernel.version "3.5";
+
+stdenv.mkDerivation rec {
+  pname = "digimend";
+  version = "unstable-2019-06-18";
+
+  src = fetchFromGitHub {
+    owner = "digimend";
+    repo = "digimend-kernel-drivers";
+    rev = "8b228a755e44106c11f9baaadb30ce668eede5d4";
+    sha256 = "1l54j85540386a8aypqka7p5hy1b63cwmpsscv9rmmf10f78v8mm";
+  };
+
+  INSTALL_MOD_PATH = "\${out}";
+
+  postPatch = ''
+    sed 's/udevadm /true /' -i Makefile
+    sed 's/depmod /true /' -i Makefile
+  '';
+
+  nativeBuildInputs = kernel.moduleBuildDependencies;
+
+  postInstall = ''
+    # Remove module reload hack.
+    # The hid-rebind unloads and then reloads the hid-* module to ensure that
+    # the extra/ module is loaded.
+    rm -r $out/lib/udev
+  '';
+
+  makeFlags = [
+    "KVERSION=${kernel.modDirVersion}"
+    "KDIR=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
+    "DESTDIR=${placeholder "out"}"
+  ];
+
+  meta = with stdenv.lib; {
+    description = "DIGImend graphics tablet drivers for the Linux kernel";
+    homepage = "https://digimend.github.io/";
+    license = licenses.gpl2;
+    maintainers = with maintainers; [ gebner ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/pkgs/os-specific/linux/kernel/linux-testing.nix b/pkgs/os-specific/linux/kernel/linux-testing.nix
index 9c91c91eeb4..8096684b137 100644
--- a/pkgs/os-specific/linux/kernel/linux-testing.nix
+++ b/pkgs/os-specific/linux/kernel/linux-testing.nix
@@ -3,7 +3,7 @@
 with stdenv.lib;
 
 buildLinux (args // rec {
-  version = "5.4-rc5";
+  version = "5.4-rc6";
   extraMeta.branch = "5.4";
 
   # modDirVersion needs to be x.y.z, will always add .0
@@ -11,7 +11,7 @@ buildLinux (args // rec {
 
   src = fetchurl {
     url = "https://git.kernel.org/torvalds/t/linux-${version}.tar.gz";
-    sha256 = "0047f1vq93cq9qa0550dnilci0qxy4ygc6brhcr6xbwqakglwr18";
+    sha256 = "0ypazqr6z0n8fwaawxca0i56bwd4g4q2bw5qwayf0f4402m34xdh";
   };
 
   # Should the testing kernels ever be built on Hydra?
diff --git a/pkgs/os-specific/linux/kmod/aggregator.nix b/pkgs/os-specific/linux/kmod/aggregator.nix
index 4da87a557cb..cd138f1d7f5 100644
--- a/pkgs/os-specific/linux/kmod/aggregator.nix
+++ b/pkgs/os-specific/linux/kmod/aggregator.nix
@@ -29,7 +29,7 @@ buildEnv {
       # kernel version number, otherwise depmod will use `uname -r'.
       if test -w $out/lib/modules/$kernelVersion; then
           rm -f $out/lib/modules/$kernelVersion/modules.!(builtin*|order*)
-          ${kmod}/bin/depmod -b $out -a $kernelVersion
+          ${kmod}/bin/depmod -b $out -C $out/etc/depmod.d -a $kernelVersion
       fi
     '';
 }
diff --git a/pkgs/servers/amqp/rabbitmq-server/default.nix b/pkgs/servers/amqp/rabbitmq-server/default.nix
index 12211f49698..bc83c5a8ea2 100644
--- a/pkgs/servers/amqp/rabbitmq-server/default.nix
+++ b/pkgs/servers/amqp/rabbitmq-server/default.nix
@@ -6,12 +6,12 @@
 stdenv.mkDerivation rec {
   pname = "rabbitmq-server";
 
-  version = "3.8.0";
+  version = "3.8.1";
 
   # when updating, consider bumping elixir version in all-packages.nix
   src = fetchurl {
     url = "https://github.com/rabbitmq/rabbitmq-server/releases/download/v${version}/${pname}-${version}.tar.xz";
-    sha256 = "174ai8ihk50gwbqinxxxx5is6izvgmfca7skvvp4yk6fl8nbwm15";
+    sha256 = "17ymzjgz3544jgf321f8f788gdxs9l252ah61nlgsglv0x8gggrh";
   };
 
   buildInputs =
diff --git a/pkgs/servers/search/groonga/default.nix b/pkgs/servers/search/groonga/default.nix
index 59affd09295..7fb7a774e8d 100644
--- a/pkgs/servers/search/groonga/default.nix
+++ b/pkgs/servers/search/groonga/default.nix
@@ -7,11 +7,11 @@
 stdenv.mkDerivation rec {
 
   pname = "groonga";
-  version = "9.0.8";
+  version = "9.0.9";
 
   src = fetchurl {
     url    = "https://packages.groonga.org/source/groonga/${pname}-${version}.tar.gz";
-    sha256 = "1fcagm0hzfl9jvn9afzhaahphvq3mc7d7s1s7hhinpv7bsr3xdl5";
+    sha256 = "0axf07cg8j5lahkl41li9f7i3c6318cmlb40865iscmkjl17yxh9";
   };
 
   buildInputs = with stdenv.lib;
diff --git a/pkgs/servers/search/solr/8.x.nix b/pkgs/servers/search/solr/8.x.nix
index fd888de60de..7abfe9a2b20 100644
--- a/pkgs/servers/search/solr/8.x.nix
+++ b/pkgs/servers/search/solr/8.x.nix
@@ -2,11 +2,11 @@
 
 stdenv.mkDerivation rec {
   pname = "solr";
-  version = "8.2.0";
+  version = "8.3.0";
 
   src = fetchurl {
     url = "mirror://apache/lucene/${pname}/${version}/${pname}-${version}.tgz";
-    sha256 = "0j9lydxlng785h2n1b8avinrkqdpbj5qn4rk897p2pbf4fdv795z";
+    sha256 = "11qkipmj8qq4gw5lwnx1j8dr2lq8d5h1v1fbdyppw8l6a68j160s";
   };
 
   nativeBuildInputs = [ makeWrapper ];
diff --git a/pkgs/servers/shellinabox/default.nix b/pkgs/servers/shellinabox/default.nix
index af1992fc869..fe1837e907a 100644
--- a/pkgs/servers/shellinabox/default.nix
+++ b/pkgs/servers/shellinabox/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchFromGitHub, autoreconfHook, pam, openssl, openssh, shadow, makeWrapper }:
+{ stdenv, fetchFromGitHub, fetchpatch, autoreconfHook, pam, openssl, openssh, shadow, makeWrapper }:
 
 stdenv.mkDerivation rec {
   version = "2.20";
@@ -11,10 +11,17 @@ stdenv.mkDerivation rec {
     sha256 = "1hmfayh21cks2lyj572944ll0mmgsxbnj981b3hq3nhdg8ywzjfr";
   };
 
-  patches = [ ./shellinabox-minus.patch ];
+  patches = [
+    ./shellinabox-minus.patch
+    (fetchpatch {
+      name = "CVE-2018-16789.patch";
+      url = "https://github.com/shellinabox/shellinabox/commit/4f0ecc31ac6f985e0dd3f5a52cbfc0e9251f6361.patch";
+      sha256 = "1mpm6acxdb0fms9pa2b88fx6hp07ph87ahxi82yyqj2m7p79jx7a";
+    })
+  ];
 
-  nativeBuildInputs = [ autoreconfHook ];
-  buildInputs = [ pam openssl openssh makeWrapper ];
+  nativeBuildInputs = [ autoreconfHook makeWrapper ];
+  buildInputs = [ pam openssl openssh ];
 
   # Disable GSSAPIAuthentication errors. Also, paths in certain source files are
   # hardcoded. Replace the hardcoded paths with correct paths.
diff --git a/pkgs/servers/sql/postgresql/ext/timescaledb.nix b/pkgs/servers/sql/postgresql/ext/timescaledb.nix
index ef3dc4894d7..296e7e0a41a 100644
--- a/pkgs/servers/sql/postgresql/ext/timescaledb.nix
+++ b/pkgs/servers/sql/postgresql/ext/timescaledb.nix
@@ -8,7 +8,7 @@
 
 stdenv.mkDerivation rec {
   pname = "timescaledb";
-  version = "1.4.2";
+  version = "1.5.0";
 
   nativeBuildInputs = [ cmake ];
   buildInputs = [ postgresql openssl ];
@@ -17,10 +17,10 @@ stdenv.mkDerivation rec {
     owner  = "timescale";
     repo   = "timescaledb";
     rev    = "refs/tags/${version}";
-    sha256 = "06mchpfjh4kskxq5r8b84870gl37xcqdf14n96qjb4nbyw9l8xcc";
+    sha256 = "0qw7yp2vh3fkx43zlnj8xsvd0d68rcmdcl3p9jpmr97hyl376xf2";
   };
 
-  cmakeFlags = [ "-DSEND_TELEMETRY_DEFAULT=OFF" ];
+  cmakeFlags = [ "-DSEND_TELEMETRY_DEFAULT=OFF" "-DREGRESS_CHECKS=OFF" ];
 
   # Fix the install phase which tries to install into the pgsql extension dir,
   # and cannot be manually overridden. This is rather fragile but works OK.
diff --git a/pkgs/servers/web-apps/dokuwiki/default.nix b/pkgs/servers/web-apps/dokuwiki/default.nix
new file mode 100644
index 00000000000..ff6fa982228
--- /dev/null
+++ b/pkgs/servers/web-apps/dokuwiki/default.nix
@@ -0,0 +1,26 @@
+{ stdenv, fetchFromGitHub }:
+
+stdenv.mkDerivation rec {
+  pname = "dokuwiki";
+  version = "2018-04-22b";
+
+  src = fetchFromGitHub {
+    owner = "splitbrain";
+    repo = "${pname}";
+    rev = "release_stable_${version}";
+    sha256 = "1na5pn4j4mi2la80ywzg1krwqdxz57mjkw0id6ga9rws809gkdjp";
+  };
+
+  installPhase = ''
+    mkdir -p $out/share/dokuwiki
+    cp -r * $out/share/dokuwiki
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Simple to use and highly versatile Open Source wiki software that doesn't require a database";
+    license = licenses.gpl2;
+    homepage = "https://www.dokuwiki.org";
+    platforms = platforms.all;
+    maintainers = [ maintainers."1000101" ];
+  };
+}
diff --git a/pkgs/shells/zsh/zsh-history-substring-search/default.nix b/pkgs/shells/zsh/zsh-history-substring-search/default.nix
index b7521654667..fcd294f4dce 100644
--- a/pkgs/shells/zsh/zsh-history-substring-search/default.nix
+++ b/pkgs/shells/zsh/zsh-history-substring-search/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "zsh-history-substring-search";
-  version = "1.0.1";
+  version = "1.0.2";
 
   src = fetchFromGitHub {
     owner = "zsh-users";
     repo = "zsh-history-substring-search";
     rev = "v${version}";
-    sha256 = "0lgmq1xcccnz5cf7vl0r0qj351hwclx9p80cl0qczxry4r2g5qaz";
+    sha256 = "0y8va5kc2ram38hbk2cibkk64ffrabfv1sh4xm7pjspsba9n5p1y";
   };
 
   installPhase = ''
diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix
index b754230b0be..6bd6a9bf41e 100644
--- a/pkgs/stdenv/generic/check-meta.nix
+++ b/pkgs/stdenv/generic/check-meta.nix
@@ -36,10 +36,10 @@ let
     attrs ? meta.license;
 
   hasWhitelistedLicense = assert areLicenseListsValid; attrs:
-    hasLicense attrs && builtins.elem attrs.meta.license whitelist;
+    hasLicense attrs && lib.lists.any (l: builtins.elem l whitelist) (lib.lists.toList attrs.meta.license);
 
   hasBlacklistedLicense = assert areLicenseListsValid; attrs:
-    hasLicense attrs && builtins.elem attrs.meta.license blacklist;
+    hasLicense attrs && lib.lists.any (l: builtins.elem l blacklist) (lib.lists.toList attrs.meta.license);
 
   allowBroken = config.allowBroken or false
     || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
@@ -75,7 +75,7 @@ let
     allowInsecurePredicate attrs ||
     builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
 
-  showLicense = license: license.shortName or "unknown";
+  showLicense = license: toString (map (l: l.shortName or "unknown") (lib.lists.toList license));
 
   pos_str = meta: meta.position or "«unknown-file»";
 
diff --git a/pkgs/stdenv/linux/make-bootstrap-tools.nix b/pkgs/stdenv/linux/make-bootstrap-tools.nix
index 8d513625df2..0c285f9661e 100644
--- a/pkgs/stdenv/linux/make-bootstrap-tools.nix
+++ b/pkgs/stdenv/linux/make-bootstrap-tools.nix
@@ -33,6 +33,15 @@ in with pkgs; rec {
     '';
   };
 
+  bootGCC = gcc.cc.override { enableLTO = false; };
+  bootBinutils = binutils.bintools.override {
+    withAllTargets = false;
+    # Don't need two linkers, disable whatever's not primary/default.
+    gold = false;
+    # bootstrap is easier w/static
+    enableShared = false;
+  };
+
   build =
 
     stdenv.mkDerivation {
@@ -109,12 +118,12 @@ in with pkgs; rec {
         cp -d ${gnugrep.pcre.out}/lib/libpcre*.so* $out/lib # needed by grep
 
         # Copy what we need of GCC.
-        cp -d ${gcc.cc.out}/bin/gcc $out/bin
-        cp -d ${gcc.cc.out}/bin/cpp $out/bin
-        cp -d ${gcc.cc.out}/bin/g++ $out/bin
-        cp -d ${gcc.cc.lib}/lib/libgcc_s.so* $out/lib
-        cp -d ${gcc.cc.lib}/lib/libstdc++.so* $out/lib
-        cp -rd ${gcc.cc.out}/lib/gcc $out/lib
+        cp -d ${bootGCC.out}/bin/gcc $out/bin
+        cp -d ${bootGCC.out}/bin/cpp $out/bin
+        cp -d ${bootGCC.out}/bin/g++ $out/bin
+        cp -d ${bootGCC.lib}/lib/libgcc_s.so* $out/lib
+        cp -d ${bootGCC.lib}/lib/libstdc++.so* $out/lib
+        cp -rd ${bootGCC.out}/lib/gcc $out/lib
         chmod -R u+w $out/lib
         rm -f $out/lib/gcc/*/*/include*/linux
         rm -f $out/lib/gcc/*/*/include*/sound
@@ -122,11 +131,11 @@ in with pkgs; rec {
         rm -f $out/lib/gcc/*/*/include-fixed/asm
         rm -rf $out/lib/gcc/*/*/plugin
         #rm -f $out/lib/gcc/*/*/*.a
-        cp -rd ${gcc.cc.out}/libexec/* $out/libexec
+        cp -rd ${bootGCC.out}/libexec/* $out/libexec
         chmod -R u+w $out/libexec
         rm -rf $out/libexec/gcc/*/*/plugin
         mkdir -p $out/include
-        cp -rd ${gcc.cc.out}/include/c++ $out/include
+        cp -rd ${bootGCC.out}/include/c++ $out/include
         chmod -R u+w $out/include
         rm -rf $out/include/c++/*/ext/pb_ds
         rm -rf $out/include/c++/*/ext/parallel
@@ -148,7 +157,7 @@ in with pkgs; rec {
 
         # Copy binutils.
         for i in as ld ar ranlib nm strip readelf objdump; do
-          cp ${binutils.bintools.out}/bin/$i $out/bin
+          cp ${bootBinutils.out}/bin/$i $out/bin
         done
         cp '${lib.getLib binutils.bintools}'/lib/* "$out/lib/"
 
@@ -172,7 +181,7 @@ in with pkgs; rec {
         mv $out/.pack $out/pack
 
         mkdir $out/on-server
-        XZ_OPT=-9 tar cvJf $out/on-server/bootstrap-tools.tar.xz --hard-dereference --sort=name --numeric-owner --owner=0 --group=0 --mtime=@1 -C $out/pack .
+        XZ_OPT="-9 -e" tar cvJf $out/on-server/bootstrap-tools.tar.xz --hard-dereference --sort=name --numeric-owner --owner=0 --group=0 --mtime=@1 -C $out/pack .
         cp ${busyboxMinimal}/bin/busybox $out/on-server
         chmod u+w $out/on-server/busybox
         nuke-refs $out/on-server/busybox
diff --git a/pkgs/tools/X11/wpgtk/default.nix b/pkgs/tools/X11/wpgtk/default.nix
index 1a6e99f0393..fce3df19718 100644
--- a/pkgs/tools/X11/wpgtk/default.nix
+++ b/pkgs/tools/X11/wpgtk/default.nix
@@ -3,13 +3,13 @@
 
 python3Packages.buildPythonApplication rec {
   pname = "wpgtk";
-  version = "6.0.9";
+  version = "6.0.11";
 
   src = fetchFromGitHub {
     owner = "deviantfero";
     repo = "wpgtk";
     rev = version;
-    sha256 = "0j2wci85918zsrrvd4qpcqv9bzhzj7qvjchvhvl11fn035jml5l0";
+    sha256 = "0da4gj54c361a0bicrjhhb9bp9yr5lx7p1knrsc4dykap1xn23vi";
   };
 
   buildInputs = [
diff --git a/pkgs/tools/audio/video2midi/default.nix b/pkgs/tools/audio/video2midi/default.nix
index c664c745f32..43539f1ee29 100644
--- a/pkgs/tools/audio/video2midi/default.nix
+++ b/pkgs/tools/audio/video2midi/default.nix
@@ -8,7 +8,7 @@ let
   });
 in pythonPackages.buildPythonApplication rec {
   pname = "video2midi";
-  version = "0.3.9.5";
+  version = "0.3.9.6";
 
   format = "other";
 
@@ -16,7 +16,7 @@ in pythonPackages.buildPythonApplication rec {
     owner = "svsdval";
     repo = pname;
     rev = version;
-    sha256 = "1jc50zimc64ilc1as3dyh16lsygwqyvi381mw8si8m9j3pw6may4";
+    sha256 = "0x9b8hwl325gd6v9i60yh95gbn49nydpwyfqs92mbq8vvvq7x8fk";
   };
 
   propagatedBuildInputs = with pythonPackages; [ opencv3_ midiutil pygame pyopengl ];
diff --git a/pkgs/tools/filesystems/sshfs-fuse/default.nix b/pkgs/tools/filesystems/sshfs-fuse/default.nix
index e01cb4dd702..33fc5ce2ab6 100644
--- a/pkgs/tools/filesystems/sshfs-fuse/default.nix
+++ b/pkgs/tools/filesystems/sshfs-fuse/default.nix
@@ -17,7 +17,7 @@ stdenv.mkDerivation rec {
 
   patches = [ (fetchpatch {
     url = "https://github.com/libfuse/sshfs/commit/a548abd1f33a8423bec72724a5f48eb96fa55dd2.patch";
-    sha256 = "03rmks4bz06m9v8s5xjybvmcdw3d09x721jp4i6v0w8pfwsn98w1";
+    sha256 = "19p94aw7nvydd7p2bd1f5cqhlhhamjhda31k22sg06xaqyl893jm";
   }) ];
 
   nativeBuildInputs = [ meson pkgconfig ninja docutils makeWrapper ];
diff --git a/pkgs/tools/misc/dust/default.nix b/pkgs/tools/misc/dust/default.nix
index 4dffae557a4..68f06f1ceb8 100644
--- a/pkgs/tools/misc/dust/default.nix
+++ b/pkgs/tools/misc/dust/default.nix
@@ -2,16 +2,16 @@
 
 rustPlatform.buildRustPackage rec {
   pname = "dust";
-  version = "0.2.3";
+  version = "0.4.1.2";
 
   src = fetchFromGitHub {
     owner = "bootandy";
     repo = "dust";
     rev = "v${version}";
-    sha256 = "1l8z1daiq2x92449p2ciblcwl0ddgr3vqj2dsd3z8jj3y0z8j51s";
+    sha256 = "0a2n96p6z4y09l5z617qbpm8lgxvfagd1l950d2gz9xw4xf1ik5w";
   };
 
-  cargoSha256 = "1bby08ijpwb8676pgm87k80s0n0fqsxc3wmz0v8p9s85yzkflnx5";
+  cargoSha256 = "0cpgxkgz10na90r3fgz8hs20vihqdcc8983inn71fq90627bhdx7";
 
   doCheck = false;
 
diff --git a/pkgs/tools/networking/acme-client/default.nix b/pkgs/tools/networking/acme-client/default.nix
index 60b3b6df69a..bf1c96b66b2 100644
--- a/pkgs/tools/networking/acme-client/default.nix
+++ b/pkgs/tools/networking/acme-client/default.nix
@@ -1,8 +1,8 @@
 { stdenv
+, fetchFromGitHub
+, autoreconfHook
+, bison
 , apple_sdk ? null
-, cacert
-, defaultCaFile ? "${cacert}/etc/ssl/certs/ca-bundle.crt"
-, fetchurl
 , libbsd
 , libressl
 , pkgconfig
@@ -12,24 +12,22 @@ with stdenv.lib;
 
 stdenv.mkDerivation rec {
   pname = "acme-client";
-  version = "0.1.16";
+  version = "0.2.4";
 
-  src = fetchurl {
-    url = "https://kristaps.bsd.lv/acme-client/snapshots/acme-client-portable-${version}.tgz";
-    sha256 = "00q05b3b1dfnfp7sr1nbd212n0mqrycl3cr9lbs51m7ncaihbrz9";
+  src = fetchFromGitHub {
+    owner = "graywolf";
+    repo = "acme-client-portable";
+    rev = "v${version}";
+    sha256 = "1yq2lkrnjwjs0h9mijqysnjmr7kp4zcq1f4cxr9n1db7pw8446xb";
   };
 
-  buildInputs = [ libbsd libressl pkgconfig ]
-    ++ optional stdenv.isDarwin apple_sdk.sdk;
+  nativeBuildInputs = [ autoreconfHook bison pkgconfig ];
+  buildInputs = [ libbsd libressl ] ++ optional stdenv.isDarwin apple_sdk.sdk;
 
-  CFLAGS = "-DDEFAULT_CA_FILE='\"${defaultCaFile}\"'";
-
-  preConfigure = ''
-    export PREFIX="$out"
-  '';
+  makeFlags = [ "PREFIX=${placeholder "out"}" ];
 
   meta = {
-    homepage = https://kristaps.bsd.lv/acme-client/;
+    homepage = "https://github.com/graywolf/acme-client-portable";
     description = "Secure ACME/Let's Encrypt client";
     platforms = platforms.unix;
     license = licenses.isc;
diff --git a/pkgs/tools/networking/phodav/default.nix b/pkgs/tools/networking/phodav/default.nix
index 320e7614c7c..0d7b30ae152 100644
--- a/pkgs/tools/networking/phodav/default.nix
+++ b/pkgs/tools/networking/phodav/default.nix
@@ -1,20 +1,24 @@
 { stdenv, fetchurl
-, intltool, pkgconfig, glib, libsoup }:
+, pkgconfig, libsoup, meson, ninja }:
 
 let
-  version = "2.2";
+  version = "2.3";
 in stdenv.mkDerivation rec {
   pname = "phodav";
   inherit version;
 
   src = fetchurl {
     url = "http://ftp.gnome.org/pub/GNOME/sources/phodav/${version}/${pname}-${version}.tar.xz";
-    sha256 = "1hap0lncbcmivnflh0fbx7y58ry78p9wgj7z03r64ic0kvf0a0q8";
+    sha256 = "0ndy5qva6bq7vhk06jq2d4nr5fp98xsdwypg42vjz91h9ii1xxkf";
   };
 
-  buildInputs = [ intltool glib libsoup ];
+  mesonFlags = [
+    "-Davahi=disabled"
+    "-Dsystemd=disabled"
+    "-Dgtk_doc=disabled"
+  ];
 
-  nativeBuildInputs = [ pkgconfig ];
+  nativeBuildInputs = [ libsoup pkgconfig meson ninja ];
 
   meta = with stdenv.lib; {
     description = "WebDav server implementation and library using libsoup";
diff --git a/pkgs/tools/security/gnupg-pkcs11-scd/default.nix b/pkgs/tools/security/gnupg-pkcs11-scd/default.nix
new file mode 100644
index 00000000000..bc7cff99dc2
--- /dev/null
+++ b/pkgs/tools/security/gnupg-pkcs11-scd/default.nix
@@ -0,0 +1,33 @@
+{ stdenv, fetchurl, libgpgerror, libassuan, libgcrypt, pkcs11helper,
+  pkgconfig, openssl }:
+
+stdenv.mkDerivation rec {
+  pname = "gnupg-pkcs11-scd";
+  version = "0.9.2";
+
+  src = fetchurl {
+    url = "https://github.com/alonbl/${pname}/releases/download/${pname}-${version}/${pname}-${version}.tar.bz2";
+    sha256 = "sha256:1mfh9zjbahjd788rq1mzx009pd7p1sq62sbz586rd7szif7pkpgx";
+  };
+
+  buildInputs = [ pkcs11helper pkgconfig openssl ];
+
+  configureFlags = [
+    "--with-libgpg-error-prefix=${libgpgerror.dev}"
+    "--with-libassuan-prefix=${libassuan.dev}"
+    "--with-libgcrypt-prefix=${libgcrypt.dev}"
+  ];
+
+  meta = with stdenv.lib; {
+    description = "A smart-card daemon to enable the use of PKCS#11 tokens with GnuPG";
+    longDescription = ''
+    gnupg-pkcs11 is a project to implement a BSD-licensed smart-card
+    daemon to enable the use of PKCS#11 tokens with GnuPG.
+    '';
+    homepage = http://gnupg-pkcs11.sourceforge.net/;
+    license = licenses.bsd3;
+    maintainers = with maintainers; [ lschuermann philandstuff ];
+    platforms = platforms.unix;
+  };
+}
+
diff --git a/pkgs/tools/security/keybase/default.nix b/pkgs/tools/security/keybase/default.nix
index 559ba0383bd..653858d3696 100644
--- a/pkgs/tools/security/keybase/default.nix
+++ b/pkgs/tools/security/keybase/default.nix
@@ -1,11 +1,12 @@
-{ stdenv, lib, buildGoPackage, fetchFromGitHub
+{ stdenv, substituteAll, lib, buildGoPackage, fetchFromGitHub
 , AVFoundation, AudioToolbox, ImageIO, CoreMedia
 , Foundation, CoreGraphics, MediaToolbox
+, gnupg
 }:
 
 buildGoPackage rec {
   pname = "keybase";
-  version = "4.6.0";
+  version = "4.7.2";
 
   goPackagePath = "github.com/keybase/client";
   subPackages = [ "go/keybase" ];
@@ -16,10 +17,18 @@ buildGoPackage rec {
     owner = "keybase";
     repo = "client";
     rev = "v${version}";
-    sha256 = "1aqj5s3vfji1zl7xdzphnsw3b8pnbg22n9rzdxkcdjf7via5wz2k";
+    sha256 = "1ixfq9qv71misg04fvf4892z956w5aydq0r1wk6qk5jjqp6gf4lv";
   };
 
-  buildInputs = lib.optionals stdenv.isDarwin [ AVFoundation AudioToolbox ImageIO CoreMedia Foundation CoreGraphics MediaToolbox ];
+  patches = [
+    (substituteAll {
+      src = ./fix-paths-keybase.patch;
+      gpg = "${gnupg}/bin/gpg";
+      gpg2 = "${gnupg}/bin/gpg2";
+    })
+  ];
+
+  buildInputs = stdenv.lib.optionals stdenv.isDarwin [ AVFoundation AudioToolbox ImageIO CoreMedia Foundation CoreGraphics MediaToolbox ];
   buildFlags = [ "-tags production" ];
 
   meta = with stdenv.lib; {
diff --git a/pkgs/tools/security/keybase/fix-paths-kbfs.patch b/pkgs/tools/security/keybase/fix-paths-kbfs.patch
new file mode 100644
index 00000000000..1180f38b865
--- /dev/null
+++ b/pkgs/tools/security/keybase/fix-paths-kbfs.patch
@@ -0,0 +1,48 @@
+diff --git a/go/kbfs/libfuse/mounter.go b/go/kbfs/libfuse/mounter.go
+index d791ffc2..b116ad5d 100644
+--- a/go/kbfs/libfuse/mounter.go
++++ b/go/kbfs/libfuse/mounter.go
+@@ -108,7 +108,7 @@ func (m *mounter) Unmount() (err error) {
+ 	case "darwin":
+ 		_, err = exec.Command("/sbin/umount", dir).Output()
+ 	case "linux":
+-		fusermountOutput, fusermountErr := exec.Command("fusermount", "-u", dir).CombinedOutput()
++		fusermountOutput, fusermountErr := exec.Command("@fusermount@", "-u", dir).CombinedOutput()
+ 		// Only clean up mountdir on a clean unmount.
+ 		if fusermountErr == nil {
+ 			m.log.Info("Successfully unmounted")
+@@ -135,7 +135,7 @@ func (m *mounter) Unmount() (err error) {
+ 				"/usr/sbin/diskutil", "unmountDisk", "force", dir).Output()
+ 		case "linux":
+ 			// Lazy unmount; will unmount when KBFS is no longer in use.
+-			_, err = exec.Command("fusermount", "-u", "-z", dir).Output()
++			_, err = exec.Command("@fusermount@", "-u", "-z", dir).Output()
+ 		default:
+ 			err = errors.New("Forced unmount is not supported on this platform yet")
+ 		}
+diff --git a/go/vendor/bazil.org/fuse/mount_linux.go b/go/vendor/bazil.org/fuse/mount_linux.go
+index ec7fd89c..4d0a9e30 100644
+--- a/go/vendor/bazil.org/fuse/mount_linux.go
++++ b/go/vendor/bazil.org/fuse/mount_linux.go
+@@ -196,7 +196,7 @@ func mount(dir string, conf *mountConfig, ready chan<- struct{}, _ *error) (fuse
+ 	defer readFile.Close()
+ 
+ 	cmd := exec.Command(
+-		"fusermount",
++		"@fusermount@",
+ 		"-o", conf.getOptions(),
+ 		"--",
+ 		dir,
+diff --git a/go/vendor/bazil.org/fuse/unmount_linux.go b/go/vendor/bazil.org/fuse/unmount_linux.go
+index f02448af..6e4c6c23 100644
+--- a/go/vendor/bazil.org/fuse/unmount_linux.go
++++ b/go/vendor/bazil.org/fuse/unmount_linux.go
+@@ -21,7 +21,7 @@ func unmount(dir string) error {
+ 		return sysunix.Unmount(dir, sysunix.MNT_DETACH)
+ 	}
+ 
+-	cmd := exec.Command("fusermount", "-u", dir)
++	cmd := exec.Command("@fusermount@", "-u", dir)
+ 	output, err := cmd.CombinedOutput()
+ 	if err != nil {
+ 		if len(output) > 0 {
diff --git a/pkgs/tools/security/keybase/fix-paths-keybase.patch b/pkgs/tools/security/keybase/fix-paths-keybase.patch
new file mode 100644
index 00000000000..b3de7bbb530
--- /dev/null
+++ b/pkgs/tools/security/keybase/fix-paths-keybase.patch
@@ -0,0 +1,16 @@
+diff --git a/go/libkb/gpg_cli.go b/go/libkb/gpg_cli.go
+index 3c7c6257..ae8f7e2f 100644
+--- a/go/libkb/gpg_cli.go
++++ b/go/libkb/gpg_cli.go
+@@ -54,9 +54,9 @@ func (g *GpgCLI) Configure(mctx MetaContext) (err error) {
+ 	if len(prog) > 0 {
+ 		err = canExec(prog)
+ 	} else {
+-		prog, err = exec.LookPath("gpg2")
++		prog, err = exec.LookPath("@gpg2@")
+ 		if err != nil {
+-			prog, err = exec.LookPath("gpg")
++			prog, err = exec.LookPath("@gpg@")
+ 		}
+ 	}
+ 	if err != nil {
diff --git a/pkgs/tools/security/keybase/gui.nix b/pkgs/tools/security/keybase/gui.nix
index aa4db75cef1..1d32f1cc881 100644
--- a/pkgs/tools/security/keybase/gui.nix
+++ b/pkgs/tools/security/keybase/gui.nix
@@ -4,16 +4,16 @@
 , runtimeShell, gsettings-desktop-schemas }:
 
 let
-  versionSuffix = "20191010154240.134c2d892b";
+  versionSuffix = "20191028173732.6fc2e969b4";
 in
 
 stdenv.mkDerivation rec {
   pname = "keybase-gui";
-  version = "4.6.0"; # Find latest version from https://prerelease.keybase.io/deb/dists/stable/main/binary-amd64/Packages
+  version = "4.7.2"; # Find latest version from https://prerelease.keybase.io/deb/dists/stable/main/binary-amd64/Packages
 
   src = fetchurl {
     url = "https://s3.amazonaws.com/prerelease.keybase.io/linux_binaries/deb/keybase_${version + "-" + versionSuffix}_amd64.deb";
-    sha256 = "a25f0c676c00d306859d32e4dad7a23dd4955fa0b352be50c281081f2cf000ae";
+    sha256 = "01slhdxcjs1543rz1khxhzn25g26vm9fd9mcyd5ahp2v4g37b8sd";
   };
 
   nativeBuildInputs = [
diff --git a/pkgs/tools/security/keybase/kbfs.nix b/pkgs/tools/security/keybase/kbfs.nix
index 9448182a65a..93c7bd540d8 100644
--- a/pkgs/tools/security/keybase/kbfs.nix
+++ b/pkgs/tools/security/keybase/kbfs.nix
@@ -1,4 +1,4 @@
-{ stdenv, buildGoPackage, fetchFromGitHub, keybase }:
+{ stdenv, substituteAll, buildGoPackage, fetchFromGitHub, fuse, osxfuse, keybase }:
 
 buildGoPackage {
   pname = "kbfs";
@@ -10,6 +10,13 @@ buildGoPackage {
 
   dontRenameImports = true;
 
+  patches = [
+    (substituteAll {
+      src = ./fix-paths-kbfs.patch;
+      fusermount = "${fuse}/bin/fusermount";
+    })
+  ];
+
   buildFlags = [ "-tags production" ];
 
   meta = with stdenv.lib; {
diff --git a/pkgs/tools/security/theharvester/default.nix b/pkgs/tools/security/theharvester/default.nix
index 4a1e92e6104..4153ddafbf4 100644
--- a/pkgs/tools/security/theharvester/default.nix
+++ b/pkgs/tools/security/theharvester/default.nix
@@ -1,40 +1,36 @@
-{ stdenv, fetchFromGitHub, makeWrapper, python3Packages }:
+{ lib, fetchFromGitHub, python3 }:
 
-stdenv.mkDerivation rec {
+python3.pkgs.buildPythonApplication rec {
   pname = "theHarvester";
-  version = "3.0.6";
+  version = "3.1";
 
   src = fetchFromGitHub {
     owner = "laramies";
     repo = pname;
-    rev = version;
-    sha256 = "0f33a7sfb5ih21yp1wspb03fxsls1m14yizgrw0srfirm2a6aa0c";
+    rev = "V${version}";
+    sha256 = "0lxzxfa9wbzim50d2jmd27i57szd0grm1dfayhnym86jn01qpvn3";
   };
 
-  nativeBuildInputs = [ makeWrapper ];
+  propagatedBuildInputs = with python3.pkgs; [ 
+    aiodns beautifulsoup4 dns grequests netaddr
+    plotly pyyaml requests retrying shodan texttable
+  ];
 
-  # add dependencies
-  propagatedBuildInputs = with python3Packages; [ requests beautifulsoup4 plotly ];
+  checkInputs = [ python3.pkgs.pytest ];
 
-  installPhase = ''
-    # create dirs
-    mkdir -p $out/share/${pname} $out/bin
+  checkPhase = "runHook preCheck ; pytest tests/test_myparser.py ; runHook postCheck";
+  # We don't run other tests (discovery modules) because they require network access
 
-    # move project code
-    mv * $out/share/${pname}/
-
-    # make project runnable
-    chmod +x $out/share/${pname}/theHarvester.py
-    ln -s $out/share/${pname}/theHarvester.py $out/bin
-
-    wrapProgram "$out/bin/theHarvester.py" --prefix PYTHONPATH : $out/share/${pname}:$PYTHONPATH
-  '';
-
-  meta = with stdenv.lib; {
+  meta = with lib; {
     description = "Gather E-mails, subdomains and names from different public sources";
+    longDescription = ''
+      theHarvester is a very simple, yet effective tool designed to be used in the early
+      stages of a penetration test. Use it for open source intelligence gathering and
+      helping to determine an entity's external threat landscape on the internet. The tool
+      gathers emails, names, subdomains, IPs, and URLs using multiple public data sources.
+    '';
     homepage = "https://github.com/laramies/theHarvester";
-    platforms = platforms.all;
-    maintainers = with maintainers; [ treemo ];
+    maintainers = with maintainers; [ c0bw3b treemo ];
     license = licenses.gpl2;
   };
 }
diff --git a/pkgs/tools/system/tre-command/default.nix b/pkgs/tools/system/tre-command/default.nix
new file mode 100644
index 00000000000..6050b2a709e
--- /dev/null
+++ b/pkgs/tools/system/tre-command/default.nix
@@ -0,0 +1,24 @@
+{ rustPlatform, fetchFromGitHub, stdenv }:
+
+rustPlatform.buildRustPackage rec {
+  pname = "tre";
+  version = "0.2.2";
+
+  src = fetchFromGitHub {
+    owner = "dduan";
+    repo = "tre";
+    rev = "v${version}";
+    sha256 = "1fazw2wn738iknbv54gv7qll7d4q2gy9bq1s3f3cv21cdv6bqral";
+  };
+
+  cargoSha256 = "0m82zbi610zgvcza6n03xl80g31x6bfkjyrfxcxa6fyf2l5cj9pv";
+  verifyCargoDeps = true;
+
+  meta = with stdenv.lib; {
+    description = "Tree command, improved";
+    homepage = "https://github.com/dduan/tre";
+    license = licenses.mit;
+    maintainers = [ maintainers.dduan ];
+    platforms = platforms.all;
+  };
+}
diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix
index bbb45be3b69..641e7459e0c 100644
--- a/pkgs/top-level/aliases.nix
+++ b/pkgs/top-level/aliases.nix
@@ -209,6 +209,7 @@ mapAliases ({
   man_db = man-db; # added 2016-05
   manpages = man-pages; # added 2015-12-06
   mariadb-client = hiPrio mariadb.client; #added 2019.07.28
+  mess = mame; # added 2019-10-30
   mysql-client = hiPrio mariadb.client;
   memtest86 = memtest86plus; # added 2019-05-08
   mesa_noglu = mesa; # added 2019-05-28
@@ -335,6 +336,7 @@ mapAliases ({
   sapic = throw "deprecated 2019-1-19: sapic is bundled with 'tamarin-prover' now";
   scim = sc-im; # added 2016-01-22
   scollector = bosun; # added 2018-04-25
+  sdlmame = mame; # added 2019-10-30
   shared_mime_info = shared-mime-info; # added 2018-02-25
   skrooge2 = skrooge; # added 2017-02-18
   skype = skypeforlinux; # added 2017-07-27
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 0f482a1e9f7..32433442739 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -1554,6 +1554,8 @@ in
 
   doitlive = callPackage ../tools/misc/doitlive { };
 
+  dokuwiki = callPackage ../servers/web-apps/dokuwiki { };
+
   dosage = callPackage ../applications/graphics/dosage {
     pythonPackages = python3Packages;
   };
@@ -3515,7 +3517,7 @@ in
   gnome-podcasts = callPackage ../applications/audio/gnome-podcasts { };
 
   gnome-photos = callPackage ../applications/graphics/gnome-photos {
-    gegl = gnome3.gegl_0_4;
+    gegl = gegl_0_4;
   };
 
   gnokii = callPackage ../tools/misc/gnokii { };
@@ -3549,6 +3551,8 @@ in
   };
   gnupg = gnupg22;
 
+  gnupg-pkcs11-scd = callPackage ../tools/security/gnupg-pkcs11-scd { };
+
   gnuplot = libsForQt5.callPackage ../tools/graphics/gnuplot { };
 
   gnuplot_qt = gnuplot.override { withQt = true; };
@@ -5672,6 +5676,8 @@ in
 
   polkit_gnome = callPackage ../tools/security/polkit-gnome { };
 
+  poly2tri-c = callPackage ../development/libraries/poly2tri-c { };
+
   polysh = callPackage ../tools/networking/polysh { };
 
   ponysay = callPackage ../tools/misc/ponysay { };
@@ -8523,6 +8529,9 @@ in
   cargo-bloat = callPackage ../development/tools/rust/cargo-bloat { };
   cargo-expand = callPackage ../development/tools/rust/cargo-expand { };
   cargo-fuzz = callPackage ../development/tools/rust/cargo-fuzz { };
+  cargo-geiger = callPackage ../development/tools/rust/cargo-geiger {
+    inherit (darwin.apple_sdk.frameworks) Security;
+  };
   cargo-inspect = callPackage ../development/tools/rust/cargo-inspect {
     inherit (darwin.apple_sdk.frameworks) Security;
   };
@@ -8656,6 +8665,8 @@ in
 
   vlang = callPackage ../development/compilers/vlang { };
 
+  vala-lint = callPackage ../development/tools/vala-lint { };
+
   inherit (callPackage ../development/compilers/vala { })
     vala_0_36
     vala_0_40
@@ -11072,7 +11083,7 @@ in
   };
 
   gegl_0_4 = callPackage ../development/libraries/gegl/4.0.nix {
-    gtk = res.gtk2;
+    inherit (darwin.apple_sdk.frameworks) OpenCL;
   };
 
   geoclue2 = callPackage ../development/libraries/geoclue {};
@@ -13729,6 +13740,8 @@ in
 
   SDL_net = callPackage ../development/libraries/SDL_net { };
 
+  SDL_Pango = callPackage ../development/libraries/SDL_Pango {};
+
   SDL_sound = callPackage ../development/libraries/SDL_sound { };
 
   SDL_stretch= callPackage ../development/libraries/SDL_stretch { };
@@ -15661,6 +15674,8 @@ in
 
   bt-fw-converter = callPackage ../os-specific/linux/firmware/bt-fw-converter { };
 
+  brillo = callPackage ../os-specific/linux/brillo { };
+
   broadcom-bt-firmware = callPackage ../os-specific/linux/firmware/broadcom-bt-firmware { };
 
   batctl = callPackage ../os-specific/linux/batman-adv/batctl.nix { };
@@ -15905,9 +15920,7 @@ in
 
   kmscube = callPackage ../os-specific/linux/kmscube { };
 
-  kmsxx = callPackage ../development/libraries/kmsxx {
-    stdenv = gcc6Stdenv;
-  };
+  kmsxx = callPackage ../development/libraries/kmsxx { };
 
   latencytop = callPackage ../os-specific/linux/latencytop { };
 
@@ -16124,6 +16137,8 @@ in
 
     deepin-anything = callPackage ../os-specific/linux/deepin-anything { };
 
+    digimend = callPackage ../os-specific/linux/digimend { };
+
     dpdk = callPackage ../os-specific/linux/dpdk { };
 
     exfat-nofuse = callPackage ../os-specific/linux/exfat { };
@@ -18274,6 +18289,7 @@ in
 
   emacs = emacs26;
   emacsPackages = emacs26Packages;
+  emacs-nox = emacs26-nox;
 
   emacs26 = callPackage ../applications/editors/emacs {
     # use override to enable additional features
@@ -18413,6 +18429,8 @@ in
 
   keepass-keepassrpc = callPackage ../applications/misc/keepass-plugins/keepassrpc { };
 
+  keepass-otpkeyprov = callPackage ../applications/misc/keepass-plugins/otpkeyprov { };
+
   exrdisplay = callPackage ../applications/graphics/exrdisplay { };
 
   exrtools = callPackage ../applications/graphics/exrtools { };
@@ -21296,6 +21314,8 @@ in
 
   tdrop = callPackage ../applications/misc/tdrop { };
 
+  tre-command = callPackage ../tools/system/tre-command {};
+
   tree = callPackage ../tools/system/tree {};
 
   treesheets = callPackage ../applications/office/treesheets { wxGTK = wxGTK31; };
@@ -21662,34 +21682,64 @@ in
     in with libretro;
       ([ ]
       ++ optional (cfg.enable4do or false) _4do
+      ++ optional (cfg.enableAtari800 or false) atari800
+      ++ optional (cfg.enableBeetleGBA or false) beetle-gba
+      ++ optional (cfg.enableBeetleLynx or false) beetle-lynx
+      ++ optional (cfg.enableBeetleNGP or false) beetle-ngp
       ++ optional (cfg.enableBeetlePCEFast or false) beetle-pce-fast
+      ++ optional (cfg.enableBeetlePCFX or false) beetle-pcfx
       ++ optional (cfg.enableBeetlePSX or false) beetle-psx
       ++ optional (cfg.enableBeetleSaturn or false) beetle-saturn
+      ++ optional (cfg.enableBeetleSNES or false) beetle-snes
+      ++ optional (cfg.enableBeetleSuperGrafx or false) beetle-supergrafx
+      ++ optional (cfg.enableBeetleWswan or false) beetle-wswan
+      ++ optional (cfg.enableBeetleVB or false) beetle-vb
+      ++ optional (cfg.enableBlueMSX or false) bluemsx
       ++ optional (cfg.enableBsnesMercury or false) bsnes-mercury
+      ++ optional (cfg.enableDOSBox or false) dosbox
       ++ optional (cfg.enableDesmume or false) desmume
+      ++ optional (cfg.enableDesmume2015 or false) desmume2015
       ++ optional (cfg.enableDolphin or false) dolphin
       ++ optional (cfg.enableFBA or false) fba
       ++ optional (cfg.enableFceumm or false) fceumm
+      ++ optional (cfg.enableFlycast or false) flycast
       ++ optional (cfg.enableGambatte or false) gambatte
       ++ optional (cfg.enableGenesisPlusGX or false) genesis-plus-gx
+      ++ optional (cfg.enableGpsp or false) gpsp
+      ++ optional (cfg.enableHandy or false) handy
+      ++ optional (cfg.enableHatari or false) hatari
       ++ optional (cfg.enableHiganSFC or false) higan-sfc
       ++ optional (cfg.enableMAME or false) mame
+      ++ optional (cfg.enableMAME2000 or false) mame2000
+      ++ optional (cfg.enableMAME2003 or false) mame2003
+      ++ optional (cfg.enableMAME2003Plus or false) mame2003-plus
+      ++ optional (cfg.enableMAME2010 or false) mame2010
+      ++ optional (cfg.enableMAME2015 or false) mame2015
+      ++ optional (cfg.enableMAME2016 or false) mame2016
+      ++ optional (cfg.enableMesen or false) mesen
       ++ optional (cfg.enableMGBA or false) mgba
       ++ optional (cfg.enableMupen64Plus or false) mupen64plus
       ++ optional (cfg.enableNestopia or false) nestopia
+      ++ optional (cfg.enableO2EM or false) o2em
       ++ optional (cfg.enableParallelN64 or false) parallel-n64
+      ++ optional (cfg.enablePCSXRearmed or false) pcsx_rearmed
       ++ optional (cfg.enablePicodrive or false) picodrive
-      ++ optional (cfg.enablePrboom or false) prboom
+      ++ optional (cfg.enablePlay or false) play
       ++ optional (cfg.enablePPSSPP or false) ppsspp
+      ++ optional (cfg.enablePrboom or false) prboom
+      ++ optional (cfg.enableProSystem or false) prosystem
       ++ optional (cfg.enableQuickNES or false) quicknes
-      ++ optional (cfg.enableReicast or false) reicast
       ++ optional (cfg.enableScummVM or false) scummvm
       ++ optional (cfg.enableSnes9x or false) snes9x
-      ++ optional (cfg.enableSnes9xNext or false) snes9x-next
+      ++ optional (cfg.enableSnes9x2002 or false) snes9x2002
+      ++ optional (cfg.enableSnes9x2005 or false) snes9x2005
+      ++ optional (cfg.enableSnes9x2010 or false) snes9x2010
       ++ optional (cfg.enableStella or false) stella
       ++ optional (cfg.enableVbaNext or false) vba-next
       ++ optional (cfg.enableVbaM or false) vba-m
-
+      ++ optional (cfg.enableVecx or false) vecx
+      ++ optional (cfg.enableVirtualJaguar or false) virtualjaguar
+      ++ optional (cfg.enableYabause or false) yabause
       # added on 2017-02-25 due #23163
       ++ optional (cfg.enableMednafenPCEFast or false)
           (throw "nix config option enableMednafenPCEFast has been renamed to enableBeetlePCEFast")
@@ -22430,6 +22480,8 @@ in
 
   frogatto = callPackage ../games/frogatto { };
 
+  frozen-bubble = callPackage ../games/frozen-bubble { };
+
   fsg = callPackage ../games/fsg {
     wxGTK = wxGTK28.override { unicode = false; };
   };
@@ -22768,8 +22820,6 @@ in
 
   scrolls = callPackage ../games/scrolls { };
 
-  sdlmame = callPackage ../games/sdlmame { };
-
   service-wrapper = callPackage ../os-specific/linux/service-wrapper { };
 
   sgtpuzzles = callPackage (callPackage ../games/sgt-puzzles) { };
@@ -23079,6 +23129,7 @@ in
     icon-hider = callPackage ../desktops/gnome-3/extensions/icon-hider { };
     impatience = callPackage ../desktops/gnome-3/extensions/impatience.nix { };
     mpris-indicator-button = callPackage ../desktops/gnome-3/extensions/mpris-indicator-button { };
+    night-theme-switcher = callPackage ../desktops/gnome-3/extensions/night-theme-switcher { };
     no-title-bar = callPackage ../desktops/gnome-3/extensions/no-title-bar { };
     pidgin-im-integration = callPackage ../desktops/gnome-3/extensions/pidgin-im-integration { };
     remove-dropdown-arrows = callPackage ../desktops/gnome-3/extensions/remove-dropdown-arrows { };
@@ -23264,6 +23315,8 @@ in
 
   dcm2niix = callPackage ../applications/science/biology/dcm2niix { };
 
+  deeptools = callPackage ../applications/science/biology/deeptools { python = python3; };
+
   delly = callPackage ../applications/science/biology/delly { };
 
   diamond = callPackage ../applications/science/biology/diamond { };
@@ -24338,11 +24391,9 @@ in
     icu = icu58;
   };
 
-  martyr = callPackage ../development/libraries/martyr { };
+  mame = libsForQt5.callPackage ../misc/emulators/mame { };
 
-  mess = callPackage ../misc/emulators/mess {
-    inherit (pkgs.gnome2) GConf;
-  };
+  martyr = callPackage ../development/libraries/martyr { };
 
   moltengamepad = callPackage ../misc/drivers/moltengamepad { };
 
@@ -24532,7 +24583,8 @@ in
 
   nix-prefetch = callPackage ../tools/package-management/nix-prefetch { };
 
-  nix-prefetch-github = callPackage ../build-support/nix-prefetch-github {};
+  nix-prefetch-github = with python3Packages;
+    toPythonApplication nix-prefetch-github;
 
   inherit (callPackages ../tools/package-management/nix-prefetch-scripts { })
     nix-prefetch-bzr
diff --git a/pkgs/top-level/perl-packages.nix b/pkgs/top-level/perl-packages.nix
index 61822351ee2..344ab71c0a8 100644
--- a/pkgs/top-level/perl-packages.nix
+++ b/pkgs/top-level/perl-packages.nix
@@ -209,6 +209,27 @@ let
      };
   };
 
+  AlienSDL = buildPerlModule {
+    pname = "Alien-SDL";
+    version = "1.446";
+    src = fetchurl {
+      url = "mirror://cpan/authors/id/F/FR/FROGGS/Alien-SDL-1.446.tar.gz";
+      sha256 = "c9aa2c9dc3c63d89773c7d7203f2a46d1b924d0c72d9f801af147a3dc8bc512a";
+    };
+    patches = [ ../development/perl-modules/alien-sdl.patch ];
+
+    installPhase = "./Build install --prefix $out";
+
+    SDL_INST_DIR = pkgs.SDL.dev;
+    buildInputs = [ ArchiveExtract ArchiveZip TextPatch pkgs.SDL ];
+    propagatedBuildInputs = [ CaptureTiny FileShareDir FileWhich ];
+
+    meta = {
+      description = "Get, Build and Use SDL libraries";
+      license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
+    };
+  };
+
   AlienTidyp = buildPerlModule {
     pname = "Alien-Tidyp";
     version = "1.4.7";
@@ -11678,10 +11699,10 @@ let
 
   MojoSQLite = buildPerlModule {
     pname = "Mojo-SQLite";
-    version = "3.002";
+    version = "3.003";
     src = fetchurl {
-      url = "mirror://cpan/authors/id/D/DB/DBOOK/Mojo-SQLite-3.002.tar.gz";
-      sha256 = "16dn0p14i6r4c8aspvkp7rfry3zy7kr2ffcmncj0pqygk62miinp";
+      url = "mirror://cpan/authors/id/D/DB/DBOOK/Mojo-SQLite-3.003.tar.gz";
+      sha256 = "d96c00dcf45e2becc8e8181df074853d42616f2a660703455d0e0a2741478092";
     };
     buildInputs = [ ModuleBuildTiny ];
     propagatedBuildInputs = [ DBDSQLite Mojolicious SQLAbstract URIdb ];
@@ -15415,6 +15436,24 @@ let
     };
   };
 
+  SDL = buildPerlModule {
+    pname = "SDL";
+    version = "2.548";
+    src = fetchurl {
+      url = "mirror://cpan/authors/id/F/FR/FROGGS/SDL-2.548.tar.gz";
+      sha256 = "252a192bfa9c2070a4883707d139c3a45d9c4518ccd66a1e699b5b7959bd4fb5";
+    };
+    perlPreHook = "export LD=$CC";
+    preCheck = "rm t/core_audiospec.t";
+    buildInputs = [ AlienSDL CaptureTiny TestDeep TestDifferences TestException TestMost TestWarn ]
+      ++ (with pkgs; [ SDL SDL_gfx SDL_mixer SDL_image SDL_ttf SDL_Pango SDL_net ] );
+    propagatedBuildInputs = [ FileShareDir TieSimple ];
+    meta = {
+      description = "SDL bindings to Perl";
+      license = stdenv.lib.licenses.lgpl21Plus;
+    };
+  };
+
   SerealDecoder = buildPerlPackage {
     pname = "Sereal-Decoder";
     version = "4.007";
@@ -18667,6 +18706,20 @@ let
     };
   };
 
+  TextPatch = buildPerlPackage {
+    pname = "Text-Patch";
+    version = "1.8";
+    src = fetchurl {
+      url = "mirror://cpan/authors/id/C/CA/CADE/Text-Patch-1.8.tar.gz";
+      sha256 = "eaf18e61ba6a3e143846a7cc66f08ce58a0c4fbda92acb31aede25cb3b5c3dcc";
+    };
+    propagatedBuildInputs = [ TextDiff ];
+    meta = {
+      description = "Patches text with given patch";
+      license = stdenv.lib.licenses.gpl2;
+    };
+  };
+
   TextPDF = buildPerlPackage {
     pname = "Text-PDF";
     version = "0.31";
@@ -19122,6 +19175,19 @@ let
     };
   };
 
+  TieSimple = buildPerlPackage {
+    pname = "Tie-Simple";
+    version = "1.04";
+    src = fetchurl {
+      url = "mirror://cpan/authors/id/H/HA/HANENKAMP/Tie-Simple-1.04.tar.gz";
+      sha256 = "29e9e2133951046c78f205f1b3e8df62c90e114f0e08fa06b817766a0f808b12";
+    };
+    meta = {
+      description = "Variable ties made much easier: much, much, much easier..";
+      license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
+    };
+  };
+
   TieSub = buildPerlPackage {
      pname = "Tie-Sub";
      version = "1.001";
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index 8fbe53f7904..1c38b47576a 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -521,6 +521,8 @@ in {
 
   deap = callPackage ../development/python-modules/deap { };
 
+  deeptoolsintervals = callPackage ../development/python-modules/deeptoolsintervals { };
+
   dkimpy = callPackage ../development/python-modules/dkimpy { };
 
   dictionaries = callPackage ../development/python-modules/dictionaries { };
@@ -3893,6 +3895,8 @@ in {
 
   moderngl = callPackage ../development/python-modules/moderngl { };
 
+  moderngl-window = callPackage ../development/python-modules/moderngl_window { };
+
   modestmaps = callPackage ../development/python-modules/modestmaps { };
 
   # Needed here because moinmoin is loaded as a Python library.
@@ -4318,12 +4322,13 @@ in {
 
   kmapper = callPackage ../development/python-modules/kmapper { };
 
-  kmsxx = (callPackage ../development/libraries/kmsxx {
+  kmsxx = toPythonModule ((callPackage ../development/libraries/kmsxx {
     inherit (pkgs.kmsxx) stdenv;
     inherit (pkgs) pkgconfig;
+    withPython = true;
   }).overrideAttrs (oldAttrs: {
     name = "${python.libPrefix}-${pkgs.kmsxx.name}";
-  });
+  }));
 
   precis-i18n = callPackage ../development/python-modules/precis-i18n { };
 
@@ -4445,6 +4450,10 @@ in {
 
   pybfd = callPackage ../development/python-modules/pybfd { };
 
+  pybigwig = callPackage ../development/python-modules/pybigwig { };
+
+  py2bit = callPackage ../development/python-modules/py2bit { };
+
   pyblock = callPackage ../development/python-modules/pyblock { };
 
   pyblosxom = callPackage ../development/python-modules/pyblosxom { };