@@ -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