Skip to content

Commit 526eae5

Browse files
authored
Merge pull request #133 from DeterminateSystems/colemickens/uds2
uds2: move merge_nix_configs to shared
2 parents a1129cb + 5f22d11 commit 526eae5

File tree

4 files changed

+146
-142
lines changed

4 files changed

+146
-142
lines changed

src/cli/cmd/login/mod.rs

+8-139
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl LoginSubcommand {
9696
// $XDG_CONFIG_HOME/nix/nix.conf; basically ~/.config/nix/nix.conf
9797
let nix_config_path = xdg.place_config_file("nix/nix.conf")?;
9898
// $XDG_CONFIG_HOME/fh/auth; basically ~/.config/fh/auth
99-
let token_path = auth_token_path()?;
99+
let token_path = user_auth_token_path()?;
100100

101101
let dnixd_state_dir = Path::new(&DETERMINATE_STATE_DIR);
102102
let netrc_file_path: PathBuf = dnixd_state_dir.join(DETERMINATE_NIXD_NETRC_NAME);
@@ -270,7 +270,7 @@ impl LoginSubcommand {
270270

271271
// TODO(cole-h): make this atomic -- copy the nix_config_path to some temporary file, then operate
272272
// on that, then move it back if all is good
273-
async fn upsert_user_nix_config(
273+
pub async fn upsert_user_nix_config(
274274
nix_config_path: &Path,
275275
netrc_file_string: &str,
276276
netrc_contents: &str,
@@ -369,8 +369,11 @@ async fn upsert_user_nix_config(
369369
.await
370370
{
371371
Ok(mut file) => {
372-
let nix_config_contents =
373-
merge_nix_configs(nix_config, nix_config_contents, merged_nix_config);
372+
let nix_config_contents = crate::shared::merge_nix_configs(
373+
nix_config,
374+
nix_config_contents,
375+
merged_nix_config,
376+
);
374377
let write_status = file.write_all(nix_config_contents.as_bytes()).await;
375378
Some(write_status.is_ok())
376379
}
@@ -399,144 +402,10 @@ async fn upsert_user_nix_config(
399402
Ok(())
400403
}
401404

402-
pub(crate) fn auth_token_path() -> Result<PathBuf, FhError> {
405+
pub(crate) fn user_auth_token_path() -> Result<PathBuf, FhError> {
403406
let xdg = xdg::BaseDirectories::new()?;
404407
// $XDG_CONFIG_HOME/flakehub/auth; basically ~/.config/flakehub/auth
405408
let token_path = xdg.place_config_file("flakehub/auth")?;
406409

407410
Ok(token_path)
408411
}
409-
410-
// NOTE(cole-h): Adapted from
411-
// https://github.com/DeterminateSystems/nix-installer/blob/0b0172547c4666f6b1eacb6561a59d6b612505a3/src/action/base/create_or_merge_nix_config.rs#L284
412-
const NIX_CONF_COMMENT_CHAR: char = '#';
413-
fn merge_nix_configs(
414-
mut existing_nix_config: nix_config_parser::NixConfig,
415-
mut existing_nix_config_contents: String,
416-
mut merged_nix_config: nix_config_parser::NixConfig,
417-
) -> String {
418-
let mut new_config = String::new();
419-
420-
// We append a newline to ensure that, in the case there are comments at the end of the
421-
// file and _NO_ trailing newline, we still preserve the entire block of comments.
422-
existing_nix_config_contents.push('\n');
423-
424-
let (associated_lines, _, _) = existing_nix_config_contents.split('\n').fold(
425-
(Vec::new(), Vec::new(), false),
426-
|(mut all_assoc, mut current_assoc, mut associating): (
427-
Vec<Vec<String>>,
428-
Vec<String>,
429-
bool,
430-
),
431-
line| {
432-
let line = line.trim();
433-
434-
if line.starts_with(NIX_CONF_COMMENT_CHAR) {
435-
associating = true;
436-
} else if line.is_empty() || !line.starts_with(NIX_CONF_COMMENT_CHAR) {
437-
associating = false;
438-
}
439-
440-
current_assoc.push(line.to_string());
441-
442-
if !associating {
443-
all_assoc.push(current_assoc);
444-
current_assoc = Vec::new();
445-
}
446-
447-
(all_assoc, current_assoc, associating)
448-
},
449-
);
450-
451-
for line_group in associated_lines {
452-
if line_group.is_empty() || line_group.iter().all(|line| line.is_empty()) {
453-
continue;
454-
}
455-
456-
// This expect should never reasonably panic, because we would need a line group
457-
// consisting solely of a comment and nothing else, but unconditionally appending a
458-
// newline to the config string before grouping above prevents this from occurring.
459-
let line_idx = line_group
460-
.iter()
461-
.position(|line| !line.starts_with(NIX_CONF_COMMENT_CHAR))
462-
.expect("There should always be one line without a comment character");
463-
464-
let setting_line = &line_group[line_idx];
465-
let comments = line_group[..line_idx].join("\n");
466-
467-
// If we're here, but the line without a comment char is empty, we have
468-
// standalone comments to preserve, but no settings with inline comments.
469-
if setting_line.is_empty() {
470-
for line in &line_group {
471-
new_config.push_str(line);
472-
new_config.push('\n');
473-
}
474-
475-
continue;
476-
}
477-
478-
// Preserve inline comments for settings we've merged
479-
let to_remove = if let Some((name, value)) = existing_nix_config
480-
.settings()
481-
.iter()
482-
.find(|(name, _value)| setting_line.starts_with(*name))
483-
{
484-
new_config.push_str(&comments);
485-
new_config.push('\n');
486-
new_config.push_str(name);
487-
new_config.push_str(" = ");
488-
489-
if let Some(merged_value) = merged_nix_config.settings_mut().shift_remove(name) {
490-
new_config.push_str(&merged_value);
491-
new_config.push(' ');
492-
} else {
493-
new_config.push_str(value);
494-
}
495-
496-
if let Some(inline_comment_idx) = setting_line.find(NIX_CONF_COMMENT_CHAR) {
497-
let inline_comment = &setting_line[inline_comment_idx..];
498-
new_config.push_str(inline_comment);
499-
new_config.push('\n');
500-
}
501-
502-
Some(name.clone())
503-
} else {
504-
new_config.push_str(&comments);
505-
new_config.push('\n');
506-
new_config.push_str(setting_line);
507-
new_config.push('\n');
508-
509-
None
510-
};
511-
512-
if let Some(to_remove) = to_remove {
513-
existing_nix_config.settings_mut().shift_remove(&to_remove);
514-
}
515-
}
516-
517-
// Add the leftover existing nix config
518-
for (name, value) in existing_nix_config.settings() {
519-
if merged_nix_config.settings().get(name).is_some() {
520-
continue;
521-
}
522-
523-
new_config.push_str(name);
524-
new_config.push_str(" = ");
525-
new_config.push_str(value);
526-
new_config.push('\n');
527-
}
528-
529-
new_config.push('\n');
530-
531-
for (name, value) in merged_nix_config.settings() {
532-
new_config.push_str(name);
533-
new_config.push_str(" = ");
534-
new_config.push_str(value);
535-
new_config.push('\n');
536-
}
537-
538-
new_config
539-
.strip_prefix('\n')
540-
.unwrap_or(&new_config)
541-
.to_owned()
542-
}

src/cli/cmd/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,13 @@ async fn make_base_client(_authenticated: bool) -> Result<Client, FhError> {
341341

342342
#[cfg(not(test))]
343343
async fn make_base_client(authenticated: bool) -> Result<Client, FhError> {
344-
use self::login::auth_token_path;
344+
use self::login::user_auth_token_path;
345345

346346
let mut headers = HeaderMap::new();
347347
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
348348

349349
if authenticated {
350-
if let Ok(token) = tokio::fs::read_to_string(auth_token_path()?).await {
350+
if let Ok(token) = tokio::fs::read_to_string(user_auth_token_path()?).await {
351351
if !token.is_empty() {
352352
headers.insert(
353353
AUTHORIZATION,

src/cli/cmd/status/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl CommandExecute for StatusSubcommand {
7272
pub(crate) async fn get_status_from_auth_file(
7373
api_addr: url::Url,
7474
) -> color_eyre::Result<TokenStatus> {
75-
let auth_token_path = crate::cli::cmd::login::auth_token_path()?;
75+
let auth_token_path = crate::cli::cmd::login::user_auth_token_path()?;
7676
let token = tokio::fs::read_to_string(&auth_token_path)
7777
.await
7878
.wrap_err_with(|| format!("Could not open {}", auth_token_path.display()))?;

src/shared/mod.rs

+135
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub async fn update_netrc_file(
2222
.await
2323
.wrap_err("failed to update netrc file contents")
2424
}
25+
2526
pub fn netrc_contents(
2627
frontend_addr: &url::Url,
2728
backend_addr: &url::Url,
@@ -47,3 +48,137 @@ pub fn netrc_contents(
4748
);
4849
Ok(contents)
4950
}
51+
52+
// NOTE(cole-h): Adapted from
53+
// https://github.com/DeterminateSystems/nix-installer/blob/0b0172547c4666f6b1eacb6561a59d6b612505a3/src/action/base/create_or_merge_nix_config.rs#L284
54+
const NIX_CONF_COMMENT_CHAR: char = '#';
55+
pub fn merge_nix_configs(
56+
mut existing_nix_config: nix_config_parser::NixConfig,
57+
mut existing_nix_config_contents: String,
58+
mut merged_nix_config: nix_config_parser::NixConfig,
59+
) -> String {
60+
let mut new_config = String::new();
61+
62+
// We append a newline to ensure that, in the case there are comments at the end of the
63+
// file and _NO_ trailing newline, we still preserve the entire block of comments.
64+
existing_nix_config_contents.push('\n');
65+
66+
let (associated_lines, _, _) = existing_nix_config_contents.split('\n').fold(
67+
(Vec::new(), Vec::new(), false),
68+
|(mut all_assoc, mut current_assoc, mut associating): (
69+
Vec<Vec<String>>,
70+
Vec<String>,
71+
bool,
72+
),
73+
line| {
74+
let line = line.trim();
75+
76+
if line.starts_with(NIX_CONF_COMMENT_CHAR) {
77+
associating = true;
78+
} else if line.is_empty() || !line.starts_with(NIX_CONF_COMMENT_CHAR) {
79+
associating = false;
80+
}
81+
82+
current_assoc.push(line.to_string());
83+
84+
if !associating {
85+
all_assoc.push(current_assoc);
86+
current_assoc = Vec::new();
87+
}
88+
89+
(all_assoc, current_assoc, associating)
90+
},
91+
);
92+
93+
for line_group in associated_lines {
94+
if line_group.is_empty() || line_group.iter().all(|line| line.is_empty()) {
95+
continue;
96+
}
97+
98+
// This expect should never reasonably panic, because we would need a line group
99+
// consisting solely of a comment and nothing else, but unconditionally appending a
100+
// newline to the config string before grouping above prevents this from occurring.
101+
let line_idx = line_group
102+
.iter()
103+
.position(|line| !line.starts_with(NIX_CONF_COMMENT_CHAR))
104+
.expect("There should always be one line without a comment character");
105+
106+
let setting_line = &line_group[line_idx];
107+
let comments = line_group[..line_idx].join("\n");
108+
109+
// If we're here, but the line without a comment char is empty, we have
110+
// standalone comments to preserve, but no settings with inline comments.
111+
if setting_line.is_empty() {
112+
for line in &line_group {
113+
new_config.push_str(line);
114+
new_config.push('\n');
115+
}
116+
117+
continue;
118+
}
119+
120+
// Preserve inline comments for settings we've merged
121+
let to_remove = if let Some((name, value)) = existing_nix_config
122+
.settings()
123+
.iter()
124+
.find(|(name, _value)| setting_line.starts_with(*name))
125+
{
126+
new_config.push_str(&comments);
127+
new_config.push('\n');
128+
new_config.push_str(name);
129+
new_config.push_str(" = ");
130+
131+
if let Some(merged_value) = merged_nix_config.settings_mut().shift_remove(name) {
132+
new_config.push_str(&merged_value);
133+
new_config.push(' ');
134+
} else {
135+
new_config.push_str(value);
136+
}
137+
138+
if let Some(inline_comment_idx) = setting_line.find(NIX_CONF_COMMENT_CHAR) {
139+
let inline_comment = &setting_line[inline_comment_idx..];
140+
new_config.push_str(inline_comment);
141+
new_config.push('\n');
142+
}
143+
144+
Some(name.clone())
145+
} else {
146+
new_config.push_str(&comments);
147+
new_config.push('\n');
148+
new_config.push_str(setting_line);
149+
new_config.push('\n');
150+
151+
None
152+
};
153+
154+
if let Some(to_remove) = to_remove {
155+
existing_nix_config.settings_mut().shift_remove(&to_remove);
156+
}
157+
}
158+
159+
// Add the leftover existing nix config
160+
for (name, value) in existing_nix_config.settings() {
161+
if merged_nix_config.settings().get(name).is_some() {
162+
continue;
163+
}
164+
165+
new_config.push_str(name);
166+
new_config.push_str(" = ");
167+
new_config.push_str(value);
168+
new_config.push('\n');
169+
}
170+
171+
new_config.push('\n');
172+
173+
for (name, value) in merged_nix_config.settings() {
174+
new_config.push_str(name);
175+
new_config.push_str(" = ");
176+
new_config.push_str(value);
177+
new_config.push('\n');
178+
}
179+
180+
new_config
181+
.strip_prefix('\n')
182+
.unwrap_or(&new_config)
183+
.to_owned()
184+
}

0 commit comments

Comments
 (0)