Skip to content

Commit 56daf3f

Browse files
committed
Fix flake input name resolution when unambiguous
1 parent c18c9b1 commit 56daf3f

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

src/main.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ struct FlakeInput {
649649
rev: Sha,
650650
}
651651

652-
fn filter_node(node: FlakeNode) -> Option<(Branch, Sha)> {
652+
fn filter_node(node: &FlakeNode) -> Option<(Branch, Sha)> {
653653
if let (
654654
Some(FlakeOriginal::GitHub {
655655
owner: owner_original,
@@ -661,14 +661,14 @@ fn filter_node(node: FlakeNode) -> Option<(Branch, Sha)> {
661661
repo: repo_locked,
662662
rev,
663663
}),
664-
) = (node.original, node.locked)
664+
) = (&node.original, &node.locked)
665665
&& let Ok(branch) = branch.as_deref().unwrap_or("master").parse()
666666
&& owner_original == "NixOS"
667667
&& repo_original == "nixpkgs"
668668
&& owner_locked == "NixOS"
669669
&& repo_locked == "nixpkgs"
670670
{
671-
Some((branch, rev))
671+
Some((branch, *rev))
672672
} else {
673673
None
674674
}
@@ -683,31 +683,52 @@ fn resolve(
683683
(_, Some(_), None) => bail!("specified `--input` but no `flake.lock`"),
684684
(None, None, None) => bail!("no branch specified and no `flake.lock` found"),
685685
(Some(branch), None, _) => Ok((branch, None)),
686-
(None, Some(name), Some(mut flake_lock)) => {
686+
(None, Some(name), Some(flake_lock)) => {
687687
let parts: Vec<_> = name.split('/').collect();
688688
let key = flake_lock.resolve(&parts)?;
689-
let Some(index) = flake_lock.nodes.get_index_of(key) else {
689+
let Some(node) = flake_lock.nodes.get(key) else {
690690
bail!("no node named {key} in `flake.lock`");
691691
};
692-
// We use an index instead of direct `swap_remove` due to borrowing issues.
693-
let (_, node) = flake_lock.nodes.swap_remove_index(index).unwrap();
694692
let Some((bran, rev)) = filter_node(node) else {
695693
bail!("expected Nixpkgs in flake input named {name}");
696694
};
697695
Ok((bran, Some(FlakeInput { name, rev })))
698696
}
699697
(None, None, Some(flake_lock)) => {
700-
let mut choices: Vec<_> = flake_lock
701-
.nodes
702-
.into_iter()
703-
.filter_map(|(name, node)| Some((name, filter_node(node)?)))
704-
.collect();
705-
let (name, (branch, rev)) = choices
706-
.pop()
707-
.ok_or_else(|| anyhow!("no Nixpkgs input found in `flake.lock`"))?;
708-
if !choices.is_empty() {
698+
let mut paths = Vec::new();
699+
let mut stack = vec![(None, &flake_lock.root)];
700+
while let Some((path, key)) = stack.pop() {
701+
let index = paths.len();
702+
paths.push((path, key));
703+
if let Some(FlakeNode {
704+
inputs: Some(inputs),
705+
..
706+
}) = flake_lock.nodes.get(key)
707+
{
708+
for (input, subpath) in inputs {
709+
if let FlakePath::Direct(subkey) = subpath {
710+
stack.push((Some((index, input)), subkey));
711+
}
712+
}
713+
}
714+
}
715+
let mut it = paths.iter().enumerate().filter_map(|(index, (_, key))| {
716+
let (branch, rev) = filter_node(flake_lock.nodes.get(*key)?)?;
717+
Some((index, branch, rev))
718+
});
719+
let Some((mut index, branch, rev)) = it.next() else {
720+
bail!("no Nixpkgs input found in `flake.lock`");
721+
};
722+
if it.next().is_some() {
709723
bail!("multiple Nixpkgs inputs in `flake.lock`; please specify `--input`");
710724
}
725+
let mut parts = Vec::<&str>::new();
726+
while let (Some((parent, part)), _) = paths[index] {
727+
parts.push(part);
728+
index = parent;
729+
}
730+
parts.reverse();
731+
let name = parts.join("/");
711732
Ok((branch, Some(FlakeInput { name, rev })))
712733
}
713734
}

0 commit comments

Comments
 (0)