-
-
Notifications
You must be signed in to change notification settings - Fork 92
Expand file tree
/
Copy pathdarwin.rs
More file actions
149 lines (126 loc) · 4.74 KB
/
darwin.rs
File metadata and controls
149 lines (126 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use color_eyre::eyre::Context;
use tracing::{debug, warn};
use crate::commands::Command;
use crate::interface::{DarwinArgs, DarwinRebuildArgs, DarwinReplArgs, DarwinSubcommand};
use crate::update::update;
use crate::util::platform;
use crate::Result;
const SYSTEM_PROFILE: &str = "/nix/var/nix/profiles/system";
const CURRENT_PROFILE: &str = "/run/current-system";
impl DarwinArgs {
pub fn run(self) -> Result<()> {
use DarwinRebuildVariant::{Build, Switch};
match self.subcommand {
DarwinSubcommand::Switch(args) => args.rebuild(Switch),
DarwinSubcommand::Build(args) => {
if args.common.ask || args.common.dry {
warn!("`--ask` and `--dry` have no effect for `nh darwin build`");
}
args.rebuild(Build)
}
DarwinSubcommand::Repl(args) => args.run(),
}
}
}
enum DarwinRebuildVariant {
Switch,
Build,
}
impl DarwinRebuildArgs {
fn rebuild(self, variant: DarwinRebuildVariant) -> Result<()> {
use DarwinRebuildVariant::{Build, Switch};
// Ensure we're not running as root
platform::check_not_root(false)?;
if self.update_args.update {
update(&self.common.installable, self.update_args.update_input)?;
}
let hostname = self
.hostname
.ok_or(())
.or_else(|()| crate::util::get_hostname())?;
// Set up temporary directory for build results
let out_path = platform::create_output_path(self.common.out_link, "nh-os")?;
debug!(?out_path);
// Check for environment variable override for flake path
let installable =
platform::resolve_env_installable("NH_DARWIN_FLAKE", self.common.installable.clone());
// Configure the installable for Darwin
let toplevel = platform::extend_installable_for_platform(
installable,
"darwinConfigurations",
&["toplevel"],
Some(hostname),
true,
&self
.extra_args
.iter()
.map(std::convert::Into::into)
.collect::<Vec<_>>(),
)?;
// Build the nix-darwin configuration
platform::build_configuration(
toplevel,
out_path.as_ref(),
&self.extra_args,
None,
"Building Darwin configuration",
self.common.no_nom,
)?;
let target_profile = out_path.get_path().to_owned();
target_profile.try_exists().context("Doesn't exist")?;
// Show diff between current and new configuration
platform::compare_configurations(
CURRENT_PROFILE,
&target_profile,
false,
"Comparing changes",
)?;
// Ask for confirmation if needed
if !platform::confirm_action(self.common.ask, self.common.dry)? && !matches!(variant, Build)
{
return Ok(());
}
if matches!(variant, Switch) {
Command::new("nix")
.args(["build", "--no-link", "--profile", SYSTEM_PROFILE])
.arg(out_path.get_path())
.elevate(true)
.dry(self.common.dry)
.run()?;
let darwin_rebuild = out_path.get_path().join("sw/bin/darwin-rebuild");
let activate_user = out_path.get_path().join("activate-user");
// Determine if we need to elevate privileges
let needs_elevation = !activate_user
.try_exists()
.context("Failed to check if activate-user file exists")?
|| std::fs::read_to_string(&activate_user)
.context("Failed to read activate-user file")?
.contains("# nix-darwin: deprecated");
// Create and run the activation command with or without elevation
Command::new(darwin_rebuild)
.arg("activate")
.message("Activating configuration")
.elevate(needs_elevation)
.dry(self.common.dry)
.run()?;
}
// Make sure out_path is not accidentally dropped
// https://docs.rs/tempfile/3.12.0/tempfile/index.html#early-drop-pitfall
drop(out_path);
Ok(())
}
}
impl DarwinReplArgs {
fn run(self) -> Result<()> {
// Check for environment variable override for flake path
let installable = platform::resolve_env_installable("NH_DARWIN_FLAKE", self.installable);
// Launch the nix REPL with the Darwin configuration
platform::run_repl(
installable,
"darwinConfigurations",
&["toplevel"],
self.hostname,
&[],
)
}
}