feat(users/Profpatsch): set up stow for nix-home

nix-home is (hopefully) gonna be a home-manager alternative for my
home directory.

Files are symlinked into the home directory via GNU stow (since that
is a tried and tested tool), so first step is to set up the base code
for that.

Implements a small tool that reads a single environment variable and
prints it to stdout.

Change-Id: Ifa3fd9f9e1cedc52c3002196d3971b02cb840e80
Reviewed-on: https://cl.tvl.fyi/c/depot/+/4832
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
Autosubmit: Profpatsch <mail@profpatsch.de>
This commit is contained in:
Profpatsch 2022-01-09 01:20:46 +01:00
parent e1044c1559
commit fed41f4959
3 changed files with 115 additions and 0 deletions

View file

@ -5,8 +5,29 @@ let
name = "exec-helpers";
} (builtins.readFile ./exec_helpers.rs);
print-one-env = depot.nix.writers.rustSimple {
name = "print-one-env";
dependencies = [
depot.users.Profpatsch.execline.exec-helpers
];
} ''
extern crate exec_helpers;
use std::os::unix::ffi::OsStrExt;
use std::io::Write;
fn main() {
let args = exec_helpers::args("print-one-env", 1);
let valname = std::ffi::OsStr::from_bytes(&args[0]);
match std::env::var_os(&valname) {
None => exec_helpers::die_user_error("print-one-env", format!("Env variable `{:?}` is not set", valname)),
Some(val) => std::io::stdout().write_all(&val.as_bytes()).unwrap()
}
}
'';
in depot.nix.readTree.drvTargets {
inherit
exec-helpers
print-one-env
;
}

View file

@ -57,6 +57,9 @@ let
in depot.nix.readTree.drvTargets {
inherit
toNetstring
toNetstringList
toNetstringKeyVal
python-netstring
rust-netstring
;

View file

@ -0,0 +1,91 @@
{ depot, pkgs, lib, ... }:
let
bins = depot.nix.getBins pkgs.stow [ "stow" ]
// depot.nix.getBins pkgs.coreutils [ "mkdir" "ln" "printenv" "rm" ]
// depot.nix.getBins pkgs.xe [ "xe" ]
// depot.nix.getBins pkgs.lr [ "lr" ]
;
# run stow to populate the target directory with the given stow package, read from stowDir.
# Bear in mind that `stowDirOriginPath` should always be semantically bound to the given `stowDir`, otherwise stow might become rather confused.
runStow = {
# “stow package” to stow (see manpage)
stowPackage,
# “target directory” to stow in (see manpage)
targetDir,
# The “stow directory” (see manpage), containing “stow packages” (see manpage)
stowDir,
# representative directory for the stowDir in the file system, against which stow will create relative links.
# ATTN: this is always overwritten with the contents of `stowDir`! You shouldnt re-use the same `stowDirOriginPath` for different `stowDir`s, otherwise there might be surprises.
stowDirOriginPath,
}: depot.nix.writeExecline "stow-${stowPackage}" {} [
# first, create a temporary stow directory to use as source
# (stow will use it to determine the origin of files)
"if" [ bins.mkdir "-p" stowDirOriginPath ]
# remove old symlinks
"if" [
"pipeline" [
bins.lr "-0" "-t" "depth == 1 && type == l" stowDirOriginPath
]
bins.xe "-0" bins.rm
]
# populate with new stow targets
"if" [
"elglob" "-w0" "stowPackages" "${stowDir}/*"
bins.ln "--force" "-st" stowDirOriginPath "$stowPackages"
]
# stow always looks for $HOME/.stowrc to read more arguments
"export" "HOME" "/homeless-shelter"
bins.stow
# always run restow for now; this does more stat but will remove stale links
"--restow"
"--dir" stowDirOriginPath
"--target" targetDir
stowPackage
];
# create a stow dir from a list of drv paths and a stow package name.
makeStowDir =
(with depot.nix.yants;
defun
[ (list (struct {
originalDir = drv;
stowPackage = string;
}))
drv
] )
(dirs:
depot.nix.runExecline "make-stow-dir" {
stdin = lib.pipe dirs [
(map depot.users.Profpatsch.netencode.gen.dwim)
depot.users.Profpatsch.netstring.toNetstringList
];
} [
"importas" "out" "out"
"if" [ bins.mkdir "-p" "$out" ]
"forstdin" "-d" "" "-o" "0" "line"
"pipeline" [
depot.users.Profpatsch.execline.print-one-env "line"
]
depot.users.Profpatsch.netencode.record-splice-env
"importas" "-ui" "originalDir" "originalDir"
"importas" "-ui" "stowPackage" "stowPackage"
bins.ln "-sT" "$originalDir" "\${out}/\${stowPackage}"
]);
in
# TODO: temp
lib.pipe {} [
(_: makeStowDir [{
stowPackage = "hello";
originalDir = pkgs.hello;
}])
(d: runStow {
stowDir = d;
stowPackage = "hello";
targetDir = "/home/philip/tmp";
stowDirOriginPath = "/home/philip/tmp/stowOrigin";
})
]