cmd: remove hpkg
All checks were successful
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m30s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m48s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m54s
Test / Flake checks (push) Successful in 1m28s
All checks were successful
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m30s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m48s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m54s
Test / Flake checks (push) Successful in 1m28s
This proof-of-concept was abandoned long ago. Its test suite is flaky, heavy on I/O and does not increase test coverage. This change fully removes hpkg and supporting code. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -89,23 +89,6 @@ jobs:
|
|||||||
path: result/*
|
path: result/*
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
hpkg:
|
|
||||||
name: Hpkg
|
|
||||||
runs-on: nix
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Run NixOS test
|
|
||||||
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.hpkg
|
|
||||||
|
|
||||||
- name: Upload test output
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "hpkg-vm-output"
|
|
||||||
path: result/*
|
|
||||||
retention-days: 1
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
name: Flake checks
|
name: Flake checks
|
||||||
needs:
|
needs:
|
||||||
@@ -114,7 +97,6 @@ jobs:
|
|||||||
- sandbox
|
- sandbox
|
||||||
- sandbox-race
|
- sandbox-race
|
||||||
- sharefs
|
- sharefs
|
||||||
- hpkg
|
|
||||||
runs-on: nix
|
runs-on: nix
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
This program is a proof of concept and is now deprecated. It is only kept
|
|
||||||
around for API demonstration purposes and to make the most out of the test
|
|
||||||
suite.
|
|
||||||
|
|
||||||
This program is replaced by planterette, which can be found at
|
|
||||||
https://git.gensokyo.uk/security/planterette. Development effort should be
|
|
||||||
focused there instead.
|
|
||||||
173
cmd/hpkg/app.go
173
cmd/hpkg/app.go
@@ -1,173 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"hakurei.app/container/check"
|
|
||||||
"hakurei.app/container/fhs"
|
|
||||||
"hakurei.app/hst"
|
|
||||||
)
|
|
||||||
|
|
||||||
type appInfo struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
ID string `json:"id"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Identity int `json:"identity"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Devel bool `json:"devel,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Userns bool `json:"userns,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
HostNet bool `json:"net,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
HostAbstract bool `json:"abstract,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Device bool `json:"dev,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Tty bool `json:"tty,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
MapRealUID bool `json:"map_real_uid,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
DirectWayland bool `json:"direct_wayland,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
SystemBus *hst.BusConfig `json:"system_bus,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
SessionBus *hst.BusConfig `json:"session_bus,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Enablements *hst.Enablements `json:"enablements,omitempty"`
|
|
||||||
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Multiarch bool `json:"multiarch,omitempty"`
|
|
||||||
// passed through to [hst.Config]
|
|
||||||
Bluetooth bool `json:"bluetooth,omitempty"`
|
|
||||||
|
|
||||||
// allow gpu access within sandbox
|
|
||||||
GPU bool `json:"gpu"`
|
|
||||||
// store path to nixGL mesa wrappers
|
|
||||||
Mesa string `json:"mesa,omitempty"`
|
|
||||||
// store path to nixGL source
|
|
||||||
NixGL string `json:"nix_gl,omitempty"`
|
|
||||||
// store path to activate-and-exec script
|
|
||||||
Launcher *check.Absolute `json:"launcher"`
|
|
||||||
// store path to /run/current-system
|
|
||||||
CurrentSystem *check.Absolute `json:"current_system"`
|
|
||||||
// store path to home-manager activation package
|
|
||||||
ActivationPackage string `json:"activation_package"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *appInfo) toHst(pathSet *appPathSet, pathname *check.Absolute, argv []string, flagDropShell bool) *hst.Config {
|
|
||||||
config := &hst.Config{
|
|
||||||
ID: app.ID,
|
|
||||||
|
|
||||||
Enablements: app.Enablements,
|
|
||||||
|
|
||||||
SystemBus: app.SystemBus,
|
|
||||||
SessionBus: app.SessionBus,
|
|
||||||
DirectWayland: app.DirectWayland,
|
|
||||||
|
|
||||||
Identity: app.Identity,
|
|
||||||
Groups: app.Groups,
|
|
||||||
|
|
||||||
Container: &hst.ContainerConfig{
|
|
||||||
Hostname: formatHostname(app.Name),
|
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append("store"), Target: pathNixStore}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: pathSet.metaPath, Target: hst.AbsPrivateTmp.Append("app")}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
|
|
||||||
},
|
|
||||||
|
|
||||||
Username: "hakurei",
|
|
||||||
Shell: pathShell,
|
|
||||||
Home: pathDataData.Append(app.ID),
|
|
||||||
|
|
||||||
Path: pathname,
|
|
||||||
Args: argv,
|
|
||||||
},
|
|
||||||
ExtraPerms: []hst.ExtraPermConfig{
|
|
||||||
{Path: dataHome, Execute: true},
|
|
||||||
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if app.Devel {
|
|
||||||
config.Container.Flags |= hst.FDevel
|
|
||||||
}
|
|
||||||
if app.Userns {
|
|
||||||
config.Container.Flags |= hst.FUserns
|
|
||||||
}
|
|
||||||
if app.HostNet {
|
|
||||||
config.Container.Flags |= hst.FHostNet
|
|
||||||
}
|
|
||||||
if app.HostAbstract {
|
|
||||||
config.Container.Flags |= hst.FHostAbstract
|
|
||||||
}
|
|
||||||
if app.Device {
|
|
||||||
config.Container.Flags |= hst.FDevice
|
|
||||||
}
|
|
||||||
if app.Tty || flagDropShell {
|
|
||||||
config.Container.Flags |= hst.FTty
|
|
||||||
}
|
|
||||||
if app.MapRealUID {
|
|
||||||
config.Container.Flags |= hst.FMapRealUID
|
|
||||||
}
|
|
||||||
if app.Multiarch {
|
|
||||||
config.Container.Flags |= hst.FMultiarch
|
|
||||||
}
|
|
||||||
config.Container.Flags |= hst.FShareRuntime | hst.FShareTmpdir
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadAppInfo(name string, beforeFail func()) *appInfo {
|
|
||||||
bundle := new(appInfo)
|
|
||||||
if f, err := os.Open(name); err != nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot open bundle: %v", err)
|
|
||||||
} else if err = json.NewDecoder(f).Decode(&bundle); err != nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot parse bundle metadata: %v", err)
|
|
||||||
} else if err = f.Close(); err != nil {
|
|
||||||
log.Printf("cannot close bundle metadata: %v", err)
|
|
||||||
// not fatal
|
|
||||||
}
|
|
||||||
|
|
||||||
if bundle.ID == "" {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatal("application identifier must not be empty")
|
|
||||||
}
|
|
||||||
if bundle.Launcher == nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatal("launcher must not be empty")
|
|
||||||
}
|
|
||||||
if bundle.CurrentSystem == nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatal("current-system must not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatHostname(name string) string {
|
|
||||||
if h, err := os.Hostname(); err != nil {
|
|
||||||
log.Printf("cannot get hostname: %v", err)
|
|
||||||
return "hakurei-" + name
|
|
||||||
} else {
|
|
||||||
return h + "-" + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
{
|
|
||||||
nixpkgsFor,
|
|
||||||
system,
|
|
||||||
nixpkgs,
|
|
||||||
home-manager,
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
closureInfo,
|
|
||||||
writeScript,
|
|
||||||
runtimeShell,
|
|
||||||
writeText,
|
|
||||||
symlinkJoin,
|
|
||||||
vmTools,
|
|
||||||
runCommand,
|
|
||||||
fetchFromGitHub,
|
|
||||||
|
|
||||||
zstd,
|
|
||||||
nix,
|
|
||||||
sqlite,
|
|
||||||
|
|
||||||
name ? throw "name is required",
|
|
||||||
version ? throw "version is required",
|
|
||||||
pname ? "${name}-${version}",
|
|
||||||
modules ? [ ],
|
|
||||||
nixosModules ? [ ],
|
|
||||||
script ? ''
|
|
||||||
exec "$SHELL" "$@"
|
|
||||||
'',
|
|
||||||
|
|
||||||
id ? name,
|
|
||||||
identity ? throw "identity is required",
|
|
||||||
groups ? [ ],
|
|
||||||
userns ? false,
|
|
||||||
net ? true,
|
|
||||||
dev ? false,
|
|
||||||
no_new_session ? false,
|
|
||||||
map_real_uid ? false,
|
|
||||||
direct_wayland ? false,
|
|
||||||
system_bus ? null,
|
|
||||||
session_bus ? null,
|
|
||||||
|
|
||||||
allow_wayland ? true,
|
|
||||||
allow_x11 ? false,
|
|
||||||
allow_dbus ? true,
|
|
||||||
allow_audio ? true,
|
|
||||||
gpu ? allow_wayland || allow_x11,
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) optionals;
|
|
||||||
|
|
||||||
homeManagerConfiguration = home-manager.lib.homeManagerConfiguration {
|
|
||||||
pkgs = nixpkgsFor.${system};
|
|
||||||
modules = modules ++ [
|
|
||||||
{
|
|
||||||
home = {
|
|
||||||
username = "hakurei";
|
|
||||||
homeDirectory = "/data/data/${id}";
|
|
||||||
stateVersion = "22.11";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
launcher = writeScript "hakurei-${pname}" ''
|
|
||||||
#!${runtimeShell} -el
|
|
||||||
${script}
|
|
||||||
'';
|
|
||||||
|
|
||||||
extraNixOSConfig =
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
environment = {
|
|
||||||
etc.nixpkgs.source = nixpkgs.outPath;
|
|
||||||
systemPackages = [ pkgs.nix ];
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = nixosModules;
|
|
||||||
};
|
|
||||||
nixos = nixpkgs.lib.nixosSystem {
|
|
||||||
inherit system;
|
|
||||||
modules = [
|
|
||||||
extraNixOSConfig
|
|
||||||
{ nix.settings.experimental-features = [ "flakes" ]; }
|
|
||||||
{ nix.settings.experimental-features = [ "nix-command" ]; }
|
|
||||||
{ boot.isContainer = true; }
|
|
||||||
{ system.stateVersion = "22.11"; }
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
etc = vmTools.runInLinuxVM (
|
|
||||||
runCommand "etc" { } ''
|
|
||||||
mkdir -p /etc
|
|
||||||
${nixos.config.system.build.etcActivationCommands}
|
|
||||||
|
|
||||||
# remove unused files
|
|
||||||
rm -rf /etc/sudoers
|
|
||||||
|
|
||||||
mkdir -p $out
|
|
||||||
tar -C /etc -cf "$out/etc.tar" .
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
extendSessionDefault = id: ext: {
|
|
||||||
filter = true;
|
|
||||||
|
|
||||||
talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
|
|
||||||
own =
|
|
||||||
(optionals (id != null) [
|
|
||||||
"${id}.*"
|
|
||||||
"org.mpris.MediaPlayer2.${id}.*"
|
|
||||||
])
|
|
||||||
++ ext.own;
|
|
||||||
|
|
||||||
inherit (ext) call broadcast;
|
|
||||||
};
|
|
||||||
|
|
||||||
nixGL = fetchFromGitHub {
|
|
||||||
owner = "nix-community";
|
|
||||||
repo = "nixGL";
|
|
||||||
rev = "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a";
|
|
||||||
hash = "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=";
|
|
||||||
};
|
|
||||||
|
|
||||||
mesaWrappers =
|
|
||||||
let
|
|
||||||
isIntelX86Platform = system == "x86_64-linux";
|
|
||||||
nixGLPackages = import (nixGL + "/default.nix") {
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
enable32bits = isIntelX86Platform;
|
|
||||||
enableIntelX86Extensions = isIntelX86Platform;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
symlinkJoin {
|
|
||||||
name = "nixGL-mesa";
|
|
||||||
paths = with nixGLPackages; [
|
|
||||||
nixGLIntel
|
|
||||||
nixVulkanIntel
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
info = builtins.toJSON {
|
|
||||||
inherit
|
|
||||||
name
|
|
||||||
version
|
|
||||||
id
|
|
||||||
identity
|
|
||||||
launcher
|
|
||||||
groups
|
|
||||||
userns
|
|
||||||
net
|
|
||||||
dev
|
|
||||||
no_new_session
|
|
||||||
map_real_uid
|
|
||||||
direct_wayland
|
|
||||||
system_bus
|
|
||||||
gpu
|
|
||||||
;
|
|
||||||
|
|
||||||
session_bus =
|
|
||||||
if session_bus != null then
|
|
||||||
(session_bus (extendSessionDefault id))
|
|
||||||
else
|
|
||||||
(extendSessionDefault id {
|
|
||||||
talk = [ ];
|
|
||||||
own = [ ];
|
|
||||||
call = { };
|
|
||||||
broadcast = { };
|
|
||||||
});
|
|
||||||
|
|
||||||
enablements = {
|
|
||||||
wayland = allow_wayland;
|
|
||||||
x11 = allow_x11;
|
|
||||||
dbus = allow_dbus;
|
|
||||||
pipewire = allow_audio;
|
|
||||||
};
|
|
||||||
|
|
||||||
mesa = if gpu then mesaWrappers else null;
|
|
||||||
nix_gl = if gpu then nixGL else null;
|
|
||||||
current_system = nixos.config.system.build.toplevel;
|
|
||||||
activation_package = homeManagerConfiguration.activationPackage;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "${pname}.pkg";
|
|
||||||
inherit version;
|
|
||||||
__structuredAttrs = true;
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
|
||||||
zstd
|
|
||||||
nix
|
|
||||||
sqlite
|
|
||||||
];
|
|
||||||
|
|
||||||
buildCommand = ''
|
|
||||||
NIX_ROOT="$(mktemp -d)"
|
|
||||||
export USER="nobody"
|
|
||||||
|
|
||||||
# create bootstrap store
|
|
||||||
bootstrapClosureInfo="${
|
|
||||||
closureInfo {
|
|
||||||
rootPaths = [
|
|
||||||
nix
|
|
||||||
nixos.config.system.build.toplevel
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
echo "copying bootstrap store paths..."
|
|
||||||
mkdir -p "$NIX_ROOT/nix/store"
|
|
||||||
xargs -n 1 -a "$bootstrapClosureInfo/store-paths" cp -at "$NIX_ROOT/nix/store/"
|
|
||||||
NIX_REMOTE="local?root=$NIX_ROOT" nix-store --load-db < "$bootstrapClosureInfo/registration"
|
|
||||||
NIX_REMOTE="local?root=$NIX_ROOT" nix-store --optimise
|
|
||||||
sqlite3 "$NIX_ROOT/nix/var/nix/db/db.sqlite" "UPDATE ValidPaths SET registrationTime = ''${SOURCE_DATE_EPOCH}"
|
|
||||||
chmod -R +r "$NIX_ROOT/nix/var"
|
|
||||||
|
|
||||||
# create binary cache
|
|
||||||
closureInfo="${
|
|
||||||
closureInfo {
|
|
||||||
rootPaths = [
|
|
||||||
homeManagerConfiguration.activationPackage
|
|
||||||
launcher
|
|
||||||
]
|
|
||||||
++ optionals gpu [
|
|
||||||
mesaWrappers
|
|
||||||
nixGL
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
echo "copying application paths..."
|
|
||||||
TMP_STORE="$(mktemp -d)"
|
|
||||||
mkdir -p "$TMP_STORE/nix/store"
|
|
||||||
xargs -n 1 -a "$closureInfo/store-paths" cp -at "$TMP_STORE/nix/store/"
|
|
||||||
NIX_REMOTE="local?root=$TMP_STORE" nix-store --load-db < "$closureInfo/registration"
|
|
||||||
sqlite3 "$TMP_STORE/nix/var/nix/db/db.sqlite" "UPDATE ValidPaths SET registrationTime = ''${SOURCE_DATE_EPOCH}"
|
|
||||||
NIX_REMOTE="local?root=$TMP_STORE" nix --offline --extra-experimental-features nix-command \
|
|
||||||
--verbose --log-format raw-with-logs \
|
|
||||||
copy --all --no-check-sigs --to \
|
|
||||||
"file://$NIX_ROOT/res?compression=zstd&compression-level=19¶llel-compression=true"
|
|
||||||
|
|
||||||
# package /etc
|
|
||||||
mkdir -p "$NIX_ROOT/etc"
|
|
||||||
tar -C "$NIX_ROOT/etc" -xf "${etc}/etc.tar"
|
|
||||||
|
|
||||||
# write metadata
|
|
||||||
cp "${writeText "bundle.json" info}" "$NIX_ROOT/bundle.json"
|
|
||||||
|
|
||||||
# create an intermediate file to improve zstd performance
|
|
||||||
INTER="$(mktemp)"
|
|
||||||
tar -C "$NIX_ROOT" -cf "$INTER" .
|
|
||||||
zstd -T0 -19 -fo "$out" "$INTER"
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
335
cmd/hpkg/main.go
335
cmd/hpkg/main.go
@@ -1,335 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"path"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"hakurei.app/command"
|
|
||||||
"hakurei.app/container/check"
|
|
||||||
"hakurei.app/container/fhs"
|
|
||||||
"hakurei.app/hst"
|
|
||||||
"hakurei.app/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errSuccess = errors.New("success")
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetPrefix("hpkg: ")
|
|
||||||
log.SetFlags(0)
|
|
||||||
msg := message.New(log.Default())
|
|
||||||
|
|
||||||
if err := os.Setenv("SHELL", pathShell.String()); err != nil {
|
|
||||||
log.Fatalf("cannot set $SHELL: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if os.Geteuid() == 0 {
|
|
||||||
log.Fatal("this program must not run as root")
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, stop := signal.NotifyContext(context.Background(),
|
|
||||||
syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
defer stop() // unreachable
|
|
||||||
|
|
||||||
var (
|
|
||||||
flagVerbose bool
|
|
||||||
flagDropShell bool
|
|
||||||
)
|
|
||||||
c := command.New(os.Stderr, log.Printf, "hpkg", func([]string) error { msg.SwapVerbose(flagVerbose); return nil }).
|
|
||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
|
|
||||||
Flag(&flagDropShell, "s", command.BoolFlag(false), "Drop to a shell in place of next hakurei action")
|
|
||||||
|
|
||||||
{
|
|
||||||
var (
|
|
||||||
flagDropShellActivate bool
|
|
||||||
)
|
|
||||||
c.NewCommand("install", "Install an application from its package", func(args []string) error {
|
|
||||||
if len(args) != 1 {
|
|
||||||
log.Println("invalid argument")
|
|
||||||
return syscall.EINVAL
|
|
||||||
}
|
|
||||||
pkgPath := args[0]
|
|
||||||
if !path.IsAbs(pkgPath) {
|
|
||||||
if dir, err := os.Getwd(); err != nil {
|
|
||||||
log.Printf("cannot get current directory: %v", err)
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
pkgPath = path.Join(dir, pkgPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Look up paths to programs started by hpkg.
|
|
||||||
This is done here to ease error handling as cleanup is not yet required.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ = lookPath("zstd")
|
|
||||||
tar = lookPath("tar")
|
|
||||||
chmod = lookPath("chmod")
|
|
||||||
rm = lookPath("rm")
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Extract package and set up for cleanup.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var workDir *check.Absolute
|
|
||||||
if p, err := os.MkdirTemp("", "hpkg.*"); err != nil {
|
|
||||||
log.Printf("cannot create temporary directory: %v", err)
|
|
||||||
return err
|
|
||||||
} else if workDir, err = check.NewAbs(p); err != nil {
|
|
||||||
log.Printf("invalid temporary directory: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cleanup := func() {
|
|
||||||
// should be faster than a native implementation
|
|
||||||
mustRun(msg, chmod, "-R", "+w", workDir.String())
|
|
||||||
mustRun(msg, rm, "-rf", workDir.String())
|
|
||||||
}
|
|
||||||
beforeRunFail.Store(&cleanup)
|
|
||||||
|
|
||||||
mustRun(msg, tar, "-C", workDir.String(), "-xf", pkgPath)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Parse bundle and app metadata, do pre-install checks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bundle := loadAppInfo(path.Join(workDir.String(), "bundle.json"), cleanup)
|
|
||||||
pathSet := pathSetByApp(bundle.ID)
|
|
||||||
|
|
||||||
a := bundle
|
|
||||||
if s, err := os.Stat(pathSet.metaPath.String()); err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("cannot access %q: %v", pathSet.metaPath, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// did not modify app, clean installation condition met later
|
|
||||||
} else if s.IsDir() {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("metadata path %q is not a file", pathSet.metaPath)
|
|
||||||
return syscall.EBADMSG
|
|
||||||
} else {
|
|
||||||
a = loadAppInfo(pathSet.metaPath.String(), cleanup)
|
|
||||||
if a.ID != bundle.ID {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("app %q claims to have identifier %q",
|
|
||||||
bundle.ID, a.ID)
|
|
||||||
return syscall.EBADE
|
|
||||||
}
|
|
||||||
// sec: should verify credentials
|
|
||||||
}
|
|
||||||
|
|
||||||
if a != bundle {
|
|
||||||
// do not try to re-install
|
|
||||||
if a.NixGL == bundle.NixGL &&
|
|
||||||
a.CurrentSystem == bundle.CurrentSystem &&
|
|
||||||
a.Launcher == bundle.Launcher &&
|
|
||||||
a.ActivationPackage == bundle.ActivationPackage {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("package %q is identical to local application %q",
|
|
||||||
pkgPath, a.ID)
|
|
||||||
return errSuccess
|
|
||||||
}
|
|
||||||
|
|
||||||
// identity determines uid
|
|
||||||
if a.Identity != bundle.Identity {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("package %q identity %d differs from installed %d",
|
|
||||||
pkgPath, bundle.Identity, a.Identity)
|
|
||||||
return syscall.EBADE
|
|
||||||
}
|
|
||||||
|
|
||||||
// sec: should compare version string
|
|
||||||
msg.Verbosef("installing application %q version %q over local %q",
|
|
||||||
bundle.ID, bundle.Version, a.Version)
|
|
||||||
} else {
|
|
||||||
msg.Verbosef("application %q clean installation", bundle.ID)
|
|
||||||
// sec: should install credentials
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Setup steps for files owned by the target user.
|
|
||||||
*/
|
|
||||||
|
|
||||||
withCacheDir(ctx, msg, "install", []string{
|
|
||||||
// export inner bundle path in the environment
|
|
||||||
"export BUNDLE=" + hst.PrivateTmp + "/bundle",
|
|
||||||
// replace inner /etc
|
|
||||||
"mkdir -p etc",
|
|
||||||
"chmod -R +w etc",
|
|
||||||
"rm -rf etc",
|
|
||||||
"cp -dRf $BUNDLE/etc etc",
|
|
||||||
// replace inner /nix
|
|
||||||
"mkdir -p nix",
|
|
||||||
"chmod -R +w nix",
|
|
||||||
"rm -rf nix",
|
|
||||||
"cp -dRf /nix nix",
|
|
||||||
// copy from binary cache
|
|
||||||
"nix copy --offline --no-check-sigs --all --from file://$BUNDLE/res --to $PWD",
|
|
||||||
// deduplicate nix store
|
|
||||||
"nix store --offline --store $PWD optimise",
|
|
||||||
// make cache directory world-readable for autoetc
|
|
||||||
"chmod 0755 .",
|
|
||||||
}, workDir, bundle, pathSet, flagDropShell, cleanup)
|
|
||||||
|
|
||||||
if bundle.GPU {
|
|
||||||
withCacheDir(ctx, msg, "mesa-wrappers", []string{
|
|
||||||
// link nixGL mesa wrappers
|
|
||||||
"mkdir -p nix/.nixGL",
|
|
||||||
"ln -s " + bundle.Mesa + "/bin/nixGLIntel nix/.nixGL/nixGL",
|
|
||||||
"ln -s " + bundle.Mesa + "/bin/nixVulkanIntel nix/.nixGL/nixVulkan",
|
|
||||||
}, workDir, bundle, pathSet, false, cleanup)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Activate home-manager generation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
withNixDaemon(ctx, msg, "activate", []string{
|
|
||||||
// clean up broken links
|
|
||||||
"mkdir -p .local/state/{nix,home-manager}",
|
|
||||||
"chmod -R +w .local/state/{nix,home-manager}",
|
|
||||||
"rm -rf .local/state/{nix,home-manager}",
|
|
||||||
// run activation script
|
|
||||||
bundle.ActivationPackage + "/activate",
|
|
||||||
}, false, func(config *hst.Config) *hst.Config { return config },
|
|
||||||
bundle, pathSet, flagDropShellActivate, cleanup)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Installation complete. Write metadata to block re-installs or downgrades.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// serialise metadata to ensure consistency
|
|
||||||
if f, err := os.OpenFile(pathSet.metaPath.String()+"~", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err != nil {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("cannot create metadata file: %v", err)
|
|
||||||
return err
|
|
||||||
} else if err = json.NewEncoder(f).Encode(bundle); err != nil {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("cannot write metadata: %v", err)
|
|
||||||
return err
|
|
||||||
} else if err = f.Close(); err != nil {
|
|
||||||
log.Printf("cannot close metadata file: %v", err)
|
|
||||||
// not fatal
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Rename(pathSet.metaPath.String()+"~", pathSet.metaPath.String()); err != nil {
|
|
||||||
cleanup()
|
|
||||||
log.Printf("cannot rename metadata file: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup()
|
|
||||||
return errSuccess
|
|
||||||
}).
|
|
||||||
Flag(&flagDropShellActivate, "s", command.BoolFlag(false), "Drop to a shell on activation")
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var (
|
|
||||||
flagDropShellNixGL bool
|
|
||||||
flagAutoDrivers bool
|
|
||||||
)
|
|
||||||
c.NewCommand("start", "Start an application", func(args []string) error {
|
|
||||||
if len(args) < 1 {
|
|
||||||
log.Println("invalid argument")
|
|
||||||
return syscall.EINVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Parse app metadata.
|
|
||||||
*/
|
|
||||||
|
|
||||||
id := args[0]
|
|
||||||
pathSet := pathSetByApp(id)
|
|
||||||
a := loadAppInfo(pathSet.metaPath.String(), func() {})
|
|
||||||
if a.ID != id {
|
|
||||||
log.Printf("app %q claims to have identifier %q", id, a.ID)
|
|
||||||
return syscall.EBADE
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Prepare nixGL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if a.GPU && flagAutoDrivers {
|
|
||||||
withNixDaemon(ctx, msg, "nix-gl", []string{
|
|
||||||
"mkdir -p /nix/.nixGL/auto",
|
|
||||||
"rm -rf /nix/.nixGL/auto",
|
|
||||||
"export NIXPKGS_ALLOW_UNFREE=1",
|
|
||||||
"nix build --impure " +
|
|
||||||
"--out-link /nix/.nixGL/auto/opengl " +
|
|
||||||
"--override-input nixpkgs path:/etc/nixpkgs " +
|
|
||||||
"path:" + a.NixGL,
|
|
||||||
"nix build --impure " +
|
|
||||||
"--out-link /nix/.nixGL/auto/vulkan " +
|
|
||||||
"--override-input nixpkgs path:/etc/nixpkgs " +
|
|
||||||
"path:" + a.NixGL + "#nixVulkanNvidia",
|
|
||||||
}, true, func(config *hst.Config) *hst.Config {
|
|
||||||
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
|
|
||||||
}...)
|
|
||||||
appendGPUFilesystem(config)
|
|
||||||
return config
|
|
||||||
}, a, pathSet, flagDropShellNixGL, func() {})
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create app configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pathname := a.Launcher
|
|
||||||
argv := make([]string, 1, len(args))
|
|
||||||
if flagDropShell {
|
|
||||||
pathname = pathShell
|
|
||||||
argv[0] = bash
|
|
||||||
} else {
|
|
||||||
argv[0] = a.Launcher.String()
|
|
||||||
}
|
|
||||||
argv = append(argv, args[1:]...)
|
|
||||||
config := a.toHst(pathSet, pathname, argv, flagDropShell)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Expose GPU devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if a.GPU {
|
|
||||||
config.Container.Filesystem = append(config.Container.Filesystem,
|
|
||||||
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append(".nixGL"), Target: hst.AbsPrivateTmp.Append("nixGL")}})
|
|
||||||
appendGPUFilesystem(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Spawn app.
|
|
||||||
*/
|
|
||||||
|
|
||||||
mustRunApp(ctx, msg, config, func() {})
|
|
||||||
return errSuccess
|
|
||||||
}).
|
|
||||||
Flag(&flagDropShellNixGL, "s", command.BoolFlag(false), "Drop to a shell on nixGL build").
|
|
||||||
Flag(&flagAutoDrivers, "auto-drivers", command.BoolFlag(false), "Attempt automatic opengl driver detection")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.MustParse(os.Args[1:], func(err error) {
|
|
||||||
msg.Verbosef("command returned %v", err)
|
|
||||||
if errors.Is(err, errSuccess) {
|
|
||||||
msg.BeforeExit()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
log.Fatal("unreachable")
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"hakurei.app/container/check"
|
|
||||||
"hakurei.app/container/fhs"
|
|
||||||
"hakurei.app/hst"
|
|
||||||
"hakurei.app/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
const bash = "bash"
|
|
||||||
|
|
||||||
var (
|
|
||||||
dataHome *check.Absolute
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// dataHome
|
|
||||||
if a, err := check.NewAbs(os.Getenv("HAKUREI_DATA_HOME")); err == nil {
|
|
||||||
dataHome = a
|
|
||||||
} else {
|
|
||||||
dataHome = fhs.AbsVarLib.Append("hakurei/" + strconv.Itoa(os.Getuid()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
pathBin = fhs.AbsRoot.Append("bin")
|
|
||||||
|
|
||||||
pathNix = check.MustAbs("/nix/")
|
|
||||||
pathNixStore = pathNix.Append("store/")
|
|
||||||
pathCurrentSystem = fhs.AbsRun.Append("current-system")
|
|
||||||
pathSwBin = pathCurrentSystem.Append("sw/bin/")
|
|
||||||
pathShell = pathSwBin.Append(bash)
|
|
||||||
|
|
||||||
pathData = check.MustAbs("/data")
|
|
||||||
pathDataData = pathData.Append("data")
|
|
||||||
)
|
|
||||||
|
|
||||||
func lookPath(file string) string {
|
|
||||||
if p, err := exec.LookPath(file); err != nil {
|
|
||||||
log.Fatalf("%s: command not found", file)
|
|
||||||
return ""
|
|
||||||
} else {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var beforeRunFail = new(atomic.Pointer[func()])
|
|
||||||
|
|
||||||
func mustRun(msg message.Msg, name string, arg ...string) {
|
|
||||||
msg.Verbosef("spawning process: %q %q", name, arg)
|
|
||||||
cmd := exec.Command(name, arg...)
|
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
if f := beforeRunFail.Swap(nil); f != nil {
|
|
||||||
(*f)()
|
|
||||||
}
|
|
||||||
log.Fatalf("%s: %v", name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type appPathSet struct {
|
|
||||||
// ${dataHome}/${id}
|
|
||||||
baseDir *check.Absolute
|
|
||||||
// ${baseDir}/app
|
|
||||||
metaPath *check.Absolute
|
|
||||||
// ${baseDir}/files
|
|
||||||
homeDir *check.Absolute
|
|
||||||
// ${baseDir}/cache
|
|
||||||
cacheDir *check.Absolute
|
|
||||||
// ${baseDir}/cache/nix
|
|
||||||
nixPath *check.Absolute
|
|
||||||
}
|
|
||||||
|
|
||||||
func pathSetByApp(id string) *appPathSet {
|
|
||||||
pathSet := new(appPathSet)
|
|
||||||
pathSet.baseDir = dataHome.Append(id)
|
|
||||||
pathSet.metaPath = pathSet.baseDir.Append("app")
|
|
||||||
pathSet.homeDir = pathSet.baseDir.Append("files")
|
|
||||||
pathSet.cacheDir = pathSet.baseDir.Append("cache")
|
|
||||||
pathSet.nixPath = pathSet.cacheDir.Append("nix")
|
|
||||||
return pathSet
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendGPUFilesystem(config *hst.Config) {
|
|
||||||
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
|
|
||||||
// flatpak commit 763a686d874dd668f0236f911de00b80766ffe79
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("dri"), Device: true, Optional: true}},
|
|
||||||
// mali
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali0"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("umplock"), Device: true, Optional: true}},
|
|
||||||
// nvidia
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidiactl"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-modeset"), Device: true, Optional: true}},
|
|
||||||
// nvidia OpenCL/CUDA
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm-tools"), Device: true, Optional: true}},
|
|
||||||
|
|
||||||
// flatpak commit d2dff2875bb3b7e2cd92d8204088d743fd07f3ff
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia0"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia1"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia2"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia3"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia4"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia5"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia6"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia7"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia8"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia9"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia10"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia11"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia12"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia13"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia14"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia15"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia16"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia17"), Device: true, Optional: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia18"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia19"), Device: true, Optional: true}},
|
|
||||||
}...)
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"hakurei.app/hst"
|
|
||||||
"hakurei.app/internal/info"
|
|
||||||
"hakurei.app/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
var hakureiPathVal = info.MustHakureiPath().String()
|
|
||||||
|
|
||||||
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
|
|
||||||
var (
|
|
||||||
cmd *exec.Cmd
|
|
||||||
st io.WriteCloser
|
|
||||||
)
|
|
||||||
|
|
||||||
if r, w, err := os.Pipe(); err != nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot pipe: %v", err)
|
|
||||||
} else {
|
|
||||||
if msg.IsVerbose() {
|
|
||||||
cmd = exec.CommandContext(ctx, hakureiPathVal, "-v", "app", "3")
|
|
||||||
} else {
|
|
||||||
cmd = exec.CommandContext(ctx, hakureiPathVal, "app", "3")
|
|
||||||
}
|
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
|
||||||
cmd.ExtraFiles = []*os.File{r}
|
|
||||||
st = w
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if err := json.NewEncoder(st).Encode(config); err != nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot send configuration: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot start hakurei: %v", err)
|
|
||||||
}
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
var exitError *exec.ExitError
|
|
||||||
if errors.As(err, &exitError) {
|
|
||||||
beforeFail()
|
|
||||||
msg.BeforeExit()
|
|
||||||
os.Exit(exitError.ExitCode())
|
|
||||||
} else {
|
|
||||||
beforeFail()
|
|
||||||
log.Fatalf("cannot wait: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
users.users = {
|
|
||||||
alice = {
|
|
||||||
isNormalUser = true;
|
|
||||||
description = "Alice Foobar";
|
|
||||||
password = "foobar";
|
|
||||||
uid = 1000;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
home-manager.users.alice.home.stateVersion = "24.11";
|
|
||||||
|
|
||||||
# Automatically login on tty1 as a normal user:
|
|
||||||
services.getty.autologinUser = "alice";
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
variables = {
|
|
||||||
SWAYSOCK = "/tmp/sway-ipc.sock";
|
|
||||||
WLR_RENDERER = "pixman";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Automatically configure and start Sway when logging in on tty1:
|
|
||||||
programs.bash.loginShellInit = ''
|
|
||||||
if [ "$(tty)" = "/dev/tty1" ]; then
|
|
||||||
set -e
|
|
||||||
|
|
||||||
mkdir -p ~/.config/sway
|
|
||||||
(sed s/Mod4/Mod1/ /etc/sway/config &&
|
|
||||||
echo 'output * bg ${pkgs.nixos-artwork.wallpapers.simple-light-gray.gnomeFilePath} fill' &&
|
|
||||||
echo 'output Virtual-1 res 1680x1050') > ~/.config/sway/config
|
|
||||||
|
|
||||||
sway --validate
|
|
||||||
systemd-cat --identifier=session sway && touch /tmp/sway-exit-ok
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
programs.sway.enable = true;
|
|
||||||
|
|
||||||
virtualisation = {
|
|
||||||
diskSize = 6 * 1024;
|
|
||||||
|
|
||||||
qemu.options = [
|
|
||||||
# Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch:
|
|
||||||
"-vga none -device virtio-gpu-pci"
|
|
||||||
|
|
||||||
# Increase zstd performance:
|
|
||||||
"-smp 8"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.hakurei = {
|
|
||||||
enable = true;
|
|
||||||
stateDir = "/var/lib/hakurei";
|
|
||||||
users.alice = 0;
|
|
||||||
|
|
||||||
extraHomeConfig = {
|
|
||||||
home.stateVersion = "23.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
testers,
|
|
||||||
callPackage,
|
|
||||||
|
|
||||||
system,
|
|
||||||
self,
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
buildPackage = self.buildPackage.${system};
|
|
||||||
in
|
|
||||||
testers.nixosTest {
|
|
||||||
name = "hpkg";
|
|
||||||
nodes.machine = {
|
|
||||||
environment.etc = {
|
|
||||||
"foot.pkg".source = callPackage ./foot.nix { inherit buildPackage; };
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
./configuration.nix
|
|
||||||
|
|
||||||
self.nixosModules.hakurei
|
|
||||||
self.inputs.home-manager.nixosModules.home-manager
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# adapted from nixos sway integration tests
|
|
||||||
|
|
||||||
# testScriptWithTypes:49: error: Cannot call function of unknown type
|
|
||||||
# (machine.succeed if succeed else machine.execute)(
|
|
||||||
# ^
|
|
||||||
# Found 1 error in 1 file (checked 1 source file)
|
|
||||||
skipTypeCheck = true;
|
|
||||||
testScript = builtins.readFile ./test.py;
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
buildPackage,
|
|
||||||
foot,
|
|
||||||
wayland-utils,
|
|
||||||
inconsolata,
|
|
||||||
}:
|
|
||||||
|
|
||||||
buildPackage {
|
|
||||||
name = "foot";
|
|
||||||
inherit (foot) version;
|
|
||||||
|
|
||||||
identity = 2;
|
|
||||||
id = "org.codeberg.dnkl.foot";
|
|
||||||
|
|
||||||
modules = [
|
|
||||||
{
|
|
||||||
home.packages = [
|
|
||||||
foot
|
|
||||||
|
|
||||||
# For wayland-info:
|
|
||||||
wayland-utils
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
nixosModules = [
|
|
||||||
{
|
|
||||||
# To help with OCR:
|
|
||||||
environment.etc."xdg/foot/foot.ini".text = lib.generators.toINI { } {
|
|
||||||
main = {
|
|
||||||
font = "inconsolata:size=14";
|
|
||||||
};
|
|
||||||
colors = rec {
|
|
||||||
foreground = "000000";
|
|
||||||
background = "ffffff";
|
|
||||||
regular2 = foreground;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
fonts.packages = [ inconsolata ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
script = ''
|
|
||||||
exec foot "$@"
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
import json
|
|
||||||
import shlex
|
|
||||||
|
|
||||||
q = shlex.quote
|
|
||||||
NODE_GROUPS = ["nodes", "floating_nodes"]
|
|
||||||
|
|
||||||
|
|
||||||
def swaymsg(command: str = "", succeed=True, type="command"):
|
|
||||||
assert command != "" or type != "command", "Must specify command or type"
|
|
||||||
shell = q(f"swaymsg -t {q(type)} -- {q(command)}")
|
|
||||||
with machine.nested(
|
|
||||||
f"sending swaymsg {shell!r}" + " (allowed to fail)" * (not succeed)
|
|
||||||
):
|
|
||||||
ret = (machine.succeed if succeed else machine.execute)(
|
|
||||||
f"su - alice -c {shell}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# execute also returns a status code, but disregard.
|
|
||||||
if not succeed:
|
|
||||||
_, ret = ret
|
|
||||||
|
|
||||||
if not succeed and not ret:
|
|
||||||
return None
|
|
||||||
|
|
||||||
parsed = json.loads(ret)
|
|
||||||
return parsed
|
|
||||||
|
|
||||||
|
|
||||||
def walk(tree):
|
|
||||||
yield tree
|
|
||||||
for group in NODE_GROUPS:
|
|
||||||
for node in tree.get(group, []):
|
|
||||||
yield from walk(node)
|
|
||||||
|
|
||||||
|
|
||||||
def wait_for_window(pattern):
|
|
||||||
def func(last_chance):
|
|
||||||
nodes = (node["name"] for node in walk(swaymsg(type="get_tree")))
|
|
||||||
|
|
||||||
if last_chance:
|
|
||||||
nodes = list(nodes)
|
|
||||||
machine.log(f"Last call! Current list of windows: {nodes}")
|
|
||||||
|
|
||||||
return any(pattern in name for name in nodes)
|
|
||||||
|
|
||||||
retry(func)
|
|
||||||
|
|
||||||
|
|
||||||
def collect_state_ui(name):
|
|
||||||
swaymsg(f"exec hakurei ps > '/tmp/{name}.ps'")
|
|
||||||
machine.copy_from_vm(f"/tmp/{name}.ps", "")
|
|
||||||
swaymsg(f"exec hakurei --json ps > '/tmp/{name}.json'")
|
|
||||||
machine.copy_from_vm(f"/tmp/{name}.json", "")
|
|
||||||
machine.screenshot(name)
|
|
||||||
|
|
||||||
|
|
||||||
def check_state(name, enablements):
|
|
||||||
instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps"))
|
|
||||||
if len(instances) != 1:
|
|
||||||
raise Exception(f"unexpected state length {len(instances)}")
|
|
||||||
instance = instances[0]
|
|
||||||
|
|
||||||
if len(instance['container']['args']) != 1 or not (instance['container']['args'][0].startswith("/nix/store/")) or f"hakurei-{name}-" not in (instance['container']['args'][0]):
|
|
||||||
raise Exception(f"unexpected args {instance['container']['args']}")
|
|
||||||
|
|
||||||
if instance['enablements'] != enablements:
|
|
||||||
raise Exception(f"unexpected enablements {instance['enablements']}")
|
|
||||||
|
|
||||||
|
|
||||||
start_all()
|
|
||||||
machine.wait_for_unit("multi-user.target")
|
|
||||||
|
|
||||||
# To check hakurei's version:
|
|
||||||
print(machine.succeed("sudo -u alice -i hakurei version"))
|
|
||||||
|
|
||||||
# Wait for Sway to complete startup:
|
|
||||||
machine.wait_for_file("/run/user/1000/wayland-1")
|
|
||||||
machine.wait_for_file("/tmp/sway-ipc.sock")
|
|
||||||
|
|
||||||
# Prepare hpkg directory:
|
|
||||||
machine.succeed("install -dm 0700 -o alice -g users /var/lib/hakurei/1000")
|
|
||||||
|
|
||||||
# Install hpkg app:
|
|
||||||
swaymsg("exec hpkg -v install /etc/foot.pkg && touch /tmp/hpkg-install-ok")
|
|
||||||
machine.wait_for_file("/tmp/hpkg-install-ok")
|
|
||||||
|
|
||||||
# Start app (foot) with Wayland enablement:
|
|
||||||
swaymsg("exec hpkg -v start org.codeberg.dnkl.foot")
|
|
||||||
wait_for_window("hakurei@machine-foot")
|
|
||||||
machine.send_chars("clear; wayland-info && touch /tmp/success-client\n")
|
|
||||||
machine.wait_for_file("/tmp/hakurei.0/tmpdir/2/success-client")
|
|
||||||
collect_state_ui("app_wayland")
|
|
||||||
check_state("foot", {"wayland": True, "dbus": True, "pipewire": True})
|
|
||||||
# Verify acl on XDG_RUNTIME_DIR:
|
|
||||||
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10002"))
|
|
||||||
machine.send_chars("exit\n")
|
|
||||||
machine.wait_until_fails("pgrep foot")
|
|
||||||
# Verify acl cleanup on XDG_RUNTIME_DIR:
|
|
||||||
machine.wait_until_fails("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10002")
|
|
||||||
|
|
||||||
# Exit Sway and verify process exit status 0:
|
|
||||||
swaymsg("exit", succeed=False)
|
|
||||||
machine.wait_for_file("/tmp/sway-exit-ok")
|
|
||||||
|
|
||||||
# Print hakurei share and rundir contents:
|
|
||||||
print(machine.succeed("find /tmp/hakurei.0 "
|
|
||||||
+ "-path '/tmp/hakurei.0/runtime/*/*' -prune -o "
|
|
||||||
+ "-path '/tmp/hakurei.0/tmpdir/*/*' -prune -o "
|
|
||||||
+ "-print"))
|
|
||||||
print(machine.fail("ls /run/user/1000/hakurei"))
|
|
||||||
130
cmd/hpkg/with.go
130
cmd/hpkg/with.go
@@ -1,130 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"hakurei.app/container/check"
|
|
||||||
"hakurei.app/container/fhs"
|
|
||||||
"hakurei.app/hst"
|
|
||||||
"hakurei.app/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
func withNixDaemon(
|
|
||||||
ctx context.Context,
|
|
||||||
msg message.Msg,
|
|
||||||
action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
|
|
||||||
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
|
|
||||||
) {
|
|
||||||
flags := hst.FMultiarch | hst.FUserns // nix sandbox requires userns
|
|
||||||
if net {
|
|
||||||
flags |= hst.FHostNet
|
|
||||||
}
|
|
||||||
if dropShell {
|
|
||||||
flags |= hst.FTty
|
|
||||||
}
|
|
||||||
|
|
||||||
mustRunAppDropShell(ctx, msg, updateConfig(&hst.Config{
|
|
||||||
ID: app.ID,
|
|
||||||
|
|
||||||
ExtraPerms: []hst.ExtraPermConfig{
|
|
||||||
{Path: dataHome, Execute: true},
|
|
||||||
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
|
|
||||||
},
|
|
||||||
|
|
||||||
Identity: app.Identity,
|
|
||||||
|
|
||||||
Container: &hst.ContainerConfig{
|
|
||||||
Hostname: formatHostname(app.Name) + "-" + action,
|
|
||||||
|
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath, Target: pathNix, Write: true}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
|
|
||||||
},
|
|
||||||
|
|
||||||
Username: "hakurei",
|
|
||||||
Shell: pathShell,
|
|
||||||
Home: pathDataData.Append(app.ID),
|
|
||||||
|
|
||||||
Path: pathShell,
|
|
||||||
Args: []string{bash, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " +
|
|
||||||
// start nix-daemon
|
|
||||||
"nix-daemon --store / & " +
|
|
||||||
// wait for socket to appear
|
|
||||||
"(while [ ! -S /nix/var/nix/daemon-socket/socket ]; do sleep 0.01; done) && " +
|
|
||||||
// create directory so nix stops complaining
|
|
||||||
"mkdir -p /nix/var/nix/profiles/per-user/root/channels && " +
|
|
||||||
strings.Join(command, " && ") +
|
|
||||||
// terminate nix-daemon
|
|
||||||
" && pkill nix-daemon",
|
|
||||||
},
|
|
||||||
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
}), dropShell, beforeFail)
|
|
||||||
}
|
|
||||||
|
|
||||||
func withCacheDir(
|
|
||||||
ctx context.Context,
|
|
||||||
msg message.Msg,
|
|
||||||
action string, command []string, workDir *check.Absolute,
|
|
||||||
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
|
|
||||||
) {
|
|
||||||
flags := hst.FMultiarch
|
|
||||||
if dropShell {
|
|
||||||
flags |= hst.FTty
|
|
||||||
}
|
|
||||||
|
|
||||||
mustRunAppDropShell(ctx, msg, &hst.Config{
|
|
||||||
ID: app.ID,
|
|
||||||
|
|
||||||
ExtraPerms: []hst.ExtraPermConfig{
|
|
||||||
{Path: dataHome, Execute: true},
|
|
||||||
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
|
|
||||||
{Path: workDir, Execute: true},
|
|
||||||
},
|
|
||||||
|
|
||||||
Identity: app.Identity,
|
|
||||||
|
|
||||||
Container: &hst.ContainerConfig{
|
|
||||||
Hostname: formatHostname(app.Name) + "-" + action,
|
|
||||||
|
|
||||||
Filesystem: []hst.FilesystemConfigJSON{
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: workDir.Append(fhs.Etc), Special: true}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: workDir.Append("nix"), Target: pathNix}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Source: workDir, Target: hst.AbsPrivateTmp.Append("bundle")}},
|
|
||||||
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID, "cache"), Source: pathSet.cacheDir, Write: true, Ensure: true}},
|
|
||||||
},
|
|
||||||
|
|
||||||
Username: "nixos",
|
|
||||||
Shell: pathShell,
|
|
||||||
Home: pathDataData.Append(app.ID, "cache"),
|
|
||||||
|
|
||||||
Path: pathShell,
|
|
||||||
Args: []string{bash, "-lc", strings.Join(command, " && ")},
|
|
||||||
|
|
||||||
Flags: flags,
|
|
||||||
},
|
|
||||||
}, dropShell, beforeFail)
|
|
||||||
}
|
|
||||||
|
|
||||||
func mustRunAppDropShell(ctx context.Context, msg message.Msg, config *hst.Config, dropShell bool, beforeFail func()) {
|
|
||||||
if dropShell {
|
|
||||||
if config.Container != nil {
|
|
||||||
config.Container.Args = []string{bash, "-l"}
|
|
||||||
}
|
|
||||||
mustRunApp(ctx, msg, config, beforeFail)
|
|
||||||
beforeFail()
|
|
||||||
msg.BeforeExit()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
mustRunApp(ctx, msg, config, beforeFail)
|
|
||||||
}
|
|
||||||
4
dist/release.sh
vendored
4
dist/release.sh
vendored
@@ -13,7 +13,7 @@ echo
|
|||||||
echo '# Building hakurei.'
|
echo '# Building hakurei.'
|
||||||
go generate ./...
|
go generate ./...
|
||||||
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w
|
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w
|
||||||
-buildid= -extldflags '-static'
|
-buildid= -linkmode external -extldflags=-static
|
||||||
-X hakurei.app/internal/info.buildVersion=${VERSION}
|
-X hakurei.app/internal/info.buildVersion=${VERSION}
|
||||||
-X hakurei.app/internal/info.hakureiPath=/usr/bin/hakurei
|
-X hakurei.app/internal/info.hakureiPath=/usr/bin/hakurei
|
||||||
-X hakurei.app/internal/info.hsuPath=/usr/bin/hsu
|
-X hakurei.app/internal/info.hsuPath=/usr/bin/hsu
|
||||||
@@ -21,7 +21,7 @@ go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
echo '# Testing hakurei.'
|
echo '# Testing hakurei.'
|
||||||
go test -ldflags='-buildid= -extldflags=-static' ./...
|
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||||
echo
|
echo
|
||||||
|
|
||||||
echo '# Creating distribution.'
|
echo '# Creating distribution.'
|
||||||
|
|||||||
23
flake.nix
23
flake.nix
@@ -29,20 +29,6 @@
|
|||||||
{
|
{
|
||||||
nixosModules.hakurei = import ./nixos.nix self.packages;
|
nixosModules.hakurei = import ./nixos.nix self.packages;
|
||||||
|
|
||||||
buildPackage = forAllSystems (
|
|
||||||
system:
|
|
||||||
nixpkgsFor.${system}.callPackage (
|
|
||||||
import ./cmd/hpkg/build.nix {
|
|
||||||
inherit
|
|
||||||
nixpkgsFor
|
|
||||||
system
|
|
||||||
nixpkgs
|
|
||||||
home-manager
|
|
||||||
;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
checks = forAllSystems (
|
checks = forAllSystems (
|
||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
@@ -71,8 +57,6 @@
|
|||||||
|
|
||||||
sharefs = callPackage ./cmd/sharefs/test { inherit system self; };
|
sharefs = callPackage ./cmd/sharefs/test { inherit system self; };
|
||||||
|
|
||||||
hpkg = callPackage ./cmd/hpkg/test { inherit system self; };
|
|
||||||
|
|
||||||
formatting = runCommandLocal "check-formatting" { nativeBuildInputs = [ nixfmt-rfc-style ]; } ''
|
formatting = runCommandLocal "check-formatting" { nativeBuildInputs = [ nixfmt-rfc-style ]; } ''
|
||||||
cd ${./.}
|
cd ${./.}
|
||||||
|
|
||||||
@@ -127,11 +111,6 @@
|
|||||||
glibc
|
glibc
|
||||||
xdg-dbus-proxy
|
xdg-dbus-proxy
|
||||||
|
|
||||||
# hpkg
|
|
||||||
zstd
|
|
||||||
gnutar
|
|
||||||
coreutils
|
|
||||||
|
|
||||||
# for check
|
# for check
|
||||||
util-linux
|
util-linux
|
||||||
nettools
|
nettools
|
||||||
@@ -219,7 +198,7 @@
|
|||||||
./test/interactive/trace.nix
|
./test/interactive/trace.nix
|
||||||
|
|
||||||
self.nixosModules.hakurei
|
self.nixosModules.hakurei
|
||||||
self.inputs.home-manager.nixosModules.home-manager
|
home-manager.nixosModules.home-manager
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ go build -trimpath -v -o /work/system/libexec/hakurei -ldflags="-s -w
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
echo '# Testing hakurei.'
|
echo '# Testing hakurei.'
|
||||||
go test -ldflags='-buildid= -extldflags=-static' ./...
|
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||||
echo
|
echo
|
||||||
|
|
||||||
mkdir -p /work/system/bin/
|
mkdir -p /work/system/bin/
|
||||||
|
|||||||
17
package.nix
17
package.nix
@@ -16,11 +16,6 @@
|
|||||||
# for sharefs
|
# for sharefs
|
||||||
fuse3,
|
fuse3,
|
||||||
|
|
||||||
# for hpkg
|
|
||||||
zstd,
|
|
||||||
gnutar,
|
|
||||||
coreutils,
|
|
||||||
|
|
||||||
# for passthru.buildInputs
|
# for passthru.buildInputs
|
||||||
go,
|
go,
|
||||||
clang,
|
clang,
|
||||||
@@ -128,18 +123,6 @@ buildGoModule rec {
|
|||||||
|
|
||||||
makeBinaryWrapper "$out/libexec/hakurei" "$out/bin/hakurei" \
|
makeBinaryWrapper "$out/libexec/hakurei" "$out/bin/hakurei" \
|
||||||
--inherit-argv0 --prefix PATH : ${lib.makeBinPath appPackages}
|
--inherit-argv0 --prefix PATH : ${lib.makeBinPath appPackages}
|
||||||
|
|
||||||
makeBinaryWrapper "$out/libexec/hpkg" "$out/bin/hpkg" \
|
|
||||||
--inherit-argv0 --prefix PATH : ${
|
|
||||||
lib.makeBinPath (
|
|
||||||
appPackages
|
|
||||||
++ [
|
|
||||||
zstd
|
|
||||||
gnutar
|
|
||||||
coreutils
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
passthru.targetPkgs = [
|
passthru.targetPkgs = [
|
||||||
|
|||||||
Reference in New Issue
Block a user