pub fn resolve(
        reqs: &[Req],
        locked: &[crate::Package],
        os: util::Os,
        py_vers: &Version,
        //) -> Result<Vec<(String, Version, Vec<Req>)>, reqwest::Error> {
    ) -> Result<Vec<crate::Package>, reqwest::Error> {
        let mut result = Vec::new();
        let mut cache = HashMap::new();
        let mut reqs_searched = Vec::new();

        let mut version_cache = HashMap::new();
        if guess_graph(
            0,
            reqs,
            locked,
            os,
            &[],
            py_vers,
            &mut result,
            &mut cache,
            &mut version_cache,
            &mut reqs_searched,
        )
        .is_err()
        {
            util::abort("Problem resolving dependencies");
        }

        let mut by_name: HashMap<String, Vec<Dependency>> = HashMap::new();
        for mut dep in result.clone() {
            // The formatted name may be different from the pypi one. Eg `IPython` vice `ipython`.
            let fmtd_name = format_name(&dep.name, &version_cache);
            dep.name = fmtd_name.clone();

            if let Some(k) = by_name.get_mut(&dep.name) {
                k.push(dep)
            } else {
                by_name.insert(fmtd_name, vec![dep]);
            }
        }

        // Deal with duplicates, conflicts etc. The code above assumed no conflicts, and that
        // we can pick the newest compatible version for each req. We pass only the info
        // needed to build the locked dependencies, and strip intermediary info like ids.

        // updated_ids is used to remap lockpack dependencies, when a dep(version) other than their
        // parent is chosen for the package.
        let mut updated_ids = HashMap::new();
        let mut result_cleaned = vec![];
        for (name, deps) in &by_name {
            let fmtd_name = format_name(name, &version_cache);
            match deps.len() {
                1 => {
                    // This dep is only specified once; no need to resolve conflicts.
                    let dep = &deps[0];

                    result_cleaned.push(Package {
                        id: dep.id,
                        parent: dep.parent,
                        name: fmtd_name,
                        version: dep.version.clone(),
                        deps: vec![], // to be filled in after resolution
                        rename: Rename::No,
                    });
                }
                x if x > 1 => {
                    // Find what constraints are driving each dep that shares a name.
                    let constraints = find_constraints(reqs, &result, deps);

                    let _names: Vec<String> = deps.iter().map(|d| d.version.to_string()).collect();
                    let inter = dep_types::intersection_many(&constraints);

                    if inter.is_empty() {
                        result_cleaned.append(&mut make_renamed_packs(
                            &version_cache,
                            deps,
                            &fmtd_name,
                        ));
                        continue;
                    }

                    // If a version we've examined meets all constraints for packages that use it, use it -
                    // we've already built the graph to accommodate its sub-deps.

                    // If unable, find the highest version that meets the constraints, and determine
                    // what its dependencies are.

                    // Otherwise install all,
                    // and rename as-required(By which criteria? the older one?). This ensures our
                    // graph is always resolveable, and avoids diving through the graph recursively,
                    // dealing with cycles etc. There may be ways around this in some cases.
                    // todo: Renaming may not work if the renamed dep uses compiled code.

                    let newest_compatible = deps
                        .iter()
                        .filter(|dep| {
                            inter
                                .iter()
                                .any(|i| i.0 <= dep.version && dep.version <= i.1)
                        })
                        .max_by(|a, b| a.version.cmp(&b.version));

                    if let Some(best) = newest_compatible {
                        result_cleaned.push(Package {
                            id: best.id,
                            parent: best.parent,
                            name: fmtd_name,
                            version: best.version.clone(),
                            deps: vec![], // to be filled in after resolution
                            rename: Rename::No,
                        });

                        // Indicate we need to update the parent. We can't do it here, since
                        // we don't know if we're pr
                        // ocessed the parent[s] yet. Not doing this will
                        // result in incorrect dependencies listed in lock packs.
                        for dep in deps {
                            // note that we push the old ids, so we can update the subdeps with the new versions.
                            //                        updated_ids.insert(dep.id, best.id).expect("Problem inserting updated id");
                            updated_ids.insert(dep.id, best.id);
                        }
                    } else {
                        // We consider the possibility there's a compatible version
                        // that wasn't one of the best-per-req we queried.
                        println!("⛏️ Digging deeper to resolve dependencies for {}...", name);

                        // I think we should query with the raw name, not fmted?
                        let versions = &version_cache.get(name).unwrap().2;

                        if versions.is_empty() {
                            result_cleaned.append(&mut make_renamed_packs(
                                &version_cache,
                                deps,
                                //                            &result,
                                &fmtd_name,
                            ));
                            continue;
                        }

                        // Generate dependencies here for all avail versions.
                        let unresolved_deps = versions.iter().filter_map(|vers| {
                            if inter.iter().any(|i| i.0 <= *vers && *vers <= i.1) {
                                Some(Dependency {
                                    id: 0, // placeholder; we'll assign an id to the one we pick.
                                    name: fmtd_name.clone(),
                                    version: vers.clone(),
                                    reqs: vec![], // todo
                                    parent: 0,    // todo
                                })
                            } else {
                                None
                            }
                        });

                        let mut newest_unresolved = unresolved_deps
                            .max_by(|a, b| a.version.cmp(&b.version))
                            .unwrap();

                        newest_unresolved.id = result.iter().map(|d| d.id).max().unwrap_or(0) + 1;

                        result_cleaned.push(Package {
                            id: newest_unresolved.id,
                            parent: newest_unresolved.parent,
                            name: fmtd_name,
                            version: newest_unresolved.version,
                            deps: vec![], // to be filled in after resolution
                            rename: Rename::No,
                        });

                        // todo: Do a check on newest_unresolved! If fails, execute renamed plan

                        for dep in deps {
                            // note that we push the old ids, so we can update the subdeps with the new versions.
                            updated_ids.insert(dep.id, newest_unresolved.id);
                        }
                    }
                }
                _ => panic!("We shouldn't be seeing this!"),
            }
        }

        // Now, assign subdeps, so we can store them in the lock.
        assign_subdeps(&mut result_cleaned, &updated_ids);

        let mut a = result;
        for b in &mut a {
            b.reqs = vec![];
        }

        Ok(result_cleaned)
    }
/// Determine which dependencies we need to install, using the newest ones which meet
/// all constraints. Gets data from a cached repo, and Pypi. Returns name, version, and name/version of its deps.
Determine which dependencies we need to install, using the newest ones which meet
all constraints. Gets data from a cached repo, and Pypi. Returns name, version, and name/version of its deps.
Determine which dependencies we need to install using the newest ones which meet all constraints . Gets data from a cached repo and Pypi . Returns name version and name / version of its deps .
pub fn resolve(
        reqs: &[Req],
        locked: &[crate::Package],
        os: util::Os,
        py_vers: &Version,
        //) -> Result<Vec<(String, Version, Vec<Req>)>, reqwest::Error> {
    ) -> Result<Vec<crate::Package>, reqwest::Error> {
        let mut result = Vec::new();
        let mut cache = HashMap::new();
        let mut reqs_searched = Vec::new();
        let mut version_cache = HashMap::new();
        if guess_graph(
            0,
            reqs,
            locked,
            os,
            &[],
            py_vers,
            &mut result,
            &mut cache,
            &mut version_cache,
            &mut reqs_searched,
        )
        .is_err()
        {
            util::abort("Problem resolving dependencies");
        }
        let mut by_name: HashMap<String, Vec<Dependency>> = HashMap::new();
        for mut dep in result.clone() {
            // The formatted name may be different from the pypi one. Eg `IPython` vice `ipython`.
            let fmtd_name = format_name(&dep.name, &version_cache);
            dep.name = fmtd_name.clone();
            if let Some(k) = by_name.get_mut(&dep.name) {
                k.push(dep)
            } else {
                by_name.insert(fmtd_name, vec![dep]);
            }
        }
        // Deal with duplicates, conflicts etc. The code above assumed no conflicts, and that
        // we can pick the newest compatible version for each req. We pass only the info
        // needed to build the locked dependencies, and strip intermediary info like ids.
        // updated_ids is used to remap lockpack dependencies, when a dep(version) other than their
        // parent is chosen for the package.
        let mut updated_ids = HashMap::new();
        let mut result_cleaned = vec![];
        for (name, deps) in &by_name {
            let fmtd_name = format_name(name, &version_cache);
            match deps.len() {
                1 => {
                    // This dep is only specified once; no need to resolve conflicts.
                    let dep = &deps[0];
                    result_cleaned.push(Package {
                        id: dep.id,
                        parent: dep.parent,
                        name: fmtd_name,
                        version: dep.version.clone(),
                        deps: vec![], // to be filled in after resolution
                        rename: Rename::No,
                    });
                }
                x if x > 1 => {
                    // Find what constraints are driving each dep that shares a name.
                    let constraints = find_constraints(reqs, &result, deps);
                    let _names: Vec<String> = deps.iter().map(|d| d.version.to_string()).collect();
                    let inter = dep_types::intersection_many(&constraints);
                    if inter.is_empty() {
                        result_cleaned.append(&mut make_renamed_packs(
                            &version_cache,
                            deps,
                            &fmtd_name,
                        ));
                        continue;
                    }
                    // If a version we've examined meets all constraints for packages that use it, use it -
                    // we've already built the graph to accommodate its sub-deps.
                    // If unable, find the highest version that meets the constraints, and determine
                    // what its dependencies are.
                    // Otherwise install all,
                    // and rename as-required(By which criteria? the older one?). This ensures our
                    // graph is always resolveable, and avoids diving through the graph recursively,
                    // dealing with cycles etc. There may be ways around this in some cases.
                    // todo: Renaming may not work if the renamed dep uses compiled code.
                    let newest_compatible = deps
                        .iter()
                        .filter(|dep| {
                            inter
                                .iter()
                                .any(|i| i.0 <= dep.version && dep.version <= i.1)
                        })
                        .max_by(|a, b| a.version.cmp(&b.version));
                    if let Some(best) = newest_compatible {
                        result_cleaned.push(Package {
                            id: best.id,
                            parent: best.parent,
                            name: fmtd_name,
                            version: best.version.clone(),
                            deps: vec![], // to be filled in after resolution
                            rename: Rename::No,
                        });
                        // Indicate we need to update the parent. We can't do it here, since
                        // we don't know if we're pr
                        // ocessed the parent[s] yet. Not doing this will
                        // result in incorrect dependencies listed in lock packs.
                        for dep in deps {
                            // note that we push the old ids, so we can update the subdeps with the new versions.
                            //                        updated_ids.insert(dep.id, best.id).expect("Problem inserting updated id");
                            updated_ids.insert(dep.id, best.id);
                        }
                    } else {
                        // We consider the possibility there's a compatible version
                        // that wasn't one of the best-per-req we queried.
                        println!("⛏️ Digging deeper to resolve dependencies for {}...", name);
                        // I think we should query with the raw name, not fmted?
                        let versions = &version_cache.get(name).unwrap().2;
                        if versions.is_empty() {
                            result_cleaned.append(&mut make_renamed_packs(
                                &version_cache,
                                deps,
                                //                            &result,
                                &fmtd_name,
                            ));
                            continue;
                        }
                        // Generate dependencies here for all avail versions.
                        let unresolved_deps = versions.iter().filter_map(|vers| {
                            if inter.iter().any(|i| i.0 <= *vers && *vers <= i.1) {
                                Some(Dependency {
                                    id: 0, // placeholder; we'll assign an id to the one we pick.
                                    name: fmtd_name.clone(),
                                    version: vers.clone(),
                                    reqs: vec![], // todo
                                    parent: 0,    // todo
                                })
                            } else {
                                None
                            }
                        });
                        let mut newest_unresolved = unresolved_deps
                            .max_by(|a, b| a.version.cmp(&b.version))
                            .unwrap();
                        newest_unresolved.id = result.iter().map(|d| d.id).max().unwrap_or(0) + 1;
                        result_cleaned.push(Package {
                            id: newest_unresolved.id,
                            parent: newest_unresolved.parent,
                            name: fmtd_name,
                            version: newest_unresolved.version,
                            deps: vec![], // to be filled in after resolution
                            rename: Rename::No,
                        });
                        // todo: Do a check on newest_unresolved! If fails, execute renamed plan
                        for dep in deps {
                            // note that we push the old ids, so we can update the subdeps with the new versions.
                            updated_ids.insert(dep.id, newest_unresolved.id);
                        }
                    }
                }
                _ => panic!("We shouldn't be seeing this!"),
            }
        }
        // Now, assign subdeps, so we can store them in the lock.
        assign_subdeps(&mut result_cleaned, &updated_ids);
        let mut a = result;
        for b in &mut a {
            b.reqs = vec![];
        }
        Ok(result_cleaned)
    }
pub fn resolve ( reqs : & [ Req ] , locked : & [ crate :: Package ] , os : util :: Os , py_vers : & Version , //) -> Result<Vec<(String, Version, Vec<Req>)>, reqwest::Error> { ) -> Result < Vec < crate :: Package > , reqwest :: Error > { let mut result = Vec :: new ( ) ; let mut cache = HashMap :: new ( ) ; let mut reqs_searched = Vec :: new ( ) ; let mut version_cache = HashMap :: new ( ) ; if guess_graph ( 0 , reqs , locked , os , & [ ] , py_vers , & mut result , & mut cache , & mut version_cache , & mut reqs_searched , ) . is_err ( ) { util :: abort ( " " ) ; } let mut by_name : HashMap < String , Vec < Dependency > > = HashMap :: new ( ) ; for mut dep in result . clone ( ) { // The formatted name may be different from the pypi one. Eg `IPython` vice `ipython`. let fmtd_name = format_name ( & dep . name , & version_cache ) ; dep . name = fmtd_name . clone ( ) ; if let Some ( k ) = by_name . get_mut ( & dep . name ) { k . push ( dep ) } else { by_name . insert ( fmtd_name , vec ! [ dep ] ) ; } } // Deal with duplicates, conflicts etc. The code above assumed no conflicts, and that // we can pick the newest compatible version for each req. We pass only the info // needed to build the locked dependencies, and strip intermediary info like ids. // updated_ids is used to remap lockpack dependencies, when a dep(version) other than their // parent is chosen for the package. let mut updated_ids = HashMap :: new ( ) ; let mut result_cleaned = vec ! [ ] ; for ( name , deps ) in & by_name { let fmtd_name = format_name ( name , & version_cache ) ; match deps . len ( ) { 1 => { // This dep is only specified once; no need to resolve conflicts. let dep = & deps [ 0 ] ; result_cleaned . push ( Package { id : dep . id , parent : dep . parent , name : fmtd_name , version : dep . version . clone ( ) , deps : vec ! [ ] , // to be filled in after resolution rename : Rename :: No , } ) ; } x if x > 1 => { // Find what constraints are driving each dep that shares a name. let constraints = find_constraints ( reqs , & result , deps ) ; let _names : Vec < String > = deps . iter ( ) . map ( | d | d . version . to_string ( ) ) . collect ( ) ; let inter = dep_types :: intersection_many ( & constraints ) ; if inter . is_empty ( ) { result_cleaned . append ( & mut make_renamed_packs ( & version_cache , deps , & fmtd_name , ) ) ; continue ; } // If a version we've examined meets all constraints for packages that use it, use it - // we've already built the graph to accommodate its sub-deps. // If unable, find the highest version that meets the constraints, and determine // what its dependencies are. // Otherwise install all, // and rename as-required(By which criteria? the older one?). This ensures our // graph is always resolveable, and avoids diving through the graph recursively, // dealing with cycles etc. There may be ways around this in some cases. // todo: Renaming may not work if the renamed dep uses compiled code. let newest_compatible = deps . iter ( ) . filter ( | dep | { inter . iter ( ) . any ( | i | i . 0 <= dep . version && dep . version <= i . 1 ) } ) . max_by ( | a , b | a . version . cmp ( & b . version ) ) ; if let Some ( best ) = newest_compatible { result_cleaned . push ( Package { id : best . id , parent : best . parent , name : fmtd_name , version : best . version . clone ( ) , deps : vec ! [ ] , // to be filled in after resolution rename : Rename :: No , } ) ; // Indicate we need to update the parent. We can't do it here, since // we don't know if we're pr // ocessed the parent[s] yet. Not doing this will // result in incorrect dependencies listed in lock packs. for dep in deps { // note that we push the old ids, so we can update the subdeps with the new versions. //                        updated_ids.insert(dep.id, best.id).expect("Problem inserting updated id"); updated_ids . insert ( dep . id , best . id ) ; } } else { // We consider the possibility there's a compatible version // that wasn't one of the best-per-req we queried. println ! ( " a ); // I think we should query with the raw name, not fmted? let versions = & version_cache . get ( name ) . unwrap ( ) . 2 ; if versions . is_empty ( ) { result_cleaned . append ( & mut make_renamed_packs ( & version_cache , deps , //                            &result, & fmtd_name , ) ) ; continue ; } // Generate dependencies here for all avail versions. let unresolved_deps = versions . iter ( ) . filter_map ( | vers | { if inter . iter ( ) . any ( | i | i . 0 <= * vers && * vers <= i . 1 ) { Some ( Dependency { id : 0 , // placeholder; we'll assign an id to the one we pick. name : fmtd_name . clone ( ) , version : vers . clone ( ) , reqs : vec ! [ ] , // todo parent : 0 , // todo } ) } else { None } } ) ; let mut newest_unresolved = unresolved_deps . max_by ( | a , b | a . version . cmp ( & b . version ) ) . unwrap ( ) ; newest_unresolved . id = result . iter ( ) . map ( | d | d . id ) . max ( ) . unwrap_or ( 0 ) + 1 ; result_cleaned . push ( Package { id : newest_unresolved . id , parent : newest_unresolved . parent , name : fmtd_name , version : newest_unresolved . version , deps : vec ! [ ] , // to be filled in after resolution rename : Rename :: No , } ) ; // todo: Do a check on newest_unresolved! If fails, execute renamed plan for dep in deps { // note that we push the old ids, so we can update the subdeps with the new versions. updated_ids . insert ( dep . id , newest_unresolved . id ) ; } } } _ => panic ! ( " " ) , } } // Now, assign subdeps, so we can store them in the lock. assign_subdeps ( & mut result_cleaned , & updated_ids ) ; let mut a = result ; for b in & mut a { b . reqs = vec ! [ ] ; } Ok ( result_cleaned ) }
Determine which dependencies we need to install, using the newest ones which meet
all constraints.
Determine which dependencies we need to install using the newest ones which meet all constraints .
reqs
&[Req]
locked
&[crate::Package]
os
util::Os
py_vers
&Version
reqs
&[Req]
locked
&[crate::Package]
os
util::Os
py_vers
&Version