Implements configurable package list URLs. Implements #75.

This commit is contained in:
Dominik Picheta 2015-12-29 13:43:05 +00:00
commit 835157ce34
4 changed files with 164 additions and 38 deletions

View file

@ -1,6 +1,6 @@
# Copyright (C) Dominik Picheta. All rights reserved.
# BSD License. Look at license.txt for more info.
import parsecfg, streams, strutils, os
import parsecfg, streams, strutils, os, tables
import tools, version, nimbletypes
@ -8,7 +8,11 @@ type
Config* = object
nimbleDir*: string
chcp*: bool # Whether to change the code page in .cmd files on Win.
packageLists*: Table[string, PackageList] ## URLs to packages.json files
PackageList* = object
name*: string
urls*: seq[string]
proc initConfig(): Config =
if getNimrodVersion() > newVersion("0.9.6"):
@ -18,6 +22,22 @@ proc initConfig(): Config =
result.chcp = true
result.packageLists = initTable[string, PackageList]()
let defaultPkgList = PackageList(name: "Official", urls: @[
"http://irclogs.nim-lang.org/packages.json",
"http://nim-lang.org/nimble/packages.json",
"https://github.com/nim-lang/packages/raw/master/packages.json"
])
result.packageLists["official"] = defaultPkgList
proc initPackageList(): PackageList =
result.name = ""
result.urls = @[]
proc addCurrentPkgList(config: var Config, currentPackageList: PackageList) =
if currentPackageList.name.len > 0:
config.packageLists[currentPackageList.name.normalize] = currentPackageList
proc parseConfig*(): Config =
result = initConfig()
var confFile = getConfigDir() / "nimble" / "nimble.ini"
@ -34,12 +54,23 @@ proc parseConfig*(): Config =
echo("Reading from config file at ", confFile)
var p: CfgParser
open(p, f, confFile)
var currentSection = ""
var currentPackageList = initPackageList()
while true:
var e = next(p)
case e.kind
of cfgEof:
addCurrentPkgList(result, currentPackageList)
break
of cfgSectionStart: discard
of cfgSectionStart:
addCurrentPkgList(result, currentPackageList)
currentSection = e.section
case currentSection.normalize
of "packagelist":
currentPackageList = initPackageList()
else:
raise newException(NimbleError, "Unable to parse config file:" &
" Unknown section: " & e.key)
of cfgKeyValuePair, cfgOption:
case e.key.normalize
of "nimbledir":
@ -48,6 +79,16 @@ proc parseConfig*(): Config =
result.nimbleDir = e.value
of "chcp":
result.chcp = parseBool(e.value)
of "name":
case currentSection.normalize
of "packagelist":
currentPackageList.name = e.value
else: assert false
of "url":
case currentSection.normalize
of "packagelist":
currentPackageList.urls.add(e.value)
else: assert false
else:
raise newException(NimbleError, "Unable to parse config file:" &
" Unknown key: " & e.key)

View file

@ -1,6 +1,6 @@
# Copyright (C) Dominik Picheta. All rights reserved.
# BSD License. Look at license.txt for more info.
import parsecfg, json, streams, strutils, parseutils, os
import parsecfg, json, streams, strutils, parseutils, os, sets, tables
import version, tools, nimbletypes, options
type
@ -127,25 +127,35 @@ proc readMetaData*(path: string): MetaData =
let jsonmeta = parseJson(cont)
result.url = jsonmeta["url"].str
proc getPackage*(pkg: string, packagesPath: string, resPkg: var Package): bool =
## Searches ``packagesPath`` file saving into ``resPkg`` the found package.
proc getPackage*(pkg: string, options: Options,
resPkg: var Package): bool =
## Searches any packages.json files defined in ``options.config.packageLists``
## Saves the found package into ``resPkg``.
##
## Pass in ``pkg`` the name of the package you are searching for. As
## convenience the proc returns a boolean specifying if the ``resPkg`` was
## successfully filled with good data.
let packages = parseFile(packagesPath)
for p in packages:
if p["name"].str == pkg:
resPkg = p.fromJson()
return true
for name, list in options.config.packageLists:
echo("Searching in \"", name, "\" package list...")
let packages = parseFile(options.getNimbleDir() /
"packages_" & name.toLower() & ".json")
for p in packages:
if p["name"].str == pkg:
resPkg = p.fromJson()
return true
proc getPackageList*(packagesPath: string): seq[Package] =
## Returns the list of packages found at the specified path.
proc getPackageList*(options: Options): seq[Package] =
## Returns the list of packages found in the downloaded packages.json files.
result = @[]
let packages = parseFile(packagesPath)
for p in packages:
let pkg: Package = p.fromJson()
result.add(pkg)
var namesAdded = initSet[string]()
for name, list in options.config.packageLists:
let packages = parseFile(options.getNimbleDir() /
"packages_" & name.toLower() & ".json")
for p in packages:
let pkg: Package = p.fromJson()
if pkg.name notin namesAdded:
result.add(pkg)
namesAdded.incl(pkg.name)
proc findNimbleFile*(dir: string; error: bool): string =
result = ""
@ -250,6 +260,27 @@ proc getDownloadDirName*(pkg: Package, verRange: VersionRange): string =
result.add "_"
result.add verSimple
proc needsRefresh*(options: Options): bool =
## Determines whether a ``nimble refresh`` is needed.
##
## In the future this will check a stored time stamp to determine how long
## ago the package list was refreshed.
result = true
for name, list in options.config.packageLists:
if fileExists(options.getNimbleDir() / "packages_" & name & ".json"):
result = false
proc validatePackagesList*(path: string): bool =
## Determines whether package list at ``path`` is valid.
try:
let pkgList = parseFile(path)
if pkgList.kind == JArray:
if pkgList.len == 0:
echo("WARNING: ", path, " contains no packages.")
return true
except ValueError, JsonParsingError:
return false
when isMainModule:
doAssert getNameVersion("/home/user/.nimble/libs/packagea-0.1") ==
("packagea", "0.1")