6666 subdir* : string
6767 downloadDir* : string
6868 pv* : PkgTuple # Require request
69+
70+ var urlToName: Table [string , string ] = initTable [string , string ]()
6971
7072const TaggedVersionsFileName * = " tagged_versions.json"
7173
@@ -111,9 +113,12 @@ proc getMinimalInfo*(pkg: PackageInfo, options: Options): PackageMinimalInfo =
111113 result .requires = pkg.requires.map (convertNimAliasToNim)
112114 if options.action.typ in {actionLock, actionDeps} or options.hasNimInLockFile ():
113115 result .requires = result .requires.filterIt (not it.isNim)
116+ if pkg.metadata.url != " " :
117+ urlToName[pkg.metadata.url] = result .name
114118
115119proc getMinimalInfo * (nimbleFile: string , pkgName: string , options: Options ): PackageMinimalInfo =
116120 # TODO we can use the new getPkgInfoFromDirWithDeclarativeParser to get the minimal info and add the features to the packageinfo type so this whole function can be removed
121+ # TODO we need to handle the url here as well.
117122 assert options.useDeclarativeParser, " useDeclarativeParser must be set"
118123 let nimbleFileInfo = extractRequiresInfo (nimbleFile)
119124 result .name = if pkgName.isNim: " nim" else : pkgName
@@ -500,6 +505,13 @@ proc getSolvedPackages*(pkgVersionTable: Table[string, PackageVersions], output:
500505 if otherPkg.pkgName == depName and otherPkg.version.withinRange (depVer):
501506 solvedPkg.deps.add (otherPkg)
502507 break
508+ # Collect reverse deps as solved package
509+ for solvedPkg in result .mitems:
510+ for (depName, depVer) in solvedPkg.reverseDependencies:
511+ for otherPkg in result :
512+ if otherPkg.pkgName == depName:
513+ solvedPkg.reverseDeps.add (otherPkg)
514+ break
503515
504516proc getCacheDownloadDir * (url: string , ver: VersionRange , options: Options ): string =
505517 options.pkgCachePath / getDownloadDirName (url, ver, notSetSha1Hash)
@@ -523,9 +535,11 @@ proc downloadPkgFromUrl*(pv: PkgTuple, options: Options, doPrompt = false): (Dow
523535proc downloadPkInfoForPv * (pv: PkgTuple , options: Options , doPrompt = false ): PackageInfo =
524536 let downloadRes = downloadPkgFromUrl (pv, options, doPrompt)
525537 if options.satResult.pass in {satNimSelection, satFallbackToVmParser}:
526- getPkgInfoFromDirWithDeclarativeParser (downloadRes[0 ].dir, options)
538+ result = getPkgInfoFromDirWithDeclarativeParser (downloadRes[0 ].dir, options)
527539 else :
528- downloadRes[0 ].dir.getPkgInfo (options)
540+ result = downloadRes[0 ].dir.getPkgInfo (options)
541+ if result .metadata.url != " " :
542+ urlToName[result .metadata.url] = result .basicInfo.name
529543
530544proc getAllNimReleases (options: Options ): seq [PackageMinimalInfo ] =
531545 let releases = getOfficialReleases (options)
@@ -764,21 +778,68 @@ proc solveLocalPackages*(rootPkgInfo: PackageInfo, pkgList: seq[PackageInfo], so
764778 (pkgInfo.basicInfo.version == solvedPkg.version or solvedPkg.version in pkgInfo.metadata.specialVersions):
765779 result .incl pkgInfo
766780
781+ proc areAllReqAny (dep: SolvedPackage ): bool =
782+ # Checks where all the requirements by other packages in the solution are any
783+ # This allows for using a special version to meet the requirement of the solution
784+ # Scenario will be, int he package list there is only a special version but all requirements
785+ # are any. So it wont need to download a regular version but just use the special version.
786+ for rev in dep.reverseDeps:
787+ for req in rev.requirements:
788+ if dep.pkgName == req.name:
789+ if req.ver.kind != verAny:
790+ return false
791+ true
792+
793+ proc normalizeRequirements * (pkgVersionTable: var Table [string , PackageVersions ]) =
794+ # changes the url in the name of the requirements to the real name of the package
795+ # so the resulting solvedPackages dont have url in the name
796+ var recordsToRemove: seq [tuple [url: string , name: string ]] = @ []
797+ for pkgName, pkgVersions in pkgVersionTable.mpairs:
798+ if pkgName.isUrl:
799+ recordsToRemove.add ((pkgName, urlToName[pkgName]))
800+ for pkgVersion in pkgVersions.versions.mitems:
801+ for req in pkgVersion.requires.mitems:
802+ if req.name.isUrl and req.name in urlToName:
803+ # echo "DEBUG: Normalizing requirement ", req.name, " to ", urlToName[req.name], "with version ", $req.ver, " for package ", pkgName, " version ", $pkgVersion.version
804+ req.name = urlToName[req.name]
805+ for (url, name) in recordsToRemove:
806+ if pkgVersionTable.hasKey (name):
807+ pkgVersionTable[name].versions.add (pkgVersionTable[url].versions)
808+ else :
809+ pkgVersionTable[name] = PackageVersions (pkgName: name, versions: pkgVersionTable[url].versions)
810+ pkgVersionTable.del (url)
811+
812+ # if there are special versions, we need to remove the regular versions
813+ for pkgName, pkgVersions in pkgVersionTable.mpairs:
814+ if pkgVersions.versions.filterIt (it.version.isSpecial).len > 0 :
815+ pkgVersions.versions = pkgVersions.versions.filterIt (it.version.isSpecial)
816+
817+ # if pkgVersionTable.hasKey("json_serialization"):
818+ # echo "DEBUG NEW VERSIONS FOR ", "json_serialization", " ", pkgVersionTable["json_serialization"].versions.mapIt(it.version).join(", ")
819+
767820proc solvePackages * (rootPkg: PackageInfo , pkgList: seq [PackageInfo ], pkgsToInstall: var seq [(string , Version )], options: Options , output: var string , solvedPkgs: var seq [SolvedPackage ]): HashSet [PackageInfo ] =
768821 var root: PackageMinimalInfo = rootPkg.getMinimalInfo (options)
769822 root.isRoot = true
770823 var pkgVersionTable = initTable [string , PackageVersions ]()
771824 pkgVersionTable[root.name] = PackageVersions (pkgName: root.name, versions: @ [root])
772825 collectAllVersions (pkgVersionTable, root, options, downloadMinimalPackage, pkgList.mapIt (it.getMinimalInfo (options)))
826+ # pkgVersionTable.normalizeRequirements() dont use it for now
773827 solvedPkgs = pkgVersionTable.getSolvedPackages (output).topologicalSort ()
828+ # echo "DEBUG: SolvedPkgs before post processing: ", solvedPkgs.mapIt(it.pkgName & " " & $it.version).join(", ")
774829 let systemNimCompatible = solvedPkgs.isSystemNimCompatible (options)
775-
830+ # echo "DEBUG: SolvedPkgs after post processing: ", solvedPkgs.mapIt(it.pkgName & " " & $it.version).join(", ")
776831 for solvedPkg in solvedPkgs:
777832 if solvedPkg.pkgName == root.name: continue
778833 var foundInList = false
834+ let canUseAny = solvedPkg.areAllReqAny ()
779835 for pkgInfo in pkgList:
836+ let specialVersions = if pkgInfo.metadata.specialVersions.len > 1 : pkgInfo.metadata.specialVersions.toSeq ()[1 ..^ 1 ] else : @ []
837+ let isSpecial = specialVersions.len > 0
780838 if (pkgInfo.basicInfo.name == solvedPkg.pkgName or pkgInfo.metadata.url == solvedPkg.pkgName) and
781- (pkgInfo.basicInfo.version == solvedPkg.version or solvedPkg.version in pkgInfo.metadata.specialVersions):
839+ (pkgInfo.basicInfo.version == solvedPkg.version and (not isSpecial or canUseAny) or solvedPkg.version in specialVersions) and
840+ # only add one (we could fall into adding two if there are multiple special versiosn in the package list and we can add any).
841+ # But we still allow it on upgrade as they are post proccessed in a later stage
842+ (result .toSeq.filterIt (it.basicInfo.name == solvedPkg.pkgName or it.metadata.url == solvedPkg.pkgName).len == 0 or options.action.typ in {actionUpgrade}):
782843 result .incl pkgInfo
783844 foundInList = true
784845 if not foundInList:
0 commit comments