From f361930a29379da7dce18daf9e9d291f741e577c Mon Sep 17 00:00:00 2001 From: Alexander Sosedkin Date: Sat, 6 Jul 2024 20:40:26 +0200 Subject: [PATCH] WIP: okc-gpg ...can't make okc-ssh-agent work even on Termux... --- .github/workflows/emulator.yml | 11 +- modules/environment/android-integration.nix | 20 +- pkgs/android-integration/okc-agents/Cargo.nix | 2670 +++++++++++++++++ .../okc-agents/default.nix | 23 + tests/emulator/okc_agents.py | 96 + .../on-device/config-android-integration.nix | 1 + 6 files changed, 2815 insertions(+), 6 deletions(-) create mode 100644 pkgs/android-integration/okc-agents/Cargo.nix create mode 100644 pkgs/android-integration/okc-agents/default.nix create mode 100644 tests/emulator/okc_agents.py diff --git a/.github/workflows/emulator.yml b/.github/workflows/emulator.yml index 490c17ed..1939ef97 100644 --- a/.github/workflows/emulator.yml +++ b/.github/workflows/emulator.yml @@ -109,11 +109,12 @@ jobs: # 34: sometimes work, but doesn't seem stable, even w/o caching images script: - android_integration - - bootstrap_flakes - - bootstrap_channels - - poke_around - - test_channels_uiautomator - - test_channels_shell + # bootstrap_flakes + # bootstrap_channels + - okc_agents + # poke_around + # test_channels_uiautomator + # test_channels_shell steps: - name: Checkout repository diff --git a/modules/environment/android-integration.nix b/modules/environment/android-integration.nix index c8ba13e9..5bf18c2b 100644 --- a/modules/environment/android-integration.nix +++ b/modules/environment/android-integration.nix @@ -1,6 +1,6 @@ # Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, nixpkgs, ... }: let cfg = config.android-integration; @@ -11,6 +11,10 @@ let pkgs.callPackage (import ../../pkgs/android-integration/termux-tools.nix) { inherit termux-am; }; + okc-agents = + import (../../pkgs/android-integration/okc-agents) { + inherit nixpkgs pkgs termux-am; + }; in { @@ -103,6 +107,17 @@ in ''; }; + okc-gpg.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provides a GPG agent for OpenKeychain, + courtesy of https://github.com/DDoSolitary/okc-agents. + This lets you use PGP keys stored on hardware tokens, like Yubikeys. + ''; + }; + unsupported.enable = lib.mkOption { type = lib.types.bool; default = false; @@ -110,6 +125,7 @@ in description = lib.mdDoc '' Provide several more unsupported and untested commands. For testing and for brave souls only. + Currently provides `termux-backup` and `okc-ssh-agent`. ''; }; @@ -127,6 +143,8 @@ in (ifD cfg.termux-wake-lock.enable termux-tools.wake_lock) ++ (ifD cfg.termux-wake-unlock.enable termux-tools.wake_unlock) ++ (ifD cfg.xdg-open.enable termux-tools.xdg_open) ++ + (ifD cfg.okc-gpg.enable okc-agents.okc_gpg) ++ + (ifD cfg.unsupported.enable okc-agents.out) ++ (ifD cfg.unsupported.enable termux-tools.out); }; } diff --git a/pkgs/android-integration/okc-agents/Cargo.nix b/pkgs/android-integration/okc-agents/Cargo.nix new file mode 100644 index 00000000..df9cca70 --- /dev/null +++ b/pkgs/android-integration/okc-agents/Cargo.nix @@ -0,0 +1,2670 @@ +# This file was @generated by crate2nix 0.14.1 with the command: +# crate2nix generate -f ~/code/okc-agents/Cargo.toml -o okc-agents.nix +# formatted with nix fmt, +# and then manually specifying +# src = pkgs.fetchFromGitHub { ... } +# for okc-agents. +# See https://github.com/kolloch/crate2nix for more info. + +{ nixpkgs ? +, pkgs ? import nixpkgs { config = { }; } +, lib ? pkgs.lib +, stdenv ? pkgs.stdenv +, buildRustCrateForPkgs ? pkgs: pkgs.buildRustCrate + # This is used as the `crateOverrides` argument for `buildRustCrate`. +, defaultCrateOverrides ? pkgs.defaultCrateOverrides + # The features to enable for the root_crate or the workspace_members. +, rootFeatures ? [ "default" ] + # If true, throw errors instead of issueing deprecation warnings. +, strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). + # Used for conditional compilation based on CPU feature detection. +, targetFeatures ? [ ] + # Whether to perform release builds: longer compile times, faster binaries. +, release ? true + # Additional crate2nix configuration if it exists. +, crateConfig ? if builtins.pathExists ./crate-config.nix + then pkgs.callPackage ./crate-config.nix { } + else { } +}: + +rec { + # + # "public" attributes that we attempt to keep stable with new versions of crate2nix. + # + + rootCrate = rec { + packageId = "okc-agents"; + + # Use this attribute to refer to the derivation building your root crate package. + # You can override the features with rootCrate.build.override { features = [ "default" "feature1" ... ]; }. + build = internal.buildRustCrateWithFeatures { + inherit packageId; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + # Refer your crate build derivation by name here. + # You can override the features with + # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. + workspaceMembers = { + "okc-agents" = rec { + packageId = "okc-agents"; + build = internal.buildRustCrateWithFeatures { + packageId = "okc-agents"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + }; + + # A derivation that joins the outputs of all workspace members together. + allWorkspaceMembers = pkgs.symlinkJoin { + name = "all-workspace-members"; + paths = + let members = builtins.attrValues workspaceMembers; + in builtins.map (m: m.build) members; + }; + + # + # "internal" ("private") attributes that may change in every new version of crate2nix. + # + + internal = rec { + # Build and dependency information for crates. + # Many of the fields are passed one-to-one to buildRustCrate. + # + # Noteworthy: + # * `dependencies`/`buildDependencies`: similar to the corresponding fields for buildRustCrate. + # but with additional information which is used during dependency/feature resolution. + # * `resolvedDependencies`: the selected default features reported by cargo - only included for debugging. + # * `devDependencies` as of now not used by `buildRustCrate` but used to + # inject test dependencies into the build + + crates = { + "aho-corasick" = rec { + crateName = "aho-corasick"; + version = "0.7.18"; + edition = "2018"; + sha256 = "0vv50b3nvkhyy7x7ip19qnsq11bqlnffkmj2yx2xlyk5wzawydqy"; + libName = "aho_corasick"; + authors = [ + "Andrew Gallant " + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "memchr/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "ansi_term" = rec { + crateName = "ansi_term"; + version = "0.11.0"; + edition = "2015"; + sha256 = "16wpvrghvd0353584i1idnsgm0r3vchg8fyrm0x8ayv1rgvbljgf"; + authors = [ + "ogham@bsago.me" + "Ryan Scheel (Havvy) " + "Josh Triplett " + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: ("windows" == target."os" or null); + features = [ "errhandlingapi" "consoleapi" "processenv" ]; + } + ]; + + }; + "arc-swap" = rec { + crateName = "arc-swap"; + version = "1.4.0"; + edition = "2018"; + sha256 = "0qzczn3grbwla2aax1jnmww39bqqy2wfr311wl63cc2qbkpmmpz6"; + authors = [ + "Michal 'vorner' Vaner " + ]; + features = { }; + }; + "atty" = rec { + crateName = "atty"; + version = "0.2.14"; + edition = "2015"; + sha256 = "1s7yslcs6a28c5vz7jwj63lkfgyx8mx99fdirlhi9lbhhzhrpcyr"; + authors = [ + "softprops " + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi"; + target = { target, features }: ("hermit" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "consoleapi" "processenv" "minwinbase" "minwindef" "winbase" ]; + } + ]; + + }; + "autocfg" = rec { + crateName = "autocfg"; + version = "1.0.1"; + edition = "2015"; + sha256 = "0jj6i9zn4gjl03kjvziqdji6rwx8ykz8zk2ngpc331z2g3fk3c6d"; + authors = [ + "Josh Stone " + ]; + + }; + "base64" = rec { + crateName = "base64"; + version = "0.13.0"; + edition = "2018"; + sha256 = "1z82g23mbzjgijkpcrilc7nljpxpvpf7zxf6iyiapkgka2ngwkch"; + authors = [ + "Alice Maz " + "Marshall Pierce " + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "bitflags" = rec { + crateName = "bitflags"; + version = "1.3.2"; + edition = "2018"; + sha256 = "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "bytes" = rec { + crateName = "bytes"; + version = "1.1.0"; + edition = "2018"; + sha256 = "1y70b249m02lfp0j6565b29kviapj4xsl9whamcqwddnp9kjv1y4"; + authors = [ + "Carl Lerche " + "Sean McArthur " + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "cfg-if" = rec { + crateName = "cfg-if"; + version = "1.0.0"; + edition = "2018"; + sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + authors = [ + "Alex Crichton " + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "chrono" = rec { + crateName = "chrono"; + version = "0.4.19"; + edition = "2015"; + sha256 = "0wyfl6c00vhfl562spnfcna3zkw8jqvcp652m9iskhl8j26dc2k7"; + authors = [ + "Kang Seonghoon " + "Brandon W Maister " + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + optional = true; + } + { + name = "num-integer"; + packageId = "num-integer"; + usesDefaultFeatures = false; + } + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "time"; + packageId = "time"; + optional = true; + } + { + name = "winapi"; + packageId = "winapi"; + optional = true; + target = { target, features }: (target."windows" or false); + features = [ "std" "minwinbase" "minwindef" "timezoneapi" ]; + } + ]; + features = { + "clock" = [ "libc" "std" "winapi" ]; + "default" = [ "clock" "std" "oldtime" ]; + "js-sys" = [ "dep:js-sys" ]; + "libc" = [ "dep:libc" ]; + "oldtime" = [ "time" ]; + "pure-rust-locales" = [ "dep:pure-rust-locales" ]; + "rustc-serialize" = [ "dep:rustc-serialize" ]; + "serde" = [ "dep:serde" ]; + "time" = [ "dep:time" ]; + "unstable-locales" = [ "pure-rust-locales" "alloc" ]; + "wasm-bindgen" = [ "dep:wasm-bindgen" ]; + "wasmbind" = [ "wasm-bindgen" "js-sys" ]; + "winapi" = [ "dep:winapi" ]; + }; + resolvedDefaultFeatures = [ "clock" "default" "libc" "oldtime" "std" "time" "winapi" ]; + }; + "clap" = rec { + crateName = "clap"; + version = "2.33.3"; + edition = "2015"; + sha256 = "00i065a58987k1sbzqmlz721rw521zcg08jmsh40gi3khp3qmr9p"; + authors = [ + "Kevin K. " + ]; + dependencies = [ + { + name = "ansi_term"; + packageId = "ansi_term"; + optional = true; + target = { target, features }: (!(target."windows" or false)); + } + { + name = "atty"; + packageId = "atty"; + optional = true; + } + { + name = "bitflags"; + packageId = "bitflags"; + } + { + name = "strsim"; + packageId = "strsim"; + optional = true; + } + { + name = "textwrap"; + packageId = "textwrap"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + } + { + name = "vec_map"; + packageId = "vec_map"; + optional = true; + } + ]; + features = { + "ansi_term" = [ "dep:ansi_term" ]; + "atty" = [ "dep:atty" ]; + "clippy" = [ "dep:clippy" ]; + "color" = [ "ansi_term" "atty" ]; + "default" = [ "suggestions" "color" "vec_map" ]; + "doc" = [ "yaml" ]; + "lints" = [ "clippy" ]; + "strsim" = [ "dep:strsim" ]; + "suggestions" = [ "strsim" ]; + "term_size" = [ "dep:term_size" ]; + "vec_map" = [ "dep:vec_map" ]; + "wrap_help" = [ "term_size" "textwrap/term_size" ]; + "yaml" = [ "yaml-rust" ]; + "yaml-rust" = [ "dep:yaml-rust" ]; + }; + resolvedDefaultFeatures = [ "ansi_term" "atty" "color" "default" "strsim" "suggestions" "vec_map" ]; + }; + "crossbeam-channel" = rec { + crateName = "crossbeam-channel"; + version = "0.5.1"; + edition = "2018"; + sha256 = "1d1dnp61g51gnmc45cb4vpjsr5n62wz22an2y3q6avgifzhjgv86"; + authors = [ + "The Crossbeam Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "crossbeam-utils" = [ "dep:crossbeam-utils" ]; + "default" = [ "std" ]; + "std" = [ "crossbeam-utils/std" ]; + }; + resolvedDefaultFeatures = [ "crossbeam-utils" "default" "std" ]; + }; + "crossbeam-utils" = rec { + crateName = "crossbeam-utils"; + version = "0.8.5"; + edition = "2018"; + sha256 = "1ny481cx8a5pdknypb41jqym03dl8x26i2ldyyp3yb3zrq8zqb6q"; + authors = [ + "The Crossbeam Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "lazy_static"; + packageId = "lazy_static"; + optional = true; + } + ]; + features = { + "default" = [ "std" ]; + "lazy_static" = [ "dep:lazy_static" ]; + "loom" = [ "dep:loom" ]; + "std" = [ "lazy_static" ]; + }; + resolvedDefaultFeatures = [ "lazy_static" "std" ]; + }; + "dirs-next" = rec { + crateName = "dirs-next"; + version = "2.0.0"; + edition = "2018"; + sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + authors = [ + "The @xdg-rs members" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "dirs-sys-next"; + packageId = "dirs-sys-next"; + } + ]; + + }; + "dirs-sys-next" = rec { + crateName = "dirs-sys-next"; + version = "0.1.2"; + edition = "2018"; + sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + authors = [ + "The @xdg-rs members" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "redox_users"; + packageId = "redox_users"; + usesDefaultFeatures = false; + target = { target, features }: ("redox" == target."os" or null); + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "knownfolders" "objbase" "shlobj" "winbase" "winerror" ]; + } + ]; + + }; + "futures-core" = rec { + crateName = "futures-core"; + version = "0.3.17"; + edition = "2018"; + sha256 = "0gd5hfxcy5fqc3wm55a4yhcbh921wvzv09nkbhwh6dpjaxlw5lc8"; + authors = [ + "Alex Crichton " + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures-macro" = rec { + crateName = "futures-macro"; + version = "0.3.17"; + edition = "2018"; + sha256 = "1fvriw31ippggp8496dpbvkykr2fgk57amhwrz5lqjzabjws9r0q"; + procMacro = true; + authors = [ + "Taylor Cramer " + "Taiki Endo " + ]; + dependencies = [ + { + name = "proc-macro-hack"; + packageId = "proc-macro-hack"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn"; + features = [ "full" ]; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + + }; + "futures-task" = rec { + crateName = "futures-task"; + version = "0.3.17"; + edition = "2018"; + sha256 = "169fi44d8sbfpkkyhncj0pgkp1amrllg5523lncf8wyvxps00g8x"; + authors = [ + "Alex Crichton " + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "futures-util" = rec { + crateName = "futures-util"; + version = "0.3.17"; + edition = "2018"; + sha256 = "10al5ci74s6rk2d2wqqya0d4fwc6sqv525hzbvj6wfha45jq8min"; + authors = [ + "Alex Crichton " + ]; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-macro"; + packageId = "futures-macro"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "proc-macro-hack"; + packageId = "proc-macro-hack"; + optional = true; + } + { + name = "proc-macro-nested"; + packageId = "proc-macro-nested"; + optional = true; + } + { + name = "slab"; + packageId = "slab"; + optional = true; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" "futures-task/alloc" ]; + "async-await-macro" = [ "async-await" "futures-macro" "proc-macro-hack" "proc-macro-nested" ]; + "channel" = [ "std" "futures-channel" ]; + "compat" = [ "std" "futures_01" ]; + "default" = [ "std" "async-await" "async-await-macro" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-io" = [ "dep:futures-io" ]; + "futures-macro" = [ "dep:futures-macro" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "futures_01" = [ "dep:futures_01" ]; + "io" = [ "std" "futures-io" "memchr" ]; + "io-compat" = [ "io" "compat" "tokio-io" ]; + "memchr" = [ "dep:memchr" ]; + "proc-macro-hack" = [ "dep:proc-macro-hack" ]; + "proc-macro-nested" = [ "dep:proc-macro-nested" ]; + "read-initializer" = [ "io" "futures-io/read-initializer" "futures-io/unstable" ]; + "sink" = [ "futures-sink" ]; + "slab" = [ "dep:slab" ]; + "std" = [ "alloc" "futures-core/std" "futures-task/std" "slab" ]; + "tokio-io" = [ "dep:tokio-io" ]; + "unstable" = [ "futures-core/unstable" "futures-task/unstable" ]; + "write-all-vectored" = [ "io" ]; + }; + resolvedDefaultFeatures = [ "alloc" "async-await" "async-await-macro" "default" "futures-macro" "proc-macro-hack" "proc-macro-nested" "slab" "std" ]; + }; + "getrandom" = rec { + crateName = "getrandom"; + version = "0.2.3"; + edition = "2018"; + sha256 = "0lr7mnkvnzdh1xxmwmhhbm4gwg29k3m2rzhpjmjm4k2jcfa9kkbz"; + authors = [ + "The Rand Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + target = { target, features }: ("wasi" == target."os" or null); + } + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "js" = [ "wasm-bindgen" "js-sys" ]; + "js-sys" = [ "dep:js-sys" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "libc/rustc-dep-of-std" "wasi/rustc-dep-of-std" ]; + "wasm-bindgen" = [ "dep:wasm-bindgen" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "hermit-abi" = rec { + crateName = "hermit-abi"; + version = "0.1.19"; + edition = "2018"; + sha256 = "0cxcm8093nf5fyn114w8vxbrbcyvv91d4015rdnlgfll7cs6gd32"; + authors = [ + "Stefan Lankes" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + } + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins/rustc-dep-of-std" "libc/rustc-dep-of-std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "instant" = rec { + crateName = "instant"; + version = "0.1.11"; + edition = "2018"; + sha256 = "1g8n89lahcaj5ris8f4ki3x7cfscbwwkbmpfs17s7ijsyf4ksvbi"; + authors = [ + "sebcrozet " + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + ]; + features = { + "js-sys" = [ "dep:js-sys" ]; + "now" = [ "time" ]; + "stdweb" = [ "dep:stdweb" ]; + "time" = [ "dep:time" ]; + "wasm-bindgen" = [ "js-sys" "wasm-bindgen_rs" "web-sys" ]; + "wasm-bindgen_rs" = [ "dep:wasm-bindgen_rs" ]; + "web-sys" = [ "dep:web-sys" ]; + }; + }; + "lazy_static" = rec { + crateName = "lazy_static"; + version = "1.4.0"; + edition = "2015"; + sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + authors = [ + "Marvin Löbel " + ]; + features = { + "spin" = [ "dep:spin" ]; + "spin_no_std" = [ "spin" ]; + }; + }; + "libc" = rec { + crateName = "libc"; + version = "0.2.103"; + edition = "2015"; + sha256 = "1xpd65rnpdniyj565zvyn9pqr29vsrah1vr1yda76qksl5ap53yx"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "align" "rustc-std-workspace-core" ]; + "rustc-std-workspace-core" = [ "dep:rustc-std-workspace-core" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "lock_api" = rec { + crateName = "lock_api"; + version = "0.4.5"; + edition = "2018"; + sha256 = "028izfyraynijd9h9x5miv1vmg6sjnw1v95wgm7f4xlr7h4lsaki"; + authors = [ + "Amanieu d'Antras " + ]; + dependencies = [ + { + name = "scopeguard"; + packageId = "scopeguard"; + usesDefaultFeatures = false; + } + ]; + features = { + "owning_ref" = [ "dep:owning_ref" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "log" = rec { + crateName = "log"; + version = "0.4.14"; + edition = "2015"; + sha256 = "04175hv0v62shd82qydq58a48k3bjijmk54v38zgqlbxqkkbpfai"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + ]; + features = { + "kv_unstable" = [ "value-bag" ]; + "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; + "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; + "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" ]; + "serde" = [ "dep:serde" ]; + "sval" = [ "dep:sval" ]; + "value-bag" = [ "dep:value-bag" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "memchr" = rec { + crateName = "memchr"; + version = "2.4.1"; + edition = "2018"; + sha256 = "0smq8xzd40njqpfzv5mghigj91fzlfrfg842iz8x0wqvw2dw731h"; + authors = [ + "Andrew Gallant " + "bluss" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "libc" = [ "dep:libc" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "mio" = rec { + crateName = "mio"; + version = "0.7.13"; + edition = "2018"; + sha256 = "05mvlrn3r2vqps4fflmknw15r0rs8xld4g99sdf8647c2iixnawc"; + authors = [ + "Carl Lerche " + "Thomas de Zeeuw " + "Tokio Contributors " + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "log"; + packageId = "log"; + } + { + name = "miow"; + packageId = "miow"; + target = { target, features }: (target."windows" or false); + } + { + name = "ntapi"; + packageId = "ntapi"; + target = { target, features }: (target."windows" or false); + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "winsock2" "mswsock" "mstcpip" ]; + } + ]; + features = { + "os-ext" = [ "os-poll" ]; + "os-util" = [ "os-ext" ]; + "pipe" = [ "os-ext" ]; + "tcp" = [ "net" ]; + "udp" = [ "net" ]; + "uds" = [ "net" ]; + }; + resolvedDefaultFeatures = [ "default" "net" "os-ext" "os-poll" "os-util" "tcp" "udp" "uds" ]; + }; + "miow" = rec { + crateName = "miow"; + version = "0.3.7"; + edition = "2018"; + sha256 = "08afp2xfpxmdw003111lxz6g9jgbj4zi2fpldvv7da6d4nqcbwdr"; + authors = [ + "Alex Crichton " + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + features = [ "std" "fileapi" "handleapi" "ioapiset" "minwindef" "namedpipeapi" "ntdef" "synchapi" "winerror" "winsock2" "ws2def" "ws2ipdef" ]; + } + ]; + + }; + "ntapi" = rec { + crateName = "ntapi"; + version = "0.3.6"; + edition = "2018"; + sha256 = "0i5daj9sr8wyi5jkpwpybln2jqpn59z0mqfc0dpdidipwh1bjsrz"; + authors = [ + "MSxDOS " + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + features = [ "cfg" "evntrace" "in6addr" "inaddr" "minwinbase" "ntsecapi" "windef" "winioctl" ]; + } + ]; + features = { + "default" = [ "user" ]; + "impl-default" = [ "winapi/impl-default" ]; + }; + resolvedDefaultFeatures = [ "default" "user" ]; + }; + "num-integer" = rec { + crateName = "num-integer"; + version = "0.1.44"; + edition = "2015"; + sha256 = "1nq152y3304as1iai95hqz8prqnc94lks1s7q05sfjdmcf56kk6j"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "i128" = [ "num-traits/i128" ]; + "std" = [ "num-traits/std" ]; + }; + }; + "num-traits" = rec { + crateName = "num-traits"; + version = "0.2.14"; + edition = "2015"; + sha256 = "144j176s2p76azy2ngk2vkdzgwdc0bc8c93jhki8c9fsbknb2r4s"; + authors = [ + "The Rust Project Developers" + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "libm" = [ "dep:libm" ]; + }; + }; + "num_cpus" = rec { + crateName = "num_cpus"; + version = "1.13.0"; + edition = "2015"; + sha256 = "1cv6yxhz2zbnwn8pn1yn8grg7zsnd523947fby41a737aqvryj85"; + authors = [ + "Sean McArthur " + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("aarch64" == target."arch" or null)) && ("hermit" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + } + ]; + + }; + "okc-agents" = rec { + crateName = "okc-agents"; + version = "0.1.2"; + edition = "2018"; + crateBin = [ + { + name = "okc-gpg"; + path = "src/bin/okc-gpg.rs"; + requiredFeatures = [ ]; + } + { + name = "okc-ssh-agent"; + path = "src/bin/okc-ssh-agent.rs"; + requiredFeatures = [ ]; + } + ]; + src = pkgs.fetchFromGitHub { + owner = "DDoSolitary"; + repo = "okc-agents"; + rev = "83e70c81f30821ab41e6f2b93f37dd3698369c08"; + sha256 = "sha256-OvWbWEtiGsTwZusTmIYOtVsCD17AVQsbdV2KHbt8DpA="; + }; + authors = [ + "DDoSolitary " + ]; + dependencies = [ + { + name = "base64"; + packageId = "base64"; + } + { + name = "clap"; + packageId = "clap"; + } + { + name = "futures-util"; + packageId = "futures-util"; + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "slog"; + packageId = "slog"; + } + { + name = "slog-async"; + packageId = "slog-async"; + } + { + name = "slog-envlogger"; + packageId = "slog-envlogger"; + } + { + name = "slog-term"; + packageId = "slog-term"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" ]; + } + { + name = "tokio-stream"; + packageId = "tokio-stream"; + features = [ "net" ]; + } + ]; + + }; + "once_cell" = rec { + crateName = "once_cell"; + version = "1.8.0"; + edition = "2018"; + sha256 = "0mkbbxg6416z11r2yzsq91cqrkj9w1iyx5hakq15h5sbnriwnbv9"; + authors = [ + "Aleksey Kladov " + ]; + features = { + "alloc" = [ "race" ]; + "default" = [ "std" ]; + "parking_lot" = [ "dep:parking_lot" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; + }; + "parking_lot" = rec { + crateName = "parking_lot"; + version = "0.11.2"; + edition = "2018"; + sha256 = "16gzf41bxmm10x82bla8d6wfppy9ym3fxsmdjyvn61m66s0bf5vx"; + authors = [ + "Amanieu d'Antras " + ]; + dependencies = [ + { + name = "instant"; + packageId = "instant"; + } + { + name = "lock_api"; + packageId = "lock_api"; + } + { + name = "parking_lot_core"; + packageId = "parking_lot_core"; + } + ]; + features = { + "arc_lock" = [ "lock_api/arc_lock" ]; + "deadlock_detection" = [ "parking_lot_core/deadlock_detection" ]; + "nightly" = [ "parking_lot_core/nightly" "lock_api/nightly" ]; + "owning_ref" = [ "lock_api/owning_ref" ]; + "serde" = [ "lock_api/serde" ]; + "stdweb" = [ "instant/stdweb" ]; + "wasm-bindgen" = [ "instant/wasm-bindgen" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "parking_lot_core" = rec { + crateName = "parking_lot_core"; + version = "0.8.5"; + edition = "2018"; + sha256 = "05ij4zxsylx99srbq8qd1k2wiwaq8krkf9y4cqkhvb5wjca8wvnp"; + authors = [ + "Amanieu d'Antras " + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "instant"; + packageId = "instant"; + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "redox_syscall"; + packageId = "redox_syscall"; + target = { target, features }: ("redox" == target."os" or null); + } + { + name = "smallvec"; + packageId = "smallvec"; + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "winnt" "ntstatus" "minwindef" "winerror" "winbase" "errhandlingapi" "handleapi" ]; + } + ]; + features = { + "backtrace" = [ "dep:backtrace" ]; + "deadlock_detection" = [ "petgraph" "thread-id" "backtrace" ]; + "petgraph" = [ "dep:petgraph" ]; + "thread-id" = [ "dep:thread-id" ]; + }; + }; + "pin-project-lite" = rec { + crateName = "pin-project-lite"; + version = "0.2.7"; + edition = "2018"; + sha256 = "0hwl8iyx3h9i3i3jr2vqj07nf4ay1v1w1ga29cbjmdd6d4fd2ccd"; + authors = [ + "Taiki Endo " + ]; + + }; + "pin-utils" = rec { + crateName = "pin-utils"; + version = "0.1.0"; + edition = "2018"; + sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + authors = [ + "Josef Brandl " + ]; + + }; + "proc-macro-hack" = rec { + crateName = "proc-macro-hack"; + version = "0.5.19"; + edition = "2018"; + sha256 = "1rg0kzsj7lj00qj602d3h77spwfz48vixn1wbjp7a4yrq65w9w6v"; + procMacro = true; + authors = [ + "David Tolnay " + ]; + + }; + "proc-macro-nested" = rec { + crateName = "proc-macro-nested"; + version = "0.1.7"; + edition = "2015"; + sha256 = "11hh1jynh62f3m1ii0f9gf1l3y0fhkwpmr40lz3704v848n1p25w"; + authors = [ + "David Tolnay " + ]; + + }; + "proc-macro2" = rec { + crateName = "proc-macro2"; + version = "1.0.29"; + edition = "2018"; + sha256 = "0gfj25ksq90ifcssfnwv46v856sxd885wmm9bhrj1ays9xfi1xdr"; + authors = [ + "Alex Crichton " + "David Tolnay " + ]; + dependencies = [ + { + name = "unicode-xid"; + packageId = "unicode-xid"; + } + ]; + features = { + "default" = [ "proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "quote" = rec { + crateName = "quote"; + version = "1.0.9"; + edition = "2018"; + sha256 = "19rjmfqzk26rxbgxy5j2ckqc2v12sw2xw8l4gi8bzpn2bmsbkl63"; + authors = [ + "David Tolnay " + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "proc-macro" ]; + "proc-macro" = [ "proc-macro2/proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "redox_syscall" = rec { + crateName = "redox_syscall"; + version = "0.2.10"; + edition = "2018"; + sha256 = "1zq36bhw4c6xig340ja1jmr36iy0d3djp8smsabxx71676bg70w3"; + libName = "syscall"; + authors = [ + "Jeremy Soller " + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags"; + } + ]; + + }; + "redox_users" = rec { + crateName = "redox_users"; + version = "0.4.0"; + edition = "2018"; + sha256 = "0r5y1a26flkn6gkayi558jg5dzh2m2fdsapgkpn7mj01v3rk51aj"; + authors = [ + "Jose Narvaez " + "Wesley Hershberger " + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom"; + features = [ "std" ]; + } + { + name = "redox_syscall"; + packageId = "redox_syscall"; + } + ]; + features = { + "auth" = [ "rust-argon2" ]; + "default" = [ "auth" ]; + "rust-argon2" = [ "dep:rust-argon2" ]; + }; + }; + "regex" = rec { + crateName = "regex"; + version = "1.5.4"; + edition = "2018"; + sha256 = "0qf479kjbmb582h4d1d6gfl75h0j8aq2nrdi5wg6zdcy6llqcynh"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "aho-corasick"; + packageId = "aho-corasick"; + optional = true; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + } + { + name = "regex-syntax"; + packageId = "regex-syntax"; + usesDefaultFeatures = false; + } + ]; + features = { + "aho-corasick" = [ "dep:aho-corasick" ]; + "default" = [ "std" "perf" "unicode" "regex-syntax/default" ]; + "memchr" = [ "dep:memchr" ]; + "perf" = [ "perf-cache" "perf-dfa" "perf-inline" "perf-literal" ]; + "perf-literal" = [ "aho-corasick" "memchr" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "regex-syntax/unicode" ]; + "unicode-age" = [ "regex-syntax/unicode-age" ]; + "unicode-bool" = [ "regex-syntax/unicode-bool" ]; + "unicode-case" = [ "regex-syntax/unicode-case" ]; + "unicode-gencat" = [ "regex-syntax/unicode-gencat" ]; + "unicode-perl" = [ "regex-syntax/unicode-perl" ]; + "unicode-script" = [ "regex-syntax/unicode-script" ]; + "unicode-segment" = [ "regex-syntax/unicode-segment" ]; + "unstable" = [ "pattern" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "aho-corasick" "default" "memchr" "perf" "perf-cache" "perf-dfa" "perf-inline" "perf-literal" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "regex-syntax" = rec { + crateName = "regex-syntax"; + version = "0.6.25"; + edition = "2018"; + sha256 = "16y87hz1bxmmz6kk360cxwfm3jnbsxb3x4zw9x1gzz7khic2i5zl"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "unicode" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "default" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "rustversion" = rec { + crateName = "rustversion"; + version = "1.0.5"; + edition = "2018"; + sha256 = "1250m7ymrhp3c5xfmliskmknhf23r7x3cirxy9wmrdwbfnfr1cv1"; + procMacro = true; + build = "build/build.rs"; + authors = [ + "David Tolnay " + ]; + + }; + "scopeguard" = rec { + crateName = "scopeguard"; + version = "1.1.0"; + edition = "2015"; + sha256 = "1kbqm85v43rq92vx7hfiay6pmcga03vrjbbfwqpyj3pwsg3b16nj"; + authors = [ + "bluss" + ]; + features = { + "default" = [ "use_std" ]; + }; + }; + "signal-hook-registry" = rec { + crateName = "signal-hook-registry"; + version = "1.4.0"; + edition = "2015"; + sha256 = "1c2mhijg54y6c1zi4630yki1vpq3z96ljfnsrdy0rb64ilr767p5"; + authors = [ + "Michal 'vorner' Vaner " + "Masaki Hara " + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + + }; + "slab" = rec { + crateName = "slab"; + version = "0.4.4"; + edition = "2018"; + sha256 = "1465rj4y59qjvzxik0v2m0mp71q50m9xfigxqww7yhsw3hna61y3"; + authors = [ + "Carl Lerche " + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "slog" = rec { + crateName = "slog"; + version = "2.7.0"; + edition = "2015"; + sha256 = "01ldk4yarx7x4y4rgsf4kmrcy3wrpcxdd53v2lkk355x9rnh8iw3"; + authors = [ + "Dawid Ciężarkiewicz " + ]; + features = { + "default" = [ "std" ]; + "erased-serde" = [ "dep:erased-serde" ]; + "nested-values" = [ "erased-serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "slog-async" = rec { + crateName = "slog-async"; + version = "2.7.0"; + edition = "2015"; + sha256 = "1zkz15xl2gkhnbn3xd0rvw26sklcbpshz1qj2ijk8ap6aar5jv3n"; + libPath = "lib.rs"; + authors = [ + "Dawid Ciężarkiewicz " + ]; + dependencies = [ + { + name = "crossbeam-channel"; + packageId = "crossbeam-channel"; + } + { + name = "slog"; + packageId = "slog"; + } + { + name = "take_mut"; + packageId = "take_mut"; + } + { + name = "thread_local"; + packageId = "thread_local"; + } + ]; + features = { + "dynamic-keys" = [ "slog/dynamic-keys" ]; + "nested-values" = [ "slog/nested-values" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "slog-envlogger" = rec { + crateName = "slog-envlogger"; + version = "2.2.0"; + edition = "2015"; + sha256 = "1h7m0jnj6kvsn9553fyqvaw3swy3pwpmwamqyhnnkv9zqh5ilslh"; + authors = [ + "The Rust Project Developers" + "Dawid Ciężarkiewicz " + ]; + dependencies = [ + { + name = "log"; + packageId = "log"; + } + { + name = "regex"; + packageId = "regex"; + optional = true; + } + { + name = "slog"; + packageId = "slog"; + } + { + name = "slog-async"; + packageId = "slog-async"; + } + { + name = "slog-scope"; + packageId = "slog-scope"; + } + { + name = "slog-stdlog"; + packageId = "slog-stdlog"; + } + { + name = "slog-term"; + packageId = "slog-term"; + } + ]; + devDependencies = [ + { + name = "slog-async"; + packageId = "slog-async"; + } + ]; + features = { + "default" = [ "regex" ]; + "regex" = [ "dep:regex" ]; + }; + resolvedDefaultFeatures = [ "default" "regex" ]; + }; + "slog-scope" = rec { + crateName = "slog-scope"; + version = "4.4.0"; + edition = "2015"; + sha256 = "11n7nd0g3iab8ahcwnxzpmchi4ycgjsq5nj9jn3d4k17qfsa959g"; + libPath = "lib.rs"; + authors = [ + "Dawid Ciężarkiewicz " + ]; + dependencies = [ + { + name = "arc-swap"; + packageId = "arc-swap"; + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "slog"; + packageId = "slog"; + } + ]; + + }; + "slog-stdlog" = rec { + crateName = "slog-stdlog"; + version = "4.1.0"; + edition = "2018"; + sha256 = "0nhg9mwaf5y1gs2f7nbz3r9fngq0g3d3qvz66z5lzgxd09rsna42"; + libPath = "lib.rs"; + authors = [ + "Dawid Ciężarkiewicz " + ]; + dependencies = [ + { + name = "log"; + packageId = "log"; + features = [ "std" ]; + } + { + name = "slog"; + packageId = "slog"; + } + { + name = "slog-scope"; + packageId = "slog-scope"; + } + ]; + + }; + "slog-term" = rec { + crateName = "slog-term"; + version = "2.8.0"; + edition = "2018"; + sha256 = "0xkdjhllhgiixxfqixz0dk8s110bfxrag7hl0rhfs75nmbjyghcm"; + authors = [ + "Dawid Ciężarkiewicz " + ]; + dependencies = [ + { + name = "atty"; + packageId = "atty"; + } + { + name = "chrono"; + packageId = "chrono"; + } + { + name = "slog"; + packageId = "slog"; + } + { + name = "term"; + packageId = "term"; + } + { + name = "thread_local"; + packageId = "thread_local"; + } + ]; + features = { + "erased-serde" = [ "dep:erased-serde" ]; + "nested-values" = [ "erased-serde" "serde" "serde_json" "slog/nested-values" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + }; + }; + "smallvec" = rec { + crateName = "smallvec"; + version = "1.7.0"; + edition = "2018"; + sha256 = "02gka690j8l12gl50ifg7axqnx1m6v6d1byaq0wl3fx66p3vdjhy"; + authors = [ + "The Servo Project Developers" + ]; + features = { + "const_new" = [ "const_generics" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "strsim" = rec { + crateName = "strsim"; + version = "0.8.0"; + edition = "2015"; + sha256 = "0sjsm7hrvjdifz661pjxq5w4hf190hx53fra8dfvamacvff139cf"; + authors = [ + "Danny Guo " + ]; + + }; + "syn" = rec { + crateName = "syn"; + version = "1.0.77"; + edition = "2018"; + sha256 = "1870dx7d4h54w2qiczlx66d6snbmvkla9zhcj2ap9xgyw1lbqfaj"; + authors = [ + "David Tolnay " + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-xid"; + packageId = "unicode-xid"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; + "quote" = [ "dep:quote" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "full" "parsing" "printing" "proc-macro" "quote" ]; + }; + "take_mut" = rec { + crateName = "take_mut"; + version = "0.2.2"; + edition = "2015"; + sha256 = "0q2d7w6nd5bl7bay5csq065sjg8fw0jcx6hl1983cpzf25fh0r7p"; + authors = [ + "Sgeo " + ]; + + }; + "term" = rec { + crateName = "term"; + version = "0.7.0"; + edition = "2018"; + sha256 = "07xzxmg7dbhlirpyfq09v7cfb9gxn0077sqqvszgjvyrjnngi7f5"; + authors = [ + "The Rust Project Developers" + "Steven Allen" + ]; + dependencies = [ + { + name = "dirs-next"; + packageId = "dirs-next"; + } + { + name = "rustversion"; + packageId = "rustversion"; + target = { target, features }: (target."windows" or false); + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "consoleapi" "wincon" "handleapi" "fileapi" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "textwrap" = rec { + crateName = "textwrap"; + version = "0.11.0"; + edition = "2015"; + sha256 = "0q5hky03ik3y50s9sz25r438bc4nwhqc6dqwynv4wylc807n29nk"; + authors = [ + "Martin Geisler " + ]; + dependencies = [ + { + name = "unicode-width"; + packageId = "unicode-width"; + } + ]; + features = { + "hyphenation" = [ "dep:hyphenation" ]; + "term_size" = [ "dep:term_size" ]; + }; + }; + "thread_local" = rec { + crateName = "thread_local"; + version = "1.1.3"; + edition = "2018"; + sha256 = "1gccp3grndpi6dyhzylz4hkqnkzc1xyri98n0xwwhnn90i7d4640"; + authors = [ + "Amanieu d'Antras " + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + } + ]; + features = { + "criterion" = [ "dep:criterion" ]; + }; + }; + "time" = rec { + crateName = "time"; + version = "0.1.43"; + edition = "2015"; + sha256 = "0f14wrgxj7ya2v4msg5mni7046bsm2angm7cn3pd3yv04gpm12na"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "std" "minwinbase" "minwindef" "ntdef" "profileapi" "sysinfoapi" "timezoneapi" ]; + } + ]; + devDependencies = [ + { + name = "winapi"; + packageId = "winapi"; + features = [ "std" "processthreadsapi" "winbase" ]; + } + ]; + features = { + "rustc-serialize" = [ "dep:rustc-serialize" ]; + }; + }; + "tokio" = rec { + crateName = "tokio"; + version = "1.12.0"; + edition = "2018"; + sha256 = "1k7g4hyvbibjdvx9y5ppv1hsycx63vg2fiabwhx49a6wvrpl3hn2"; + authors = [ + "Tokio Contributors " + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { + name = "libc"; + packageId = "libc"; + optional = true; + target = { target, features }: (target."unix" or false); + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + } + { + name = "mio"; + packageId = "mio"; + optional = true; + } + { + name = "num_cpus"; + packageId = "num_cpus"; + optional = true; + } + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + { + name = "parking_lot"; + packageId = "parking_lot"; + optional = true; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "signal-hook-registry"; + packageId = "signal-hook-registry"; + optional = true; + target = { target, features }: (target."unix" or false); + } + { + name = "tokio-macros"; + packageId = "tokio-macros"; + optional = true; + } + { + name = "winapi"; + packageId = "winapi"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (target."windows" or false); + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + devDependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + ]; + features = { + "bytes" = [ "dep:bytes" ]; + "full" = [ "fs" "io-util" "io-std" "macros" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "sync" "time" ]; + "io-util" = [ "memchr" "bytes" ]; + "libc" = [ "dep:libc" ]; + "macros" = [ "tokio-macros" ]; + "memchr" = [ "dep:memchr" ]; + "mio" = [ "dep:mio" ]; + "net" = [ "libc" "mio/os-poll" "mio/os-util" "mio/tcp" "mio/udp" "mio/uds" "winapi/namedpipeapi" ]; + "num_cpus" = [ "dep:num_cpus" ]; + "once_cell" = [ "dep:once_cell" ]; + "parking_lot" = [ "dep:parking_lot" ]; + "process" = [ "bytes" "once_cell" "libc" "mio/os-poll" "mio/os-util" "mio/uds" "signal-hook-registry" "winapi/threadpoollegacyapiset" ]; + "rt-multi-thread" = [ "num_cpus" "rt" ]; + "signal" = [ "once_cell" "libc" "mio/os-poll" "mio/uds" "mio/os-util" "signal-hook-registry" "winapi/consoleapi" ]; + "signal-hook-registry" = [ "dep:signal-hook-registry" ]; + "test-util" = [ "rt" "sync" "time" ]; + "tokio-macros" = [ "dep:tokio-macros" ]; + "tracing" = [ "dep:tracing" ]; + "winapi" = [ "dep:winapi" ]; + }; + resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "memchr" "mio" "net" "num_cpus" "once_cell" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "sync" "time" "tokio-macros" "winapi" ]; + }; + "tokio-macros" = rec { + crateName = "tokio-macros"; + version = "1.4.1"; + edition = "2018"; + sha256 = "1sz5pq7yzm40x935zvrhfqpf7s838wlkks0rrnd63hlryk498iqm"; + procMacro = true; + authors = [ + "Tokio Contributors " + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn"; + features = [ "full" ]; + } + ]; + + }; + "tokio-stream" = rec { + crateName = "tokio-stream"; + version = "0.1.7"; + edition = "2018"; + sha256 = "0zvj8d2i1147s4i3ml3lh3h6fypncjmbw0h1mhck3w2kh9lkybvv"; + authors = [ + "Tokio Contributors " + ]; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" "test-util" ]; + } + ]; + features = { + "default" = [ "time" ]; + "fs" = [ "tokio/fs" ]; + "io-util" = [ "tokio/io-util" ]; + "net" = [ "tokio/net" ]; + "signal" = [ "tokio/signal" ]; + "sync" = [ "tokio/sync" "tokio-util" ]; + "time" = [ "tokio/time" ]; + "tokio-util" = [ "dep:tokio-util" ]; + }; + resolvedDefaultFeatures = [ "default" "net" "time" ]; + }; + "unicode-width" = rec { + crateName = "unicode-width"; + version = "0.1.9"; + edition = "2015"; + sha256 = "0wq9wl69wlp6zwlxp660g9p4hm5gk91chwk14dp1gl9bxba45mry"; + authors = [ + "kwantam " + "Manish Goregaokar " + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; + "std" = [ "dep:std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "unicode-xid" = rec { + crateName = "unicode-xid"; + version = "0.2.2"; + edition = "2015"; + sha256 = "1wrkgcw557v311dkdb6n2hrix9dm2qdsb1zpw7pn79l03zb85jwc"; + authors = [ + "erick.tryzelaar " + "kwantam " + "Manish Goregaokar " + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "vec_map" = rec { + crateName = "vec_map"; + version = "0.8.2"; + edition = "2015"; + sha256 = "1481w9g1dw9rxp3l6snkdqihzyrd2f8vispzqmwjwsdyhw8xzggi"; + authors = [ + "Alex Crichton " + "Jorge Aparicio " + "Alexis Beingessner " + "Brian Anderson <>" + "tbu- <>" + "Manish Goregaokar <>" + "Aaron Turon " + "Adolfo Ochagavía <>" + "Niko Matsakis <>" + "Steven Fackler <>" + "Chase Southwood " + "Eduard Burtescu <>" + "Florian Wilkens <>" + "Félix Raimundo <>" + "Tibor Benke <>" + "Markus Siemens " + "Josh Branchaud " + "Huon Wilson " + "Corey Farwell " + "Aaron Liblong <>" + "Nick Cameron " + "Patrick Walton " + "Felix S Klock II <>" + "Andrew Paseltiner " + "Sean McArthur " + "Vadim Petrochenkov <>" + ]; + features = { + "eders" = [ "serde" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "wasi" = rec { + crateName = "wasi"; + version = "0.10.2+wasi-snapshot-preview1"; + edition = "2018"; + sha256 = "1ii7nff4y1mpcrxzzvbpgxm7a1nn3szjf1n21jnx37c2g6dbsvzx"; + authors = [ + "The Cranelift Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "rustc-std-workspace-alloc" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "winapi" = rec { + crateName = "winapi"; + version = "0.3.9"; + edition = "2015"; + sha256 = "06gl025x418lchw1wxj64ycr7gha83m44cjr5sarhynd9xkrm0sw"; + authors = [ + "Peter Atashian " + ]; + dependencies = [ + { + name = "winapi-i686-pc-windows-gnu"; + packageId = "winapi-i686-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); + } + { + name = "winapi-x86_64-pc-windows-gnu"; + packageId = "winapi-x86_64-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); + } + ]; + features = { + "debug" = [ "impl-debug" ]; + }; + resolvedDefaultFeatures = [ "cfg" "consoleapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "in6addr" "inaddr" "ioapiset" "knownfolders" "minwinbase" "minwindef" "mstcpip" "mswsock" "namedpipeapi" "ntdef" "ntsecapi" "ntstatus" "objbase" "processenv" "profileapi" "shlobj" "std" "synchapi" "sysinfoapi" "threadpoollegacyapiset" "timezoneapi" "winbase" "wincon" "windef" "winerror" "winioctl" "winnt" "winsock2" "ws2def" "ws2ipdef" ]; + }; + "winapi-i686-pc-windows-gnu" = rec { + crateName = "winapi-i686-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + authors = [ + "Peter Atashian " + ]; + + }; + "winapi-x86_64-pc-windows-gnu" = rec { + crateName = "winapi-x86_64-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + authors = [ + "Peter Atashian " + ]; + + }; + }; + + # + # crate2nix/default.nix (excerpt start) + # + + /* Target (platform) data for conditional dependencies. + This corresponds roughly to what buildRustCrate is setting. + */ + makeDefaultTarget = platform: { + unix = platform.isUnix; + windows = platform.isWindows; + fuchsia = true; + test = false; + + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; + env = "gnu"; + endian = + if platform.parsed.cpu.significantByte.name == "littleEndian" + then "little" else "big"; + pointer_width = toString platform.parsed.cpu.bits; + debug_assertions = false; + }; + + /* Filters common temp files and build files. */ + # TODO(pkolloch): Substitute with gitignore filter + sourceFilter = name: type: + let + baseName = builtins.baseNameOf (builtins.toString name); + in + ! ( + # Filter out git + baseName == ".gitignore" + || (type == "directory" && baseName == ".git") + + # Filter out build results + || ( + type == "directory" && ( + baseName == "target" + || baseName == "_site" + || baseName == ".sass-cache" + || baseName == ".jekyll-metadata" + || baseName == "build-artifacts" + ) + ) + + # Filter out nix-build result symlinks + || ( + type == "symlink" && lib.hasPrefix "result" baseName + ) + + # Filter out IDE config + || ( + type == "directory" && ( + baseName == ".idea" || baseName == ".vscode" + ) + ) || lib.hasSuffix ".iml" baseName + + # Filter out nix build files + || baseName == "Cargo.nix" + + # Filter out editor backup / swap files. + || lib.hasSuffix "~" baseName + || builtins.match "^\\.sw[a-z]$$" baseName != null + || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null + || lib.hasSuffix ".tmp" baseName + || lib.hasSuffix ".bak" baseName + || baseName == "tests.nix" + ); + + /* Returns a crate which depends on successful test execution + of crate given as the second argument. + + testCrateFlags: list of flags to pass to the test exectuable + testInputs: list of packages that should be available during test execution + */ + crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: + assert builtins.typeOf testCrateFlags == "list"; + assert builtins.typeOf testInputs == "list"; + assert builtins.typeOf testPreRun == "string"; + assert builtins.typeOf testPostRun == "string"; + let + # override the `crate` so that it will build and execute tests instead of + # building the actual lib and bin targets We just have to pass `--test` + # to rustc and it will do the right thing. We execute the tests and copy + # their log and the test executables to $out for later inspection. + test = + let + drv = testCrate.override + ( + _: { + buildTests = true; + } + ); + # If the user hasn't set any pre/post commands, we don't want to + # insert empty lines. This means that any existing users of crate2nix + # don't get a spurious rebuild unless they set these explicitly. + testCommand = pkgs.lib.concatStringsSep "\n" + (pkgs.lib.filter (s: s != "") [ + testPreRun + "$f $testCrateFlags 2>&1 | tee -a $out" + testPostRun + ]); + in + pkgs.runCommand "run-tests-${testCrate.name}" + { + inherit testCrateFlags; + buildInputs = testInputs; + } '' + set -e + + export RUST_BACKTRACE=1 + + # recreate a file hierarchy as when running tests with cargo + + # the source for test data + # It's necessary to locate the source in $NIX_BUILD_TOP/source/ + # instead of $NIX_BUILD_TOP/ + # because we compiled those test binaries in the former and not the latter. + # So all paths will expect source tree to be there and not in the build top directly. + # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. + # NOTE: There could be edge cases if `crate.sourceRoot` does exist but + # it's very hard to reason about them. + # Open a bug if you run into this! + mkdir -p source/ + cd source/ + + ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + in + pkgs.runCommand "${crate.name}-linked" + { + inherit (crate) outputs crateName; + passthru = (crate.passthru or { }) // { + inherit test; + }; + } + (lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' + echo tested by ${test} + '' + '' + ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} + ''); + + /* A restricted overridable version of builtRustCratesWithFeatures. */ + buildRustCrateWithFeatures = + { packageId + , features ? rootFeatures + , crateOverrides ? defaultCrateOverrides + , buildRustCrateForPkgsFunc ? null + , runTests ? false + , testCrateFlags ? [ ] + , testInputs ? [ ] + # Any command to run immediatelly before a test is executed. + , testPreRun ? "" + # Any command run immediatelly after a test is executed. + , testPostRun ? "" + }: + lib.makeOverridable + ( + { features + , crateOverrides + , runTests + , testCrateFlags + , testInputs + , testPreRun + , testPostRun + }: + let + buildRustCrateForPkgsFuncOverriden = + if buildRustCrateForPkgsFunc != null + then buildRustCrateForPkgsFunc + else + ( + if crateOverrides == pkgs.defaultCrateOverrides + then buildRustCrateForPkgs + else + pkgs: (buildRustCrateForPkgs pkgs).override { + defaultCrateOverrides = crateOverrides; + } + ); + builtRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = false; + }; + builtTestRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = true; + }; + drv = builtRustCrates.crates.${packageId}; + testDrv = builtTestRustCrates.crates.${packageId}; + derivation = + if runTests then + crateWithTest + { + crate = drv; + testCrate = testDrv; + inherit testCrateFlags testInputs testPreRun testPostRun; + } + else drv; + in + derivation + ) + { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + + /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc + for the corresponding crate. + */ + builtRustCratesWithFeatures = + { packageId + , features + , crateConfigs ? crates + , buildRustCrateForPkgsFunc + , runTests + , makeTarget ? makeDefaultTarget + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isList features); + assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); + assert (builtins.isBool runTests); + let + rootPackageId = packageId; + mergedFeatures = mergePackageFeatures + ( + args // { + inherit rootPackageId; + target = makeTarget stdenv.hostPlatform // { test = runTests; }; + } + ); + # Memoize built packages so that reappearing packages are only built once. + builtByPackageIdByPkgs = mkBuiltByPackageIdByPkgs pkgs; + mkBuiltByPackageIdByPkgs = pkgs: + let + self = { + crates = lib.mapAttrs (packageId: _value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; + target = makeTarget stdenv.hostPlatform; + build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; + }; + in + self; + buildByPackageIdForPkgsImpl = self: pkgs: packageId: + let + features = mergedFeatures."${packageId}" or [ ]; + crateConfig' = crateConfigs."${packageId}"; + crateConfig = + builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; + devDependencies = + lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig'.devDependencies or [ ]); + dependencies = + dependencyDerivations { + inherit features; + inherit (self) target; + buildByPackageId = depPackageId: + # proc_macro crates must be compiled for the build architecture + if crateConfigs.${depPackageId}.procMacro or false + then self.build.crates.${depPackageId} + else self.crates.${depPackageId}; + dependencies = + (crateConfig.dependencies or [ ]) + ++ devDependencies; + }; + buildDependencies = + dependencyDerivations { + inherit features; + inherit (self.build) target; + buildByPackageId = depPackageId: + self.build.crates.${depPackageId}; + dependencies = crateConfig.buildDependencies or [ ]; + }; + dependenciesWithRenames = + let + buildDeps = filterEnabledDependencies { + inherit features; + inherit (self) target; + dependencies = crateConfig.dependencies or [ ] ++ devDependencies; + }; + hostDeps = filterEnabledDependencies { + inherit features; + inherit (self.build) target; + dependencies = crateConfig.buildDependencies or [ ]; + }; + in + lib.filter (d: d ? "rename") (hostDeps ++ buildDeps); + # Crate renames have the form: + # + # { + # crate_name = [ + # { version = "1.2.3"; rename = "crate_name01"; } + # ]; + # # ... + # } + crateRenames = + let + grouped = + builtins.groupBy + (dependency: dependency.name) + dependenciesWithRenames; + versionAndRename = dep: + let + package = crateConfigs."${dep.packageId}"; + in + { inherit (dep) rename; inherit (package) version; }; + in + lib.mapAttrs (_name: builtins.map versionAndRename) grouped; + in + buildRustCrateForPkgsFunc pkgs + ( + crateConfig // { + src = crateConfig.src or ( + pkgs.fetchurl rec { + name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; + # https://www.pietroalbini.org/blog/downloading-crates-io/ + # Not rate-limited, CDN URL. + url = "https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate"; + sha256 = + assert (lib.assertMsg (crateConfig ? sha256) "Missing sha256 for ${name}"); + crateConfig.sha256; + } + ); + extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + inherit features dependencies buildDependencies crateRenames release; + } + ); + in + builtByPackageIdByPkgs; + + /* Returns the actual derivations for the given dependencies. */ + dependencyDerivations = + { buildByPackageId + , features + , dependencies + , target + }: + assert (builtins.isList features); + assert (builtins.isList dependencies); + assert (builtins.isAttrs target); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies features target; + }; + depDerivation = dependency: buildByPackageId dependency.packageId; + in + map depDerivation enabledDependencies; + + /* Returns a sanitized version of val with all values substituted that cannot + be serialized as JSON. + */ + sanitizeForJson = val: + if builtins.isAttrs val + then lib.mapAttrs (_n: sanitizeForJson) val + else if builtins.isList val + then builtins.map sanitizeForJson val + else if builtins.isFunction val + then "function" + else val; + + /* Returns various tools to debug a crate. */ + debugCrate = { packageId, target ? makeDefaultTarget stdenv.hostPlatform }: + assert (builtins.isString packageId); + let + debug = rec { + # The built tree as passed to buildRustCrate. + buildTree = buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: lib.id; + inherit packageId; + }; + sanitizedBuildTree = sanitizeForJson buildTree; + dependencyTree = sanitizeForJson + ( + buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: crate: { + "01_crateName" = crate.crateName or false; + "02_features" = crate.features or [ ]; + "03_dependencies" = crate.dependencies or [ ]; + }; + inherit packageId; + } + ); + mergedPackageFeatures = mergePackageFeatures { + features = rootFeatures; + inherit packageId target; + }; + diffedDefaultPackageFeatures = diffDefaultPackageFeatures { + inherit packageId target; + }; + }; + in + { internal = debug; }; + + /* Returns differences between cargo default features and crate2nix default + features. + + This is useful for verifying the feature resolution in crate2nix. + */ + diffDefaultPackageFeatures = + { crateConfigs ? crates + , packageId + , target + }: + assert (builtins.isAttrs crateConfigs); + let + prefixValues = prefix: lib.mapAttrs (_n: v: { "${prefix}" = v; }); + mergedFeatures = + prefixValues + "crate2nix" + (mergePackageFeatures { inherit crateConfigs packageId target; features = [ "default" ]; }); + configs = prefixValues "cargo" crateConfigs; + combined = lib.foldAttrs (a: b: a // b) { } [ mergedFeatures configs ]; + onlyInCargo = + builtins.attrNames + (lib.filterAttrs (_n: v: !(v ? "crate2nix") && (v ? "cargo")) combined); + onlyInCrate2Nix = + builtins.attrNames + (lib.filterAttrs (_n: v: (v ? "crate2nix") && !(v ? "cargo")) combined); + differentFeatures = lib.filterAttrs + ( + _n: v: + (v ? "crate2nix") + && (v ? "cargo") + && (v.crate2nix.features or [ ]) != (v."cargo".resolved_default_features or [ ]) + ) + combined; + in + builtins.toJSON { + inherit onlyInCargo onlyInCrate2Nix differentFeatures; + }; + + /* Returns an attrset mapping packageId to the list of enabled features. + + If multiple paths to a dependency enable different features, the + corresponding feature sets are merged. Features in rust are additive. + */ + mergePackageFeatures = + { crateConfigs ? crates + , packageId + , rootPackageId ? packageId + , features ? rootFeatures + , dependencyPath ? [ crates.${packageId}.crateName ] + , featuresByPackageId ? { } + , target + # Adds devDependencies to the crate with rootPackageId. + , runTests ? false + , ... + }: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isString rootPackageId); + assert (builtins.isList features); + assert (builtins.isList dependencyPath); + assert (builtins.isAttrs featuresByPackageId); + assert (builtins.isAttrs target); + assert (builtins.isBool runTests); + let + crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); + expandedFeatures = expandFeatures (crateConfig.features or { }) features; + enabledFeatures = enableFeatures (crateConfig.dependencies or [ ]) expandedFeatures; + depWithResolvedFeatures = dependency: + let + inherit (dependency) packageId; + features = dependencyFeatures enabledFeatures dependency; + in + { inherit packageId features; }; + resolveDependencies = cache: _path: dependencies: + assert (builtins.isAttrs cache); + assert (builtins.isList dependencies); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies target; + features = enabledFeatures; + }; + directDependencies = map depWithResolvedFeatures enabledDependencies; + foldOverCache = op: lib.foldl op cache directDependencies; + in + foldOverCache + ( + cache: { packageId, features }: + let + cacheFeatures = cache.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ features); + in + if cache ? ${packageId} && cache.${packageId} == combinedFeatures + then cache + else + mergePackageFeatures { + features = combinedFeatures; + featuresByPackageId = cache; + inherit crateConfigs packageId target runTests rootPackageId; + } + ); + cacheWithSelf = + let + cacheFeatures = featuresByPackageId.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ enabledFeatures); + in + featuresByPackageId // { + "${packageId}" = combinedFeatures; + }; + cacheWithDependencies = + resolveDependencies cacheWithSelf "dep" + ( + crateConfig.dependencies or [ ] + ++ lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig.devDependencies or [ ]) + ); + cacheWithAll = + resolveDependencies + cacheWithDependencies "build" + (crateConfig.buildDependencies or [ ]); + in + cacheWithAll; + + /* Returns the enabled dependencies given the enabled features. */ + filterEnabledDependencies = { dependencies, features, target }: + assert (builtins.isList dependencies); + assert (builtins.isList features); + assert (builtins.isAttrs target); + + lib.filter + ( + dep: + let + targetFunc = dep.target or (_features: true); + in + targetFunc { inherit features target; } + && ( + !(dep.optional or false) + || builtins.any (doesFeatureEnableDependency dep) features + ) + ) + dependencies; + + /* Returns whether the given feature should enable the given dependency. */ + doesFeatureEnableDependency = dependency: feature: + let + name = dependency.rename or dependency.name; + prefix = "${name}/"; + len = builtins.stringLength prefix; + startsWithPrefix = builtins.substring 0 len feature == prefix; + in + feature == name || feature == "dep:" + name || startsWithPrefix; + + /* Returns the expanded features for the given inputFeatures by applying the + rules in featureMap. + + featureMap is an attribute set which maps feature names to lists of further + feature names to enable in case this feature is selected. + */ + expandFeatures = featureMap: inputFeatures: + assert (builtins.isAttrs featureMap); + assert (builtins.isList inputFeatures); + let + expandFeaturesNoCycle = oldSeen: inputFeatures: + if inputFeatures != [ ] + then + let + # The feature we're currently expanding. + feature = builtins.head inputFeatures; + # All the features we've seen/expanded so far, including the one + # we're currently processing. + seen = oldSeen // { ${feature} = 1; }; + # Expand the feature but be careful to not re-introduce a feature + # that we've already seen: this can easily cause a cycle, see issue + # #209. + enables = builtins.filter (f: !(seen ? "${f}")) (featureMap."${feature}" or [ ]); + in + [ feature ] ++ (expandFeaturesNoCycle seen (builtins.tail inputFeatures ++ enables)) + # No more features left, nothing to expand to. + else [ ]; + outFeatures = expandFeaturesNoCycle { } inputFeatures; + in + sortedUnique outFeatures; + + /* This function adds optional dependencies as features if they are enabled + indirectly by dependency features. This function mimics Cargo's behavior + described in a note at: + https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features + */ + enableFeatures = dependencies: features: + assert (builtins.isList features); + assert (builtins.isList dependencies); + let + additionalFeatures = lib.concatMap + ( + dependency: + assert (builtins.isAttrs dependency); + let + enabled = builtins.any (doesFeatureEnableDependency dependency) features; + in + if (dependency.optional or false) && enabled + then [ (dependency.rename or dependency.name) ] + else [ ] + ) + dependencies; + in + sortedUnique (features ++ additionalFeatures); + + /* + Returns the actual features for the given dependency. + + features: The features of the crate that refers this dependency. + */ + dependencyFeatures = features: dependency: + assert (builtins.isList features); + assert (builtins.isAttrs dependency); + let + defaultOrNil = + if dependency.usesDefaultFeatures or true + then [ "default" ] + else [ ]; + explicitFeatures = dependency.features or [ ]; + additionalDependencyFeatures = + let + name = dependency.rename or dependency.name; + stripPrefixMatch = prefix: s: + if lib.hasPrefix prefix s + then lib.removePrefix prefix s + else null; + extractFeature = feature: lib.findFirst + (f: f != null) + null + (map (prefix: stripPrefixMatch prefix feature) [ + (name + "/") + (name + "?/") + ]); + dependencyFeatures = lib.filter (f: f != null) (map extractFeature features); + in + dependencyFeatures; + in + defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures; + + /* Sorts and removes duplicates from a list of strings. */ + sortedUnique = features: + assert (builtins.isList features); + assert (builtins.all builtins.isString features); + let + outFeaturesSet = lib.foldl (set: feature: set // { "${feature}" = 1; }) { } features; + outFeaturesUnique = builtins.attrNames outFeaturesSet; + in + builtins.sort (a: b: a < b) outFeaturesUnique; + + deprecationWarning = message: value: + if strictDeprecation + then builtins.throw "strictDeprecation enabled, aborting: ${message}" + else builtins.trace message value; + + # + # crate2nix/default.nix (excerpt end) + # + }; +} diff --git a/pkgs/android-integration/okc-agents/default.nix b/pkgs/android-integration/okc-agents/default.nix new file mode 100644 index 00000000..bcac29f0 --- /dev/null +++ b/pkgs/android-integration/okc-agents/default.nix @@ -0,0 +1,23 @@ +# Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. + +{ nixpkgs, pkgs, termux-am }: + +let + okc-agents-unwrapped = + (import ./Cargo.nix { inherit nixpkgs pkgs; }).rootCrate.build; +in +pkgs.stdenvNoCC.mkDerivation { + inherit (okc-agents-unwrapped) name version; + phases = [ "installPhase" ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + outputs = [ "out" "okc_gpg" ]; + installPhase = '' + mkdir -p $out/bin $okc_gpg/bin + makeWrapper ${okc-agents-unwrapped}/bin/okc-gpg \ + $okc_gpg/bin/okc-gpg \ + --prefix PATH : ${pkgs.lib.makeBinPath [ termux-am ]} + makeWrapper ${okc-agents-unwrapped}/bin/okc-ssh-agent \ + $out/bin/okc-ssh-agent \ + --prefix PATH : ${pkgs.lib.makeBinPath [ termux-am ]} + ''; +} diff --git a/tests/emulator/okc_agents.py b/tests/emulator/okc_agents.py new file mode 100644 index 00000000..10e47422 --- /dev/null +++ b/tests/emulator/okc_agents.py @@ -0,0 +1,96 @@ +import base64 +import os + +import bootstrap_channels + +from common import screenshot, wait_for + + +def run(d): + # Set up a GPG key in OpenKeychain + os.system('fdroidcl update') + okc = 'org.sufficientlysecure.keychain' + openkeychain = d.fdroid[okc] + openkeychain.permissions.allow_notifications() + openkeychain.launch() + wait_for(d, 'CREATE MY KEY') + d.ui(resourceId=f'{okc}:id/create_key_create_key_button').click() + d.ui(resourceId=f'{okc}:id/create_key_name').set_text('Test Key') + d.ui(resourceId=f'{okc}:id/create_key_next_button').click() + d.ui(resourceId=f'{okc}:id/create_key_email').set_text('nod@example.org') + d.ui(resourceId=f'{okc}:id/create_key_next_button').click() + d.ui(resourceId=f'{okc}:id/create_key_next_button').click() + screenshot(d, 'key-created') + + # Select this key in OkcAgent + okc_agent = d.fdroid['org.ddosolitary.okcagent'] + okc_agent.permissions.allow_notifications() + okc_agent.launch() + wait_for(d, 'Automatic error reporting') + d.ui(text='NO').click() + wait_for(d, 'SELECT GPG KEY') + d.ui(text='SELECT GPG KEY').click() + d.ui(text='Test Key ').click() + screenshot(d, 'gpg-key-selected') + + # SSH is currently untested (`Error: Could not create description: null`) + # wait_for(d, 'ADD SSH KEY') + # d.ui(text='ADD SSH KEY').click() + # wait_for(d, 'Select authentication key') + # d.ui(text='Use key: nod@example.org').click() + # d.ui(text='SELECT').click() + # screenshot(d, 'ssh-key-selected') + + # Bootstrap + bootstrap_channels.run(d) + + # Apply a config that enables okc-agents (but not am) + cfg_file = '.config/nixpkgs/nix-on-droid.nix' + config = ('_: { system.stateVersion = "23.11"; ' + 'android-integration.okc-gpg.enable = true; }') + config_base64 = base64.b64encode(config.encode()).decode() + d(f'input text "echo {config_base64} | base64 -d > {cfg_file}"') + d.ui.press('enter') + d('input text "nix-on-droid switch && echo okc-agents installed"') + screenshot(d, 'pre-switch') + d.ui.press('enter') + wait_for(d, 'okc-agents installed', timeout=1200) + screenshot(d, 'post-switch') + + # Verify am is not in path + d('input text "am"') + d.ui.press('enter') + wait_for(d, 'bash: am: command not found') + screenshot(d, 'no-am') + + # Test that nix-on-droid can use that GPG key through okc-gpg: encryption + d('input text "echo secret data > test"') + d.ui.press('enter') + screenshot(d, 'pre-encryption') + d('input text "RUST_BACKTRACE=1 okc-gpg -er nod@example.org test > test.gpg"') + d.ui.press('enter') + screenshot(d, 'encryption') + d('input text "rm test"') + d.ui.press('enter') + screenshot(d, 'pre-decryption') + d('input text "okc-gpg -d test.gpg"') + d.ui.press('enter') + screenshot(d, 'decryption') + wait_for(d, 'secret data') + wait_for(d, 'Verification result: RESULT_NO_SIGNATURE') + wait_for(d, 'Decryption result: RESULT_ENCRYPTED') + screenshot(d, 'decryption-success') + + # Test that nix-on-droid can use that GPG key through okc-gpg: signing + d('input text "echo signed data > test"') + d.ui.press('enter') + d('input text "okc-gpg -s test -o test.sig"') + d.ui.press('enter') + d('input text "okc-gpg -v test.sig"') + d.ui.press('enter') + screenshot(d, 'verification-attempt') + wait_for(d, 'secret data') + wait_for(d, 'Signature from: Test Key ') + wait_for(d, 'Created on: ') + wait_for(d, 'Verification result: RESULT_VALID_KEY_CONFIRMED') + screenshot(d, 'verification-success') diff --git a/tests/on-device/config-android-integration.nix b/tests/on-device/config-android-integration.nix index dd30d5e4..fbf163ea 100644 --- a/tests/on-device/config-android-integration.nix +++ b/tests/on-device/config-android-integration.nix @@ -11,6 +11,7 @@ _: termux-wake-lock.enable = true; termux-wake-unlock.enable = true; xdg-open.enable = true; + okc-gpg.enable = false; # building takes an eternity, tested separately # unsupported.enable = false; }; }