forked from lix-project/lix-installer
Tidy and flesh out README
This commit is contained in:
parent
d675647fc9
commit
d35edb976f
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -264,26 +264,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.20"
|
||||
version = "4.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
|
||||
checksum = "3b1a0a4208c6c483b952ad35c6eed505fc13b46f08f631b81e828084a9318d74"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.18"
|
||||
version = "4.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
checksum = "db342ce9fda24fb191e2ed4e102055a4d381c1086a06630174cd8da8d5d917ce"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
|
@ -294,9 +292,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
@ -1443,12 +1441,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.33"
|
||||
|
|
|
@ -9,7 +9,7 @@ resolver = "2"
|
|||
async-tar = "0.4.2"
|
||||
async-trait = "0.1.57"
|
||||
atty = "0.2.14"
|
||||
clap = { version = "3.2.20", features = ["derive", "env"] }
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
color-eyre = "0.6.2"
|
||||
crossterm = { version = "0.25.0", features = ["event-stream"] }
|
||||
eyre = "0.6.8"
|
||||
|
|
67
README.md
67
README.md
|
@ -1,14 +1,67 @@
|
|||
# Harmonic
|
||||
|
||||
> **Harmonic is pre-release and experimental.** Don't run it on machines you care about.
|
||||
|
||||
Harmonic is an opinionated, experimental Nix installer.
|
||||
|
||||
> **Harmonic is pre-release, pre-early access.** Don't run it on machines you care about.
|
||||
## Status
|
||||
|
||||
Currently it supports:
|
||||
Harmonic is **pre-release and experimental**. It is not ready for you to use! *Please* don't use it on a machine you are not planning to oblierate!
|
||||
|
||||
* x86_64 Linux with systemd init
|
||||
* (Planned) aarch64 Linux with systemd init
|
||||
* (Planned) x86_64 MacOS
|
||||
* (Planned) aarch64 MacOS
|
||||
Planned support:
|
||||
|
||||
Harmonic may also support some form of NixOS install in the future.
|
||||
* [x] Multi-user x86_64 Linux with systemd init
|
||||
* [ ] Multi-user aarch64 Linux with systemd init
|
||||
* [ ] Multi-user x86_64 MacOS
|
||||
* [ ] Single-user x86_64 Linux with systemd init
|
||||
* [ ] Single-user aarch64 Linux with systemd init
|
||||
* [ ] Multi-user aarch64 MacOS
|
||||
* [ ] Others...
|
||||
|
||||
## Installation Differences
|
||||
|
||||
Differing from the current official Nix installer scripts:
|
||||
|
||||
* Nix is installed with the `nix-command` and `flakes` features enabled in the `nix.conf`
|
||||
* Harmonic stores an installation receipt (for uninstalling) at `/nix/receipt.json`
|
||||
|
||||
## Motivations
|
||||
|
||||
The current Nix installer scripts do an excellent job, however they are difficult to maintain. Subtle differences in the shell implementations, and certain characteristics of bash scripts make it difficult to make meaningful changes to the installer.
|
||||
|
||||
Our team wishes to experiment with the idea of an installer in a more structured language and see if this is a worthwhile alternative. Along the way, we are also exploring a few other ideas, such as:
|
||||
|
||||
* offering users a chance to review an accurate, calculated install plan
|
||||
* keeping an installation receipt for uninstallation
|
||||
* offering users with a failing install the chance to revert
|
||||
* doing whatever tasks we can in parallel
|
||||
|
||||
So far, our explorations have been quite fruitful, so we wanted to share and keep exploring.
|
||||
|
||||
## Building
|
||||
|
||||
Harmonic is pre-release and we do not provide binaries at this time.
|
||||
|
||||
Since you'll be using Harmonic to install Nix on systems without Nix, the default build is a static binary.
|
||||
|
||||
Build it on a system with Nix:
|
||||
|
||||
```bash
|
||||
nix build github:determinatesystems/harmonic
|
||||
```
|
||||
|
||||
Then copy the `result/bin/harmonic` to the machine you wish to run it on.
|
||||
|
||||
## Running
|
||||
|
||||
Harmonic must be run as `root` or via `sudo`, as it needs to alter the system and cannot elevate privileges without significant complexity.
|
||||
|
||||
Install Nix with default options:
|
||||
|
||||
```bash
|
||||
./harmonic
|
||||
```
|
||||
|
||||
To observe verbose logging, either use `harmonic -V`, for extremely verbose trace logging use `RUST_LOG=harmonic=trace harmonic`.
|
||||
|
||||
Harmonic supports many of the options the current official Nix installer scripts. Review `harmonic --help` for details.
|
|
@ -121,17 +121,18 @@
|
|||
};
|
||||
in
|
||||
rec {
|
||||
default = harmonic;
|
||||
harmonic = naerskLib.buildPackage
|
||||
(sharedAttrs // { });
|
||||
} // lib.optionalAttrs (system == "x86_64-linux") {
|
||||
} // lib.optionalAttrs (system == "x86_64-linux") rec {
|
||||
default = harmonicStatic;
|
||||
harmonicStatic = naerskLib.buildPackage
|
||||
(sharedAttrs // {
|
||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||
OPENSSL_LIB_DIR = "${pkgs.pkgsStatic.openssl.out}/lib";
|
||||
OPENSSL_INCLUDE_DIR = "${pkgs.pkgsStatic.openssl.dev}";
|
||||
});
|
||||
} // lib.optionalAttrs (system == "aarch64-linux") {
|
||||
} // lib.optionalAttrs (system == "aarch64-linux") rec {
|
||||
default = harmonicStatic;
|
||||
harmonicStatic = naerskLib.buildPackage
|
||||
(sharedAttrs // {
|
||||
CARGO_BUILD_TARGET = "aarch64-unknown-linux-musl";
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
|||
use bytes::Buf;
|
||||
use reqwest::Url;
|
||||
use serde::Serialize;
|
||||
use tokio::task::{spawn_blocking, JoinError};
|
||||
use tokio::task::{JoinError};
|
||||
|
||||
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ impl clap::builder::TypedValueParser for ChannelValueParser {
|
|||
value: &std::ffi::OsStr,
|
||||
) -> Result<Self::Value, clap::Error> {
|
||||
let buf = value.to_str().ok_or_else(|| {
|
||||
clap::Error::raw(clap::ErrorKind::InvalidValue, "Should be all UTF-8")
|
||||
clap::Error::raw(clap::error::ErrorKind::InvalidValue, "Should be all UTF-8")
|
||||
})?;
|
||||
let (name, url) = buf.split_once('=').ok_or_else(|| {
|
||||
clap::Error::raw(
|
||||
clap::ErrorKind::InvalidValue,
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
"Should be formatted `name=url`",
|
||||
)
|
||||
})?;
|
||||
|
|
|
@ -8,8 +8,8 @@ use valuable::Valuable;
|
|||
#[derive(clap::Args, Debug, Valuable)]
|
||||
pub struct Instrumentation {
|
||||
/// Enable debug logs, -vv for trace
|
||||
#[clap(short = 'v', long, parse(from_occurrences), global = true)]
|
||||
pub(crate) verbose: usize,
|
||||
#[clap(short = 'v', long, action = clap::ArgAction::Count, global = true)]
|
||||
pub(crate) verbose: u8,
|
||||
}
|
||||
|
||||
impl<'a> Instrumentation {
|
||||
|
|
|
@ -15,6 +15,8 @@ pub(crate) trait CommandExecute {
|
|||
}
|
||||
|
||||
/// An opinionated, experimental Nix installer
|
||||
///
|
||||
/// Plans a Nix install, prompts for confirmation, then executes it
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(version)]
|
||||
pub(crate) struct HarmonicCli {
|
||||
|
@ -80,7 +82,7 @@ impl CommandExecute for HarmonicCli {
|
|||
match subcommand {
|
||||
Some(HarmonicSubcommand::Plan(plan)) => plan.execute().await,
|
||||
Some(HarmonicSubcommand::Execute(execute)) => execute.execute().await,
|
||||
Some(HarmonicSubcommand::Revert(revert)) => revert.execute().await,
|
||||
Some(HarmonicSubcommand::Uninstall(revert)) => revert.execute().await,
|
||||
None => {
|
||||
let mut settings = InstallSettings::default();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use harmonic::InstallPlan;
|
|||
|
||||
use crate::{cli::CommandExecute, interaction};
|
||||
|
||||
/// An opinionated, experimental Nix installer
|
||||
/// Execute an install using an existing plan
|
||||
#[derive(Debug, Parser)]
|
||||
pub(crate) struct Execute {
|
||||
#[clap(
|
|
@ -1,13 +1,13 @@
|
|||
mod plan;
|
||||
use plan::Plan;
|
||||
mod execute;
|
||||
use execute::Execute;
|
||||
mod revert;
|
||||
use revert::Revert;
|
||||
mod install;
|
||||
use install::Execute;
|
||||
mod uninstall;
|
||||
use uninstall::Uninstall;
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub(crate) enum HarmonicSubcommand {
|
||||
Plan(Plan),
|
||||
Execute(Execute),
|
||||
Revert(Revert),
|
||||
Uninstall(Uninstall),
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use eyre::WrapErr;
|
|||
|
||||
use crate::cli::{arg::ChannelValue, CommandExecute};
|
||||
|
||||
/// An opinionated, experimental Nix installer
|
||||
/// Plan an install that can be repeated on an identical host later
|
||||
#[derive(Debug, Parser)]
|
||||
pub(crate) struct Plan {
|
||||
/// Channel(s) to add by default, pass multiple times for multiple channels
|
||||
|
|
|
@ -6,9 +6,9 @@ use harmonic::InstallPlan;
|
|||
|
||||
use crate::{cli::CommandExecute, interaction};
|
||||
|
||||
/// An opinionated, experimental Nix installer
|
||||
/// Uninstall a previously installed Nix (only Harmonic done installs supported)
|
||||
#[derive(Debug, Parser)]
|
||||
pub(crate) struct Revert {
|
||||
pub(crate) struct Uninstall {
|
||||
#[clap(
|
||||
long,
|
||||
action(ArgAction::SetTrue),
|
||||
|
@ -21,7 +21,7 @@ pub(crate) struct Revert {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl CommandExecute for Revert {
|
||||
impl CommandExecute for Uninstall {
|
||||
#[tracing::instrument(skip_all, fields())]
|
||||
async fn execute(self) -> eyre::Result<ExitCode> {
|
||||
let Self {
|
Loading…
Reference in a new issue