Tidy UX, make --logger param (#108)

* Tidy UX, make --logger param

* Include cargo change
This commit is contained in:
Ana Hobden 2022-12-09 11:15:54 -08:00 committed by GitHub
parent cda9fcfc03
commit 72792372ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 190 additions and 98 deletions

2
Cargo.lock generated
View file

@ -2128,6 +2128,8 @@ dependencies = [
"nu-ansi-term", "nu-ansi-term",
"once_cell", "once_cell",
"regex", "regex",
"serde",
"serde_json",
"sharded-slab", "sharded-slab",
"smallvec", "smallvec",
"thread_local", "thread_local",

View file

@ -43,7 +43,7 @@ tokio = { version = "1.21.0", features = ["time", "io-std", "process", "fs", "si
tokio-util = { version = "0.7", features = ["io"] } tokio-util = { version = "0.7", features = ["io"] }
tracing = { version = "0.1.36", features = [ "valuable" ] } tracing = { version = "0.1.36", features = [ "valuable" ] }
tracing-error = { version = "0.2.0", optional = true } tracing-error = { version = "0.2.0", optional = true }
tracing-subscriber = { version = "0.3.15", features = [ "env-filter", "valuable" ], optional = true } tracing-subscriber = { version = "0.3.15", features = [ "json", "env-filter", "valuable" ], optional = true }
url = { version = "2.3.1", features = ["serde"] } url = { version = "2.3.1", features = ["serde"] }
valuable = { version = "0.1.0", features = ["derive"] } valuable = { version = "0.1.0", features = ["derive"] }
walkdir = "2.3.2" walkdir = "2.3.2"

View file

@ -23,7 +23,7 @@ pub struct CreateDirectory {
} }
impl CreateDirectory { impl CreateDirectory {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
path: impl AsRef<Path>, path: impl AsRef<Path>,
user: impl Into<Option<String>>, user: impl Into<Option<String>>,
@ -78,7 +78,7 @@ impl Action for CreateDirectory {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,
@ -150,7 +150,7 @@ impl Action for CreateDirectory {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,

View file

@ -25,7 +25,7 @@ pub struct CreateFile {
} }
impl CreateFile { impl CreateFile {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
path: impl AsRef<Path>, path: impl AsRef<Path>,
user: impl Into<Option<String>>, user: impl Into<Option<String>>,
@ -62,7 +62,7 @@ impl Action for CreateFile {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,
@ -135,7 +135,7 @@ impl Action for CreateFile {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,

View file

@ -15,7 +15,7 @@ pub struct CreateGroup {
} }
impl CreateGroup { impl CreateGroup {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn plan(name: String, gid: usize) -> StatefulAction<Self> { pub fn plan(name: String, gid: usize) -> StatefulAction<Self> {
Self { name, gid }.into() Self { name, gid }.into()
} }
@ -37,7 +37,7 @@ impl Action for CreateGroup {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
user = self.name, user = self.name,
gid = self.gid, gid = self.gid,
))] ))]
@ -107,7 +107,7 @@ impl Action for CreateGroup {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
user = self.name, user = self.name,
gid = self.gid, gid = self.gid,
))] ))]

View file

@ -30,7 +30,7 @@ pub struct CreateOrAppendFile {
} }
impl CreateOrAppendFile { impl CreateOrAppendFile {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
path: impl AsRef<Path>, path: impl AsRef<Path>,
user: impl Into<Option<String>>, user: impl Into<Option<String>>,
@ -62,7 +62,7 @@ impl Action for CreateOrAppendFile {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,
@ -142,7 +142,7 @@ impl Action for CreateOrAppendFile {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
user = self.user, user = self.user,
group = self.group, group = self.group,

View file

@ -17,7 +17,7 @@ pub struct CreateUser {
} }
impl CreateUser { impl CreateUser {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn plan(name: String, uid: usize, groupname: String, gid: usize) -> StatefulAction<Self> { pub fn plan(name: String, uid: usize, groupname: String, gid: usize) -> StatefulAction<Self> {
Self { Self {
name, name,
@ -47,7 +47,7 @@ impl Action for CreateUser {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
user = self.name, user = self.name,
uid = self.uid, uid = self.uid,
groupname = self.groupname, groupname = self.groupname,
@ -231,7 +231,7 @@ impl Action for CreateUser {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
user = self.name, user = self.name,
uid = self.uid, uid = self.uid,
gid = self.gid, gid = self.gid,

View file

@ -15,7 +15,7 @@ pub struct FetchAndUnpackNix {
} }
impl FetchAndUnpackNix { impl FetchAndUnpackNix {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(url: Url, dest: PathBuf) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(url: Url, dest: PathBuf) -> Result<StatefulAction<Self>, ActionError> {
// TODO(@hoverbear): Check URL exists? // TODO(@hoverbear): Check URL exists?
// TODO(@hoverbear): Check tempdir exists // TODO(@hoverbear): Check tempdir exists
@ -35,7 +35,7 @@ impl Action for FetchAndUnpackNix {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
url = %self.url, url = %self.url,
dest = %self.dest.display(), dest = %self.dest.display(),
))] ))]
@ -66,7 +66,7 @@ impl Action for FetchAndUnpackNix {
vec![/* Deliberately empty -- this is a noop */] vec![/* Deliberately empty -- this is a noop */]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
url = %self.url, url = %self.url,
dest = %self.dest.display(), dest = %self.dest.display(),
))] ))]

View file

@ -13,7 +13,7 @@ pub struct MoveUnpackedNix {
} }
impl MoveUnpackedNix { impl MoveUnpackedNix {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(src: PathBuf) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(src: PathBuf) -> Result<StatefulAction<Self>, ActionError> {
// Note: Do NOT try to check for the src/dest since the installer creates those // Note: Do NOT try to check for the src/dest since the installer creates those
Ok(Self { src }.into()) Ok(Self { src }.into())
@ -37,7 +37,7 @@ impl Action for MoveUnpackedNix {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
src = %self.src.display(), src = %self.src.display(),
dest = DEST, dest = DEST,
))] ))]
@ -73,7 +73,7 @@ impl Action for MoveUnpackedNix {
vec![/* Deliberately empty -- this is a noop */] vec![/* Deliberately empty -- this is a noop */]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
src = %self.src.display(), src = %self.src.display(),
dest = DEST, dest = DEST,
))] ))]

View file

@ -18,7 +18,7 @@ pub struct SetupDefaultProfile {
} }
impl SetupDefaultProfile { impl SetupDefaultProfile {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(channels: Vec<String>) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(channels: Vec<String>) -> Result<StatefulAction<Self>, ActionError> {
Ok(Self { channels }.into()) Ok(Self { channels }.into())
} }
@ -35,7 +35,7 @@ impl Action for SetupDefaultProfile {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
channels = %self.channels.join(","), channels = %self.channels.join(","),
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -156,7 +156,7 @@ impl Action for SetupDefaultProfile {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
channels = %self.channels.join(","), channels = %self.channels.join(","),
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -24,7 +24,7 @@ pub struct ConfigureNix {
} }
impl ConfigureNix { impl ConfigureNix {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
let channels: Vec<(String, Url)> = settings let channels: Vec<(String, Url)> = settings
.channels .channels
@ -87,7 +87,7 @@ impl Action for ConfigureNix {
buf buf
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { let Self {
setup_default_profile, setup_default_profile,
@ -137,7 +137,7 @@ impl Action for ConfigureNix {
buf buf
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { let Self {
setup_default_profile, setup_default_profile,

View file

@ -39,7 +39,7 @@ pub struct ConfigureShellProfile {
} }
impl ConfigureShellProfile { impl ConfigureShellProfile {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
let mut create_or_append_files = Vec::default(); let mut create_or_append_files = Vec::default();
let mut create_directories = Vec::default(); let mut create_directories = Vec::default();
@ -148,7 +148,7 @@ impl Action for ConfigureShellProfile {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { let Self {
create_or_append_files, create_or_append_files,
@ -200,7 +200,7 @@ impl Action for ConfigureShellProfile {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { let Self {
create_directories, create_directories,

View file

@ -26,7 +26,7 @@ pub struct CreateNixTree {
} }
impl CreateNixTree { impl CreateNixTree {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
let mut create_directories = Vec::default(); let mut create_directories = Vec::default();
for path in PATHS { for path in PATHS {
@ -64,7 +64,7 @@ impl Action for CreateNixTree {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { create_directories } = self; let Self { create_directories } = self;
@ -96,7 +96,7 @@ impl Action for CreateNixTree {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { create_directories } = self; let Self { create_directories } = self;

View file

@ -19,7 +19,7 @@ pub struct CreateUsersAndGroups {
} }
impl CreateUsersAndGroups { impl CreateUsersAndGroups {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(settings: CommonSettings) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(settings: CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
// TODO(@hoverbear): CHeck if it exist, error if so // TODO(@hoverbear): CHeck if it exist, error if so
let create_group = CreateGroup::plan( let create_group = CreateGroup::plan(
@ -91,7 +91,7 @@ impl Action for CreateUsersAndGroups {
vec![ActionDescription::new(self.tracing_synopsis(), explanation)] vec![ActionDescription::new(self.tracing_synopsis(), explanation)]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
daemon_user_count = self.daemon_user_count, daemon_user_count = self.daemon_user_count,
nix_build_group_name = self.nix_build_group_name, nix_build_group_name = self.nix_build_group_name,
nix_build_group_id = self.nix_build_group_id, nix_build_group_id = self.nix_build_group_id,
@ -188,7 +188,7 @@ impl Action for CreateUsersAndGroups {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
daemon_user_count = self.daemon_user_count, daemon_user_count = self.daemon_user_count,
nix_build_group_name = self.nix_build_group_name, nix_build_group_name = self.nix_build_group_name,
nix_build_group_id = self.nix_build_group_id, nix_build_group_id = self.nix_build_group_id,

View file

@ -13,7 +13,7 @@ pub struct PlaceChannelConfiguration {
} }
impl PlaceChannelConfiguration { impl PlaceChannelConfiguration {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
channels: Vec<(String, Url)>, channels: Vec<(String, Url)>,
force: bool, force: bool,
@ -58,7 +58,7 @@ impl Action for PlaceChannelConfiguration {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "), channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "),
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -82,7 +82,7 @@ impl Action for PlaceChannelConfiguration {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "), channels = self.channels.iter().map(|(c, u)| format!("{c}={u}")).collect::<Vec<_>>().join(", "),
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -14,7 +14,7 @@ pub struct PlaceNixConfiguration {
} }
impl PlaceNixConfiguration { impl PlaceNixConfiguration {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
nix_build_group_name: String, nix_build_group_name: String,
extra_conf: Vec<String>, extra_conf: Vec<String>,
@ -60,7 +60,7 @@ impl Action for PlaceNixConfiguration {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { let Self {
create_file, create_file,
@ -83,7 +83,7 @@ impl Action for PlaceNixConfiguration {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { let Self {
create_file, create_file,

View file

@ -20,7 +20,7 @@ pub struct ProvisionNix {
} }
impl ProvisionNix { impl ProvisionNix {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
let fetch_nix = FetchAndUnpackNix::plan( let fetch_nix = FetchAndUnpackNix::plan(
settings.nix_package_url.clone(), settings.nix_package_url.clone(),
@ -65,7 +65,7 @@ impl Action for ProvisionNix {
buf buf
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { let Self {
fetch_nix, fetch_nix,
@ -106,7 +106,7 @@ impl Action for ProvisionNix {
buf buf
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { let Self {
fetch_nix, fetch_nix,

View file

@ -16,7 +16,7 @@ pub struct BootstrapApfsVolume {
} }
impl BootstrapApfsVolume { impl BootstrapApfsVolume {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(path: impl AsRef<Path>) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(path: impl AsRef<Path>) -> Result<StatefulAction<Self>, ActionError> {
Ok(Self { Ok(Self {
path: path.as_ref().to_path_buf(), path: path.as_ref().to_path_buf(),
@ -36,7 +36,7 @@ impl Action for BootstrapApfsVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -70,7 +70,7 @@ impl Action for BootstrapApfsVolume {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -15,7 +15,7 @@ pub struct CreateApfsVolume {
} }
impl CreateApfsVolume { impl CreateApfsVolume {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
disk: impl AsRef<Path>, disk: impl AsRef<Path>,
name: String, name: String,
@ -45,7 +45,7 @@ impl Action for CreateApfsVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
name = %self.name, name = %self.name,
case_sensitive = %self.case_sensitive, case_sensitive = %self.case_sensitive,
@ -91,7 +91,7 @@ impl Action for CreateApfsVolume {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
name = %self.name, name = %self.name,
case_sensitive = %self.case_sensitive, case_sensitive = %self.case_sensitive,

View file

@ -33,7 +33,7 @@ pub struct CreateNixVolume {
} }
impl CreateNixVolume { impl CreateNixVolume {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
disk: impl AsRef<Path>, disk: impl AsRef<Path>,
name: String, name: String,
@ -150,7 +150,7 @@ impl Action for CreateNixVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields(destination,))] #[tracing::instrument(level = "debug", skip_all, fields(destination,))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self { let Self {
disk: _, disk: _,
@ -213,7 +213,7 @@ impl Action for CreateNixVolume {
)] )]
} }
#[tracing::instrument(skip_all, fields(disk, name))] #[tracing::instrument(level = "debug", skip_all, fields(disk, name))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
let Self { let Self {
disk: _, disk: _,

View file

@ -9,7 +9,7 @@ use crate::action::{Action, ActionDescription, ActionError, StatefulAction};
pub struct CreateSyntheticObjects; pub struct CreateSyntheticObjects;
impl CreateSyntheticObjects { impl CreateSyntheticObjects {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
Ok(Self.into()) Ok(Self.into())
} }
@ -29,7 +29,7 @@ impl Action for CreateSyntheticObjects {
)] )]
} }
#[tracing::instrument(skip_all, fields())] #[tracing::instrument(level = "debug", skip_all, fields())]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261 // Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
execute_command( execute_command(
@ -59,7 +59,7 @@ impl Action for CreateSyntheticObjects {
)] )]
} }
#[tracing::instrument(skip_all, fields())] #[tracing::instrument(level = "debug", skip_all, fields())]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
// Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261 // Yup we literally call both and ignore the error! Reasoning: https://github.com/NixOS/nix/blob/95331cb9c99151cbd790ceb6ddaf49fc1c0da4b3/scripts/create-darwin-volume.sh#L261
execute_command( execute_command(

View file

@ -18,7 +18,7 @@ pub struct EnableOwnership {
} }
impl EnableOwnership { impl EnableOwnership {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(path: impl AsRef<Path>) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(path: impl AsRef<Path>) -> Result<StatefulAction<Self>, ActionError> {
Ok(Self { Ok(Self {
path: path.as_ref().to_path_buf(), path: path.as_ref().to_path_buf(),
@ -38,7 +38,7 @@ impl Action for EnableOwnership {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -79,7 +79,7 @@ impl Action for EnableOwnership {
vec![] vec![]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
path = %self.path.display(), path = %self.path.display(),
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -18,7 +18,7 @@ pub struct EncryptApfsVolume {
} }
impl EncryptApfsVolume { impl EncryptApfsVolume {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
disk: impl AsRef<Path>, disk: impl AsRef<Path>,
name: impl AsRef<str>, name: impl AsRef<str>,
@ -47,7 +47,7 @@ impl Action for EncryptApfsVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -142,7 +142,7 @@ impl Action for EncryptApfsVolume {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -14,7 +14,7 @@ pub struct KickstartLaunchctlService {
} }
impl KickstartLaunchctlService { impl KickstartLaunchctlService {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(unit: String) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(unit: String) -> Result<StatefulAction<Self>, ActionError> {
Ok(Self { unit }.into()) Ok(Self { unit }.into())
} }
@ -32,7 +32,7 @@ impl Action for KickstartLaunchctlService {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
unit = %self.unit, unit = %self.unit,
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -56,7 +56,7 @@ impl Action for KickstartLaunchctlService {
vec![] vec![]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
unit = %self.unit, unit = %self.unit,
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -17,7 +17,7 @@ pub struct UnmountApfsVolume {
} }
impl UnmountApfsVolume { impl UnmountApfsVolume {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan( pub async fn plan(
disk: impl AsRef<Path>, disk: impl AsRef<Path>,
name: String, name: String,
@ -38,7 +38,7 @@ impl Action for UnmountApfsVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
name = %self.name, name = %self.name,
))] ))]
@ -62,7 +62,7 @@ impl Action for UnmountApfsVolume {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
disk = %self.disk.display(), disk = %self.disk.display(),
name = %self.name, name = %self.name,
))] ))]

View file

@ -22,7 +22,7 @@ Run systemd utilities to configure the Nix daemon
pub struct ConfigureNixDaemonService {} pub struct ConfigureNixDaemonService {}
impl ConfigureNixDaemonService { impl ConfigureNixDaemonService {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
match OperatingSystem::host() { match OperatingSystem::host() {
OperatingSystem::MacOSX { OperatingSystem::MacOSX {
@ -62,7 +62,7 @@ impl Action for ConfigureNixDaemonService {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
let Self {} = self; let Self {} = self;
@ -172,7 +172,7 @@ impl Action for ConfigureNixDaemonService {
)] )]
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {
match OperatingSystem::host() { match OperatingSystem::host() {
OperatingSystem::MacOSX { OperatingSystem::MacOSX {

View file

@ -14,7 +14,7 @@ pub struct StartSystemdUnit {
} }
impl StartSystemdUnit { impl StartSystemdUnit {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(unit: impl AsRef<str>) -> Result<StatefulAction<Self>, ActionError> { pub async fn plan(unit: impl AsRef<str>) -> Result<StatefulAction<Self>, ActionError> {
Ok(StatefulAction { Ok(StatefulAction {
action: Self { action: Self {
@ -36,7 +36,7 @@ impl Action for StartSystemdUnit {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
unit = %self.unit, unit = %self.unit,
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -64,7 +64,7 @@ impl Action for StartSystemdUnit {
)] )]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
unit = %self.unit, unit = %self.unit,
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -57,7 +57,7 @@ pub struct MyAction {}
impl MyAction { impl MyAction {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
Ok(Self {}.into()) Ok(Self {}.into())
} }
@ -75,7 +75,7 @@ impl Action for MyAction {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
// Tracing fields... // Tracing fields...
))] ))]
async fn execute(&mut self) -> Result<(), ActionError> { async fn execute(&mut self) -> Result<(), ActionError> {
@ -87,7 +87,7 @@ impl Action for MyAction {
vec![ActionDescription::new(self.tracing_synopsis(), vec![])] vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
// Tracing fields... // Tracing fields...
))] ))]
async fn revert(&mut self) -> Result<(), ActionError> { async fn revert(&mut self) -> Result<(), ActionError> {

View file

@ -23,6 +23,9 @@ where
} }
impl StatefulAction<Box<dyn Action>> { impl StatefulAction<Box<dyn Action>> {
pub fn tracing_synopsis(&self) -> String {
self.action.tracing_synopsis()
}
/// A description of what this action would do during execution /// A description of what this action would do during execution
pub fn describe_execute(&self) -> Vec<ActionDescription> { pub fn describe_execute(&self) -> Vec<ActionDescription> {
match self.state { match self.state {
@ -99,6 +102,10 @@ impl<A> StatefulAction<A>
where where
A: Action, A: Action,
{ {
pub fn tracing_synopsis(&self) -> String {
self.action.tracing_synopsis()
}
pub fn inner(&self) -> &A { pub fn inner(&self) -> &A {
&self.action &self.action
} }

View file

@ -5,11 +5,35 @@ use tracing_error::ErrorLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
use valuable::Valuable; use valuable::Valuable;
#[derive(Clone, Default, Debug, clap::ValueEnum, Valuable)]
pub enum Logger {
#[default]
Compact,
Full,
Pretty,
Json,
}
impl std::fmt::Display for Logger {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let logger = match self {
Logger::Compact => "compact",
Logger::Full => "full",
Logger::Pretty => "pretty",
Logger::Json => "json",
};
write!(f, "{}", logger)
}
}
#[derive(clap::Args, Debug, Valuable)] #[derive(clap::Args, Debug, Valuable)]
pub struct Instrumentation { pub struct Instrumentation {
/// Enable debug logs, -vv for trace /// Enable debug logs, -vv for trace
#[clap(short = 'v', long, action = clap::ArgAction::Count, global = true)] #[clap(short = 'v', long, action = clap::ArgAction::Count, global = true)]
pub verbose: u8, pub verbose: u8,
/// Which logger to use
#[clap(long, default_value_t = Default::default(), global = true)]
pub logger: Logger,
} }
impl<'a> Instrumentation { impl<'a> Instrumentation {
@ -23,19 +47,44 @@ impl<'a> Instrumentation {
} }
pub fn setup<'b: 'a>(&'b self) -> eyre::Result<()> { pub fn setup<'b: 'a>(&'b self) -> eyre::Result<()> {
let fmt_layer = self.fmt_layer();
let filter_layer = self.filter_layer()?; let filter_layer = self.filter_layer()?;
tracing_subscriber::registry() let registry = tracing_subscriber::registry()
.with(filter_layer) .with(filter_layer)
.with(fmt_layer) .with(ErrorLayer::default());
.with(ErrorLayer::default())
.try_init()?; match self.logger {
Logger::Compact => {
let fmt_layer = self.fmt_layer_compact();
registry.with(fmt_layer).try_init()?
},
Logger::Full => {
let fmt_layer = self.fmt_layer_full();
registry.with(fmt_layer).try_init()?
},
Logger::Pretty => {
let fmt_layer = self.fmt_layer_pretty();
registry.with(fmt_layer).try_init()?
},
Logger::Json => {
let fmt_layer = self.fmt_layer_json();
registry.with(fmt_layer).try_init()?
},
}
Ok(()) Ok(())
} }
pub fn fmt_layer<S>(&self) -> impl tracing_subscriber::layer::Layer<S> pub fn fmt_layer_full<S>(&self) -> impl tracing_subscriber::layer::Layer<S>
where
S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
{
tracing_subscriber::fmt::Layer::new()
.with_ansi(atty::is(Stream::Stderr))
.with_writer(std::io::stderr)
}
pub fn fmt_layer_pretty<S>(&self) -> impl tracing_subscriber::layer::Layer<S>
where where
S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>, S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
{ {
@ -45,6 +94,32 @@ impl<'a> Instrumentation {
.pretty() .pretty()
} }
pub fn fmt_layer_json<S>(&self) -> impl tracing_subscriber::layer::Layer<S>
where
S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
{
tracing_subscriber::fmt::Layer::new()
.with_ansi(atty::is(Stream::Stderr))
.with_writer(std::io::stderr)
.json()
}
pub fn fmt_layer_compact<S>(&self) -> impl tracing_subscriber::layer::Layer<S>
where
S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
{
tracing_subscriber::fmt::Layer::new()
.with_ansi(atty::is(Stream::Stderr))
.with_writer(std::io::stderr)
.compact()
.without_time()
.with_target(false)
.with_thread_ids(false)
.with_thread_names(false)
.with_file(false)
.with_line_number(false)
}
pub fn filter_layer(&self) -> eyre::Result<EnvFilter> { pub fn filter_layer(&self) -> eyre::Result<EnvFilter> {
let filter_layer = match EnvFilter::try_from_default_env() { let filter_layer = match EnvFilter::try_from_default_env() {
Ok(layer) => layer, Ok(layer) => layer,

View file

@ -1,8 +1,6 @@
use std::io::{stdin, stdout, BufRead, Write}; use std::io::{stdin, stdout, BufRead, Write};
use crossterm::event::{EventStream, KeyCode};
use eyre::{eyre, WrapErr}; use eyre::{eyre, WrapErr};
use futures::{FutureExt, StreamExt};
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
// Do not try to get clever! // Do not try to get clever!

View file

@ -32,7 +32,7 @@ pub struct HarmonicCli {
#[async_trait::async_trait] #[async_trait::async_trait]
impl CommandExecute for HarmonicCli { impl CommandExecute for HarmonicCli {
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
async fn execute(self) -> eyre::Result<ExitCode> { async fn execute(self) -> eyre::Result<ExitCode> {
let Self { let Self {
instrumentation: _, instrumentation: _,

View file

@ -44,7 +44,7 @@ pub struct Install {
#[async_trait::async_trait] #[async_trait::async_trait]
impl CommandExecute for Install { impl CommandExecute for Install {
#[tracing::instrument(skip_all, fields())] #[tracing::instrument(level = "debug", skip_all, fields())]
async fn execute(self) -> eyre::Result<ExitCode> { async fn execute(self) -> eyre::Result<ExitCode> {
let Self { let Self {
no_confirm, no_confirm,

View file

@ -18,7 +18,7 @@ pub struct Plan {
#[async_trait::async_trait] #[async_trait::async_trait]
impl CommandExecute for Plan { impl CommandExecute for Plan {
#[tracing::instrument(skip_all, fields())] #[tracing::instrument(level = "debug", skip_all, fields())]
async fn execute(self) -> eyre::Result<ExitCode> { async fn execute(self) -> eyre::Result<ExitCode> {
let Self { planner, output } = self; let Self { planner, output } = self;

View file

@ -11,6 +11,7 @@ use crate::{
}; };
use clap::{ArgAction, Parser}; use clap::{ArgAction, Parser};
use eyre::{eyre, WrapErr}; use eyre::{eyre, WrapErr};
use owo_colors::OwoColorize;
use rand::Rng; use rand::Rng;
use crate::cli::{interaction, CommandExecute}; use crate::cli::{interaction, CommandExecute};
@ -38,7 +39,7 @@ pub struct Uninstall {
#[async_trait::async_trait] #[async_trait::async_trait]
impl CommandExecute for Uninstall { impl CommandExecute for Uninstall {
#[tracing::instrument(skip_all, fields())] #[tracing::instrument(level = "debug", skip_all, fields())]
async fn execute(self) -> eyre::Result<ExitCode> { async fn execute(self) -> eyre::Result<ExitCode> {
let Self { let Self {
no_confirm, no_confirm,
@ -115,6 +116,13 @@ impl CommandExecute for Uninstall {
// TODO(@hoverbear): It would be so nice to catch errors and offer the user a way to keep going... // TODO(@hoverbear): It would be so nice to catch errors and offer the user a way to keep going...
// However that will require being able to link error -> step and manually setting that step as `Uncompleted`. // However that will require being able to link error -> step and manually setting that step as `Uncompleted`.
println!(
"\
{success}\n\
",
success = "Nix was uninstalled successfully!".green().bold(),
);
Ok(ExitCode::SUCCESS) Ok(ExitCode::SUCCESS)
} }
} }

View file

@ -87,7 +87,7 @@ use planner::BuiltinPlanner;
use tokio::process::Command; use tokio::process::Command;
#[tracing::instrument(skip_all, fields(command = %format!("{:?}", command.as_std())))] #[tracing::instrument(level = "debug", skip_all, fields(command = %format!("{:?}", command.as_std())))]
async fn execute_command(command: &mut Command) -> Result<Output, std::io::Error> { async fn execute_command(command: &mut Command) -> Result<Output, std::io::Error> {
let command_str = format!("{:?}", command.as_std()); let command_str = format!("{:?}", command.as_std());
tracing::trace!("Executing `{command_str}`"); tracing::trace!("Executing `{command_str}`");
@ -104,7 +104,7 @@ async fn execute_command(command: &mut Command) -> Result<Output, std::io::Error
} }
} }
#[tracing::instrument(skip_all, fields( #[tracing::instrument(level = "debug", skip_all, fields(
k = %k.as_ref().to_string_lossy(), k = %k.as_ref().to_string_lossy(),
v = %v.as_ref().to_string_lossy(), v = %v.as_ref().to_string_lossy(),
))] ))]

View file

@ -49,7 +49,7 @@ impl InstallPlan {
version: current_version()?, version: current_version()?,
}) })
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn describe_install(&self, explain: bool) -> Result<String, HarmonicError> { pub fn describe_install(&self, explain: bool) -> Result<String, HarmonicError> {
let Self { let Self {
planner, planner,
@ -107,7 +107,7 @@ impl InstallPlan {
Ok(buf) Ok(buf)
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn install( pub async fn install(
&mut self, &mut self,
cancel_channel: impl Into<Option<Receiver<()>>>, cancel_channel: impl Into<Option<Receiver<()>>>,
@ -134,6 +134,7 @@ impl InstallPlan {
} }
} }
tracing::info!("Step: {}", action.tracing_synopsis());
if let Err(err) = action.try_execute().await { if let Err(err) = action.try_execute().await {
if let Err(err) = write_receipt(self.clone()).await { if let Err(err) = write_receipt(self.clone()).await {
tracing::error!("Error saving receipt: {:?}", err); tracing::error!("Error saving receipt: {:?}", err);
@ -149,7 +150,7 @@ impl InstallPlan {
Ok(()) Ok(())
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub fn describe_uninstall(&self, explain: bool) -> Result<String, HarmonicError> { pub fn describe_uninstall(&self, explain: bool) -> Result<String, HarmonicError> {
let Self { let Self {
version: _, version: _,
@ -208,7 +209,7 @@ impl InstallPlan {
Ok(buf) Ok(buf)
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn uninstall( pub async fn uninstall(
&mut self, &mut self,
cancel_channel: impl Into<Option<Receiver<()>>>, cancel_channel: impl Into<Option<Receiver<()>>>,
@ -235,6 +236,7 @@ impl InstallPlan {
} }
} }
tracing::info!("Step: {}", action.tracing_synopsis());
if let Err(err) = action.try_revert().await { if let Err(err) = action.try_revert().await {
if let Err(err) = write_receipt(self.clone()).await { if let Err(err) = write_receipt(self.clone()).await {
tracing::error!("Error saving receipt: {:?}", err); tracing::error!("Error saving receipt: {:?}", err);
@ -286,7 +288,7 @@ fn ensure_version<'de, D: Deserializer<'de>>(d: D) -> Result<Version, D::Error>
} }
} }
#[tracing::instrument] #[tracing::instrument(level = "debug")]
async fn copy_self_to_nix_store() -> Result<(), std::io::Error> { async fn copy_self_to_nix_store() -> Result<(), std::io::Error> {
let path = std::env::current_exe()?; let path = std::env::current_exe()?;
tokio::fs::copy(path, "/nix/harmonic").await?; tokio::fs::copy(path, "/nix/harmonic").await?;