Merge pull request #19 from nix-community/rustrewrite

This commit is contained in:
Artturi 2022-04-19 01:50:24 +03:00 committed by GitHub
commit 0b4e4bc525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 426 additions and 167 deletions

73
,
View File

@ -1,73 +0,0 @@
#!/usr/bin/env bash
#
# usage example:
# $ , yarn --help
# This finds a derivation providing a bin/yarn, and runs it with `nix run`.
# If there are multiple candidates, the user chooses one using `fzy`.
set -euo pipefail
picker=fzy
if [ -n "${COMMA_PICKER+1}" ]; then
picker="${COMMA_PICKER}"
fi
# Test that the picker exists
if ! [ -x "$(command -v "${picker}")" ]; then
>&2 echo "picker ${picker} is not found in PATH"
exit 1
fi
if [[ $# -lt 1 ]]; then
>&2 echo "usage: , <program> [arguments]"
exit 1
fi
if [[ "$1" == "--install" ]] || [[ "$1" == "-i" ]]; then
install=1
shift
else
install=""
fi
argv0=$1; shift
case "${argv0}" in
@OVERLAY_PACKAGES@)
attr="${argv0}"
;;
*)
attr="$(nix-locate --top-level --minimal --at-root --whole-name "/bin/${argv0}")"
if [[ "$(echo "${attr}" | wc -l)" -ne 1 ]]; then
attr="$(echo "${attr}" | "${picker}")"
fi
;;
esac
if [[ -z $attr ]]; then
>&2 echo "no match"
exit 1
fi
# on flake based installations nixpkgs is specified via
# flake input and therefore NIX_PATH might be unset
if echo $NIX_PATH | grep -q "nixpkgs="; then
nixArgs=""
else
nixArgs="-I nixpkgs=${NIXPKGS}"
fi
if [[ -n $install ]]; then
nix-env $nixArgs -iA "nixpkgs.${attr%%.*}"
else
nix_version_greater_or_equal() {
local nix_version
nix_version=$(nix --version | cut -f3 -d ' ')
printf '%s\n%s' "$1" "$nix_version" | sort -C -V
}
if nix_version_greater_or_equal "2.4"; then
nix --extra-experimental-features 'nix-command flakes' shell "${NIXPKGS}#${attr}" -c "${argv0}" "$@"
else
nix run "nixpkgs.${attr}" -c "${argv0}" "$@"
fi
fi

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

12
.gitignore vendored
View File

@ -1,2 +1,14 @@
# ignore nix-build result folder
result
# Added by cargo
/target
# Added by cargo
#
# already existing elements were commented out
#/target

146
Cargo.lock generated Normal file
View File

@ -0,0 +1,146 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "clap"
version = "3.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aad2534fad53df1cc12519c5cda696dd3e20e6118a027e24054aea14a0bdcbe"
dependencies = [
"atty",
"bitflags",
"clap_lex",
"indexmap",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_lex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "comma"
version = "0.1.0"
dependencies = [
"clap",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "libc"
version = "0.2.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd"
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "comma"
description = "runs programs without installing them"
version = "0.1.0"
edition = "2021"
authors = ["Artturin <Artturin@artturin.com>"]
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = "3.1.9"

21
LICENSE
View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2020 Shopify
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,26 +1,30 @@
# ,
# comma
Comma runs software without installing it.
Basically it just wraps together `nix run` and `nix-index`. You stick a `,` in front of a command to
Basically it just wraps together `nix shell -c` and `nix-index`. You stick a `,` in front of a command to
run it from whatever location it happens to occupy in `nixpkgs` without really thinking about it.
## Installation
```bash
nix-env -i -f .
```
- Nix with [Flakes](https://nixos.wiki/wiki/Flakes):
```bash
$ nix profile install github:nix-community/comma
```
- No flakes:
```bash
$ nix-env -i -f "https://github.com/nix-community/comma/archive/master.tar.gz"
```
## Usage
[See a quick demo on
YouTube](https://www.youtube.com/watch?v=VUM3Km_4gUg&list=PLRGI9KQ3_HP_OFRG6R-p4iFgMSK1t5BHs)
```bash
, cowsay neato
```
## Prebuilt index
https://github.com/Mic92/nix-index-database

View File

@ -1,35 +1,10 @@
{ pkgs ? import <nixpkgs> { }
, stdenv ? pkgs.stdenv
, lib ? pkgs.lib
, fetchurl ? pkgs.fetchurl
, nix ? pkgs.nix
, fzy ? pkgs.fzy
, makeWrapper ? pkgs.makeWrapper
# We use this to add matchers for stuff that's not in upstream nixpkgs, but is
# in our own overlay. No fuzzy matching from multiple options here, it's just:
# Was the command `, mything`? Run `nixpkgs.mything`.
, overlayPackages ? []
}:
stdenv.mkDerivation rec {
name = "comma";
src = ./.;
nativeBuildInputs = [ makeWrapper ];
installPhase = let
caseCondition = lib.concatStringsSep "|" (overlayPackages ++ [ "--placeholder--" ]);
in ''
mkdir -p $out/bin
sed -e 's/@OVERLAY_PACKAGES@/${caseCondition}/' < , > $out/bin/,
chmod +x $out/bin/,
wrapProgram $out/bin/, \
--prefix PATH : ${nix}/bin \
--prefix PATH : ${fzy}/bin
ln -s $out/bin/, $out/bin/comma
'';
}
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).defaultNix

View File

@ -1,23 +1,79 @@
{
"nodes": {
"nixpkgs": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1638110343,
"narHash": "sha256-hQaow8sGPyUrXgrqgDRsfA+73uR0vms2goTQNxIAaRQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "942eb9a335b4cd22fa6a7be31c494e53e76f5637",
"lastModified": 1648199409,
"narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "64a525ee38886ab9028e6f61790de0832aa3ef03",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1650101877,
"narHash": "sha256-IYxYc5Z1ZHQDTQbTWsOZ9HlZepsVjgV5oZwmbKzxSJs=",
"owner": "nix-community",
"repo": "naersk",
"rev": "8cc379478819e6a22ce7595a761fe1e17c8d7458",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1650109093,
"narHash": "sha256-tqlnKrAdJktRLXTou9le0oTqrYBAFpGscV5RADdpArU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "faad370edcb37162401be50d45526f52bb16a713",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
"flake-compat": "flake-compat",
"naersk": "naersk",
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"utils": {
"locked": {
"lastModified": 1649676176,
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},

View File

@ -1,28 +1,50 @@
{
description = "Comma runs software without installing it";
description = "runs programs without installing them";
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
naersk = {
url = "github:nix-community/naersk/master";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
utils.url = "github:numtide/flake-utils";
flake-compat = {
url = github:edolstra/flake-compat;
flake = false;
};
};
outputs = { self, nixpkgs, }:
let
b = builtins;
lib = nixpkgs.lib;
supportedSystems = lib.systems.supported.hydra;
forAllSystems = f: lib.genAttrs supportedSystems
(system: f system (import nixpkgs { inherit system; }));
in
rec {
outputs = { self, nixpkgs, utils, naersk, flake-compat }:
utils.lib.eachDefaultSystem (system:
let
inherit (nixpkgs) lib;
pkgs = nixpkgs.legacyPackages.${system};
naersk-lib = pkgs.callPackage naersk { };
in
{
packages = {
default = self.packages."${system}".comma;
comma = naersk-lib.buildPackage {
pname = "comma";
root = ./.;
nativeBuildInputs = with pkgs; [ makeWrapper ];
overrideMain = _: {
postInstall = ''
wrapProgram $out/bin/comma \
--prefix PATH : ${lib.makeBinPath (with pkgs; [ nix fzy ])}
ln -s $out/bin/comma $out/bin/,
'';
};
};
};
packages = forAllSystems
(system: pkgs: {
comma = import ./default.nix {
inherit pkgs;
apps.default = utils.lib.mkApp {
drv = self.packages."${system}".default;
};
devShells.default = with pkgs; mkShell {
nativeBuildInputs = [ cargo rustc rustfmt rustPackages.clippy fzy ];
RUST_SRC_PATH = rustPlatform.rustLibSrc;
};
});
defaultPackage = forAllSystems (system: pkgs: packages."${system}".comma);
};
}

10
shell.nix Normal file
View File

@ -0,0 +1,10 @@
(import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; }
).shellNix

115
src/main.rs Normal file
View File

@ -0,0 +1,115 @@
use std::{
env,
io::Write,
os::unix::prelude::CommandExt,
process::{exit, Command, Stdio},
};
use clap::{arg, Arg};
fn pick(picker: &str, derivations: Vec<&str>) -> String {
let mut picker_process = Command::new(&picker)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap_or_else(|err| panic!("failed to execute {}: {}", picker, err));
let picker_stdin = picker_process.stdin.as_mut().unwrap();
picker_stdin
.write_all(derivations.join("\n").as_bytes())
.expect("failure to write stdin");
let output = picker_process.wait_with_output().unwrap().stdout;
if output.is_empty() {
exit(1)
}
std::str::from_utf8(&output)
.expect("fail")
.trim()
.to_string()
}
fn run_command(use_channel: bool, choice: &str, command: &str, trail: Vec<&str>) {
let mut run_cmd = Command::new("nix");
run_cmd.args([
"--extra-experimental-features",
"nix-command flakes",
"shell",
]);
if use_channel {
run_cmd.args(["-f", "<nixpkgs>", choice]);
} else {
run_cmd.args([format!("nixpkgs#{}", choice)]);
}
run_cmd.args(["--command", command]);
run_cmd.args(trail);
run_cmd.exec();
}
fn main() {
let matches = clap::Command::new("comma")
.about("runs programs without installing them")
.arg(
Arg::new("install")
.short('i')
.long("install")
.takes_value(false)
.help("install the derivation containing the executable"),
)
.trailing_var_arg(true)
.arg(arg!(<cmd> ... "command to run"))
.get_matches();
let picker = match env::var("COMMA_PICKER") {
Ok(val) => val,
Err(_) => "fzy".to_string(),
};
let install = matches.is_present("install");
let mut trail: Vec<&str> = matches.values_of("cmd").unwrap().collect();
let command: String = trail.remove(0).to_string();
let attrs = Command::new("nix-locate")
.args(["--top-level", "--minimal", "--at-root", "--whole-name"])
.arg(format!("/bin/{}", command))
.output()
.expect("failed to execute nix-locate")
.stdout;
if attrs.is_empty() {
eprintln!("no match");
std::process::exit(1)
}
let attrs: Vec<&str> = std::str::from_utf8(&attrs)
.expect("fail")
.trim()
.split('\n')
.collect();
let choice = if attrs.len() != 1 {
pick(&picker, attrs)
} else {
attrs.first().unwrap().trim().to_string()
};
let use_channel = (match env::var("NIX_PATH") {
Ok(val) => val,
Err(_) => "".to_string(),
})
.contains("nixpkgs");
if install {
Command::new("nix-env")
.args(["-f", "<nixpkgs>", "-iA", choice.rsplit('.').last().unwrap()])
.exec();
} else {
run_command(use_channel, &choice, &command, trail)
}
}