Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions modules/commands.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ let
# environment.
strOrPackage = import ../nix/strOrPackage.nix { inherit lib pkgs; };

writeDefaultShellScript = import ../nix/writeDefaultShellScript.nix {
inherit (pkgs) lib writeTextFile bash;
};

pad = str: num:
if num > 0 then
pad "${str} " (num - 1)
Expand All @@ -18,7 +22,12 @@ let
assert lib.assertMsg (cmd.command == null || cmd.name != cmd.command) "[[commands]]: ${toString cmd.name} cannot be set to both the `name` and the `command` attributes. Did you mean to use the `package` attribute?";
assert lib.assertMsg (cmd.package != null || (cmd.command != null && cmd.command != "")) "[[commands]]: ${name} expected either a command or package attribute.";
if cmd.package == null then
pkgs.writeShellScriptBin cmd.name cmd.command
writeDefaultShellScript
{
name = cmd.name;
text = cmd.command;
binPrefix = true;
}
else
cmd.package;

Expand Down Expand Up @@ -117,7 +126,15 @@ let
type = types.nullOr types.str;
default = null;
description = ''
If defined, it will define a script for the command.
If defined, it will add a script with the name of the command, and the
content of this value.

By default it generates a bash script, unless a different shebang is
provided.
'';
example = ''
#!/usr/bin/env python
print("Hello")
'';
};

Expand Down
26 changes: 26 additions & 0 deletions nix/writeDefaultShellScript.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{ lib, writeTextFile, bash }:

/*
* Similar to writeShellScript, except that a default shebang can be provided
*
* Either the script already has a shebang, or one will be provided for it.
*/
{ name
, text
, defaultShebang ? "#!${bash}/bin/bash\nset -euo pipefail\n"
, checkPhase ? null
, binPrefix ? false
}:
let
script =
if lib.hasPrefix "#!" then text
else "${defaultShebang}\n${text}";
in
writeTextFile (
{
inherit name text;
executable = true;
}
// (lib.optionalAttrs (checkPhase != null) { inherit checkPhase; })
// (lib.optionalAttrs binPrefix { destination = "/bin/${name}"; })
)
53 changes: 53 additions & 0 deletions tests/commands.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{ pkgs, devshell }:
{
# Basic devshell usage
commands-1 =
let
shell = devshell.mkShell {
devshell.name = "commands-1";
commands = [
{
name = "bash-script";
category = "hello";
help = "Prints hello-bash";
command = ''
echo "hello-bash"
'';
}
{
name = "python-script";
category = "hello";
help = "Prints hello-python";
command = ''
#!/usr/bin/env python3
print("hello-python")
'';
}
{
package = "git";
}
];
};
in
pkgs.runCommand "devshell-1" { } ''
# Load the devshell
source ${shell}

menu

# Checks that all the commands are available
type -p bash-script
type -p python-script
type -p git

[[ $(bash-script) == hello-bash ]]

# Check that the shebang is correct. We can't execute it inside of the
# sandbox because /usr/bin/env doesn't exist.
#
# Ideally it would be rewritten with patchShebang.
[[ $(head -n1 "$(type -p python-script)") == "#!/usr/bin/env python3" ]]

touch $out
'';
}
1 change: 1 addition & 0 deletions tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let
attrs = { inherit pkgs devshell; };
in
{ recurseForDerivations = true; }
// (import ./commands.nix attrs)
// (import ./devshell.nix attrs)
// (import ./git-hooks.nix attrs)
// (import ./modules-docs.nix attrs)
Expand Down