Da ich meine Module ausschließlich händisch verwalte, habe ich mir jetzt zumindest eine Routine zum Prüfen aller Packages auf vorhandene Updates erstellt.
EDIT 31.01.22
Die Ursache der Nicht-Erreichbarkeit der Seite:
Von 12 Packages verlinken 11 mit "../raw/master/.." auf die *.nimble (dort ist die Versionsnummer auslesbar). Aber 1 Package verwendet stattdessen: "../raw/main/..". Da hatte ich dann mit einer nicht existenten Adresse versucht zuzugreifen - deshalb HTTP-Error.
Jetzt verwende ich "master", gibt das Fehler probiere ich "main" und sollte auch das fehlschlagen wird Online-Version=0 gesetzt, was dann bedeutet: Seite falsch/nicht erreichbar.
Ich habe das Programm überarbeitet und leite die nimble-Aufrufe in eine Tmp-Datei, die ich dann auswerte.
Vorerst habe ich nur die Kommandozeilen-Version geändert. Hinzugekommen sind dort Aufrufparameter:
- "help" Gibt die möglichen Parameter aus
"list" Listet alle lokalen Packages formatiert auf.
"check" Wie "list", zusätzlich mit online verfügbarer Version.
- "update" Wie "check", zusätzlich wird für verfügbare neuere Versionen ein Update installiert.
Wobei bemerkt werden muss: Update gibt es nicht wirklich in nimble, genau sowenig, wie eine Online-Versionsabfrage. Es gibt zwar die Möglichkeit mit Flag --ver danach zu fragen - in den Repos nutzt aber niemand diesen Parameter, sodass kein Ergebnis verfügbar ist.
Zum Updaten muss also der Install-Befehl genutzt werden. Führt man Install aus, obwohl keine neuere als die installierte Version vorhanden ist, wird nachgefragt ob die lokale Version überschrieben werden soll.
Programmname jetzt: nimble_up_check_cmd.nim
Ich werde es dann später noch in die GUI-Version integrieren.
EDIT 26.01.2022
Ich habe hierfür jetzt auch eine Lösung mit GUI erstellt:
PS: Habe gerade aktualisiert und festgestellt, dass bei den mit installierten Dependencies wohl ungültige/anders dargestellte url hinterlegt sind. Dadurch crasht das Programm bei erneutem Aufruf.
Da muss ich noch mal ran. EDIT: Die Seite ist einfach nicht erreichbar, Fehlerabfrage jetzt integriert.
# compile: nim c --define:ssl --app:gui nimble_up_check_gui.nim
import os, strutils, re, httpClient, json
import wNim/[wApp, wFrame, wPanel, wButton, wTextCtrl, wListCtrl, wImageList,
wCheckBox, wBrush, wBitmap, wIcon, wMemoryDC]
let pkgsPath = getEnv("HOMEDRIVE") & getEnv("HOMEPATH") & r"\.nimble\pkgs"
type
Packages = tuple
path: string
name: string
version: string
PkgsHighest = object
name: string # package name
versions: seq[string] # all installed version numbers
version: string # highest version number
path: string # installation directory
repo: string # url of the repository
url: string # url of ".../raw/master/PACKAGE.nimble"
versionOnline: string # version number from current repository
newup: bool # indicates that a higher version is available
ListHead = tuple[text: string, format: int, width: int]
var
pkgsAll: seq[Packages] # all packages in all versions
pkgsTmp: seq[string] # temporary only unique package names
pkgsHigh: seq[PkgsHighest] # packages with highest version number
client = newHttpClient() # client for online version request
# ------------------------------------------------------------------------------
proc pkg(path, get: string): string =
# gets from package folder the name and version
let tsplit = path.splitPath().tail.split('-')
case get
of "name": result = tsplit[0]
of "version": result = tsplit[1]
proc getUrl(path: string): string =
# reads from package folder the meta file and extracts the repository-url
let
jsonFile = joinPath(path, "nimblemeta.json")
jn = jsonFile.parseFile()
result = jn["url"].str
proc getOnlineVersion(url: string): string =
# reads from repository the "package-name.nimble" and extracts the version
try:
let patt = re(r"version\s+=\s\x22([^\x22]+)", {reIgnoreCase,reMultiLine})
var
match: seq[string]
readNimble: string
try:
readNimble = client.getContent(url)
match = re.findAll(readNimble, patt)
except:
return "HTTP REQUEST ERROR"
if match.len > 0:
var
line = match[0]
pos = line.find('"')
ver = line[pos+1..line.len-1]
return ver
else: return "0" # can't read version number
except OSError:
return "CONNECTION ERROR"
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
proc getAllPkgInfo() =
# comparable to "nimble list -i", all versions
for kind, path in walkDir(pkgsPath):
if kind == pcDir:
pkgsAll.add((path: path, name: path.pkg("name"),
version: path.pkg("version")))
else: discard
# filter highest versions
# 1. write unique package names in temporary sequence
for e in pkgsAll:
if not (e.name in pkgsTmp): pkgsTmp.add(e.name)
else: discard
# 2. for each package name search highest version
# store all version numbers
var
v, p: string
h: seq[string]
for n in pkgsTmp:
v = ""
p = ""
h = newSeq[string]()
for i in 0..pkgsAll.len - 1:
if pkgsAll[i].name == n:
if pkgsAll[i].version > v:
v = pkgsAll[i].version
p = pkgsAll[i].path
h.add(pkgsAll[i].version)
else: discard
pkgsHigh.add(PkgsHighest(name: n, versions: h, version: v, path: p))
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# GUI #
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
proc setListColumns(list: wListCtrl, head: openArray[ListHead]) =
for i in 0..<head.len:
list.appendColumn(text=head[i][0], width=head[i][2])
list.setColumnFormat(i, head[i][1])
# ------------------------------------------------------------------------------
let
app = App()
frame = Frame(title="Nimble - Package Viewer",size=(620,400))
panel = frame.Panel()
button = panel.Button(label="Check Online Version")
list = panel.ListCtrl(style=wLcReport or wBorderDouble or wLcSingleSel)
var
il = ImageList(size=(16,16), mask=false, initialCount=0)
dc = MemoryDC()
bmp = Bitmap(16, 16)
dc.selectObject(bmp)
dc.clear(Brush(wGreenBrush))
let icoGreen = Icon(bmp)
dc.clear(Brush(wRedBrush))
let icoRed = Icon(bmp)
dc.clear(Brush(color=wYellow))
let icoYellow = Icon(bmp)
il.add(icoYellow) # 0
il.add(icoGreen) # 1
il.add(icoRed) # 2
list.setExtendedStyle(0x1)
list.setImageList(il)
list.setListColumns([
("Package", wListFormatLeft, 130),
("Current", wListFormatCenter, 80),
("Online", wListFormatCenter, 160),
("Installed", wListFormatLeft, wListAutosizeUseHeader)])
proc insertInstalled() =
getAllPkgInfo()
let imgIndex = 0
var item: int
for i in 0..pkgsHigh.len - 1:
item = list.appendItem([pkgsHigh[i].name, pkgsHigh[i].version,
"", $pkgsHigh[i].versions], imgIndex)
proc insertOnline() =
# read out repository url, change to "../raw/...nimble"
# ask for online version number
var
u: string
imgIndex, item: int
for i in 0..pkgsHigh.len - 1:
u = pkgsHigh[i].path.getUrl()
pkgsHigh[i].repo = u
if u[u.len-4..u.len-1] in [".git", ".nim"]: u = u[0..u.len-5] # remove file suffix if any
pkgsHigh[i].url = u & "/raw/master/" & pkgsHigh[i].name & ".nimble"
pkgsHigh[i].versionOnline = pkgsHigh[i].url.getOnlineVersion()
if (pkgsHigh[i].versionOnline > pkgsHigh[i].version):
pkgsHigh[i].newup = true
imgIndex = 2 # red
else:
pkgsHigh[i].newup = false
imgIndex = 1 # green
# to avoid failure by possible different sorting search item
item = list.findItem(pkgsHigh[i].name)
# insert online version number and change image color
list.setItemText(item, 2, pkgsHigh[i].versionOnline)
list.setItemImage(item, 0, imgIndex)
proc layout() =
panel.layout:
button:
top = panel.top + 10
right = panel.right - 15
height = bestHeight
width = bestWidth
list:
top = button.bottom + 10
left = panel.left + 15
bottom = panel.bottom - 15
width = panel.width - 30
panel.wEvent_Size do ():
layout()
button.wEvent_Button do ():
insertOnline()
frame.wIdExit do ():
frame.delete()
insertInstalled()
layout()
frame.setMinSize((620,400))
frame.center()
frame.show()
app.mainLoop()
Alles anzeigen
# compile: nim c -d:ssl nimble_up_check_cmd.nim
import os, strutils, re, httpClient, strformat
let params = commandLineParams()
type
Packages = tuple
name: string # name of the package
versions: string # installed versions
verhigh: string # highest version (current)
repo: string # repository url
veronline: string # package-name.nimble url
bupdate: bool # true: newer version online, needs update
# Extract infos about all installed packages
# ------------------------------------------------------------------------------
proc pkgsInstalled(): seq[Packages] =
let tmpfile = os.getHomeDir() & "nimbledump.txt"
# tmpfile maybe exist - delete it
discard execShellCmd("DEL " & tmpfile)
# write installed pkgs into tmpfile
discard execShellCmd("nimble list -i >>" & tmpfile)
let f = tmpfile.open(fmRead)
var
line, name, ver, vhigh: string
smatch: seq[string]
pkgs: seq[Packages]
while f.readLine(line):
smatch = line.findAll(re(r"\w+")) # name
if smatch.len > 0: name = smatch[0]
smatch = line.findAll(re(r"\[.+\]")) # versions
if smatch.len > 0: ver = smatch[0]
smatch = line.findAll(re(r"\d+[\.\d]+\]$"))
if smatch.len > 0:
vhigh = smatch[0] # highest version
vhigh.delete(vhigh.len - 1, vhigh.len)
pkgs.add((name, ver, vhigh, "", "", false))
f.close()
result = pkgs
# ------------------------------------------------------------------------------
# Search for each installed package the repo url,
# read from this repo the *.nimble file and extract the version info
# ------------------------------------------------------------------------------
proc getOnlineVersion(): seq[Packages] =
let
client = newHttpClient()
tmpfile = os.getHomeDir() & "nimbledump.txt"
patt = re(r"version\s+=\s""([^""]+)""", {reIgnoreCase, reMultiLine})
var
pkgs = pkgsInstalled()
smatch: seq[string]
readNimble, rawurl: string
for i in 0..pkgs.len - 1:
discard execShellCmd("DEL " & tmpfile)
discard execShellCmd("nimble search " & pkgs[i].name & " >>" & tmpfile)
smatch = tmpfile.readFile().findAll(re(r"url:\s+\S+" & pkgs[i].name & r"\S*", {reIgnoreCase,reMultiLine}))
if smatch.len > 0:
smatch = smatch[0].findAll(re(r"https://\S+"))
pkgs[i].repo = smatch[0]
# reads "/raw/master/package-name.nimble" and extracts the version number
# maybe "/raw/main/...."
rawurl = pkgs[i].repo & "/raw/master/" & pkgs[i].name & ".nimble"
try:
readNimble = client.getContent(rawurl)
except:
rawurl = pkgs[i].repo & "/raw/main/" & pkgs[i].name & ".nimble"
try:
readNimble = client.getContent(rawurl)
except:
pkgs[i].veronline = "0"
smatch = re.findAll(readNimble, patt)
if smatch.len > 0:
pkgs[i].veronline = (smatch[0])[smatch[0].find('"')+1..smatch[0].len-2]
else: pkgs[i].veronline = "0"
pkgs[i].bupdate = (pkgs[i].veronline > pkgs[i].verhigh)
result = pkgs
# ------------------------------------------------------------------------------
# Get informations about all installed packages and [optional]
# installs newer version, if exists.
# i.e.:
# memlib [OK] current: 1.2.0 online: 1.2.0 installed: [1.2.0]
# minhook [OK] current: 1.0.0 online: 1.0.0 installed: [1.0.0]
#
# All packages are up to date.
# ------------------------------------------------------------------------------
proc outputPkgInfo(bup: bool=false) =
# collect all information
let pkgs = getOnlineVersion()
var needUp, output: string
var cmdUpdate, outputUp: string
for i in 0..pkgs.len - 1:
if pkgs[i].bupdate:
needUp = "[NEW!]"
cmdUpdate &= pkgs[i].name & ","
else:
needUp = "[OK]"
output &= fmt"{pkgs[i].name:<20}{needUp:<8}current:{pkgs[i].verhigh:>8} online:{pkgs[i].veronline:>8} installed: {$pkgs[i].versions}{'\n'}"
if cmdUpdate.len > 0:
outputUp = "Package Update:\n" & cmdUpdate[0..cmdUpdate.len-2] & "\n"
cmdUpdate = "nimble install " & cmdUpdate[0..cmdUpdate.len-2]
else: outputUp = "All packages are up to date."
echo output
if bup:
echo outputUp
if cmdUpdate != "": discard execShellCmd(cmdUpdate) else: discard
else: discard
# ------------------------------------------------------------------------------
# Outputs informations about installed packages, from "nimble list -i", but formatted.
# ------------------------------------------------------------------------------
proc outputLocal() {.discardable.} =
let pkgs = pkgsInstalled()
var output: string
for i in 0..pkgs.len - 1:
output &= fmt"{pkgs[i].name:<20} current:{pkgs[i].verhigh:>8} installed: {$pkgs[i].versions}{'\n'}"
echo output
# ------------------------------------------------------------------------------
if params.len > 0:
for i in 0..params.len - 1:
if params[i] == "help": echo "Available:\n" & "\"list\" Gets a list with local packages.\n\"check\" Gets a list with package informations local and online.\n\"update\" Retrieves the same list and, if newer versions are online: Installs them."
elif params[i] == "list": outputLocal()
elif params[i] == "check": outputPkgInfo()
elif params[i] == "update": outputPkgInfo(true)
else: echo "Wrong parameter! Use \"help\" to see available params."
else:
echo "No Params passed. List all installed packages."
outputPkgInfo()
Alles anzeigen
So schauts dann aus: