-
Notifications
You must be signed in to change notification settings - Fork 2
/
lpm
executable file
·244 lines (215 loc) · 9.67 KB
/
lpm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/usr/bin/env python3
import sys
from pathlib import Path
from argparse import ArgumentParser
from os import makedirs
from shutil import get_terminal_size
from download import HTTPDownload, GITDownload, SVNDownload
from packagemanager import PackageManager
from opm import OnlinePackageManager
from logger import Logger, LogLevel
from project import LazarusProject
from subprocess import call
def performUpdate(opm):
opm.downloadPackageList()
return True
def performFetch(lpm, opm, packages, logger):
result = True
for pkgName in packages:
pkg = opm.packages.get(pkgName)
if pkg is None:
logger.error(f"Package {pkgName} not found... skipping")
result = False
continue
result = result and lpm.fetchFromOPM(pkg)
return result
def performInstall(lpm, opm, packages, logger):
fetchFirst = [p for p in packages if p not in lpm.packages]
result = performFetch(lpm, opm, fetchFirst, logger)
for pkgName in packages:
result = result and lpm.installPackage(pkgName)
return result
def performUpgrade(lpm, opm, packages, logger):
result = True
if len(packages) == 0:
packages = [name for name, _ in lpm.packages.items()]
updateable = [p for p in packages if p in opm.packages]
for p in updateable:
pkg = lpm.packages.get(p)
if pkg is None:
logger.error(f"Package {p} not found... skipping")
result = False
continue
opmPkg = opm.packages[p]
if pkg.date >= opmPkg.file_date:
logger.log(f"{p} is up to date")
continue
logger.log(f"updating {p}")
pkgResult = performFetch(lpm, opm, [p], logger)
if not pkgResult:
result = False
continue
sel = lpm.selected
for i in pkg.installed:
if lpm.selectLazarus(i):
result = result and performInstall(lpm, opm, [p], logger)
else:
result = False
lpm.selectLazarus(sel)
return result
def performSearch(opm, searchstring):
result = opm.searchPackages(searchstring)
nameSize = 0
catSize = 0
for pkg in result:
nameSize = max(nameSize, len(pkg.name))
cats = pkg.categories[:2]
cat = ", ".join(pkg.categories[0:2])
if len(cats) < len(pkg.categories):
cat += ", ..."
catSize = max(catSize, len(cat))
for pkg in result:
namePadding = " "*(nameSize-len(pkg.name))
cats = pkg.categories[:2]
cat = ", ".join(pkg.categories[0:2])
if len(cats) < len(pkg.categories):
cat += ", ..."
catPadding = " "*(catSize-len(cat))
desc = pkg.description.replace("\n", " ")
desc = desc.replace("\r", "")
separator = " | "
wndSize = get_terminal_size((0, 0)).columns
totalLen = nameSize + catSize + len(desc) + 2*len(separator)
totalLenWithouDesc = totalLen - len(desc)
if totalLen > wndSize > 0 and totalLenWithouDesc + 3 < wndSize:
desc = desc[:wndSize-totalLenWithouDesc-3] + "..."
print(f"{pkg.name}{namePadding}{separator}{cat}{catPadding}{separator}{desc}")
return len(result) > 0
def performDirectDownload(lpm, name, url, dltype, branch, packages, logger):
download = None
if dltype == "git":
download = GITDownload(url, branch, logger=logger)
elif dltype == "svn":
download = SVNDownload(url, logger=logger)
elif dltype == "http":
download = HTTPDownload(url, logger=logger)
if download is None:
print(f"download method {dltype} unkown")
return False
return lpm.fetchFromDownloader(name, download, 0, packages)
def handleLazarus(lpm, action, name, path):
if action == "add":
return lpm.addLazarus(name, Path(path).expanduser())
if action == "delete":
return lpm.removeLazarus(name)
if action == "select":
return lpm.selectLazarus(name)
return False
def performBuild(lpm, opm, project, modes, yes, logger):
lazbuild = lpm.getLazbuild()
if lazbuild is None:
return False
project = LazarusProject(Path(project).expanduser())
basePackages = lpm.getLazarusbasePackages()
if basePackages is None:
return False
availableModes = project.getModes()
if len(modes) == 0:
modes = availableModes
dependencies = [f"{d}.lpk" for d in project.getDependencies()]
for dep in dependencies:
dep = dep.lower()
if dep in basePackages:
continue
pkg = lpm.packageByPackage(dep)
toInstall = None
if (pkg is not None) and (lpm.selected not in pkg.installed):
toInstall = pkg.name
elif pkg is None:
opmPkg = opm.packageMap.get(dep)
if opmPkg is None:
logger.error(f"dependency {dep} could not be resolved")
return False
toInstall = opmPkg.name
if toInstall is not None:
if not yes:
print(f"Dependency {dep} is found but not installed, install now?")
inp = input("[Y/n] > ")
if inp.lower() == "n":
logger.error(f"dependency {dep} could not be resolved")
return False
performInstall(lpm, opm, [toInstall], logger)
result = True
for mode in modes:
if mode not in availableModes:
logger.error(f"Buildmode {mode} requested but not available for project")
result = False
continue
result = result and project.build(lazbuild, mode)
return result
def performSelfUpdate():
git_dir = Path(__file__).resolve().parent
return call(["git", "pull"], cwd=git_dir) == 0
def main():
parser = ArgumentParser(description="online package manager CLI")
parser.add_argument("--target", type=str, help="target directory for the package list and downloaded packages (default=~/.lpm)", default="~/.lpm")
parser.add_argument("--quiet", "-q", action="store_true", required=False, help="only output errors", default=False)
sp = parser.add_subparsers(dest="mainaction", required=True)
updateArg = sp.add_parser("update", help="updates package list from server")
upgradeArg = sp.add_parser("upgrade", help="update packages from server")
upgradeArg.add_argument("packages", type=str, nargs="*", help="packages to upgrade, if none are given all are updated")
fetchArg = sp.add_parser("fetch", help="download newest version of a package")
fetchArg.add_argument("packages", type=str, help="packages to download", nargs="+")
installArg = sp.add_parser("install", help="installs the package to a lazarus installation")
installArg.add_argument("packages", type=str, help="packages to install", nargs="+")
searchArg = sp.add_parser("search", help="search for packages")
searchArg.add_argument("searchstring", type=str, help="the string to search for")
rawArg = sp.add_parser("direct-download", help="download a package not using OPM")
rawArg.add_argument("--type", "-t", type=str, choices=["http", "git", "svn"], help="downloading method. Default=http", default="http")
rawArg.add_argument("--branch", "-b", type=str, help="branch to checkout (git only). Default=master", default="master")
rawArg.add_argument("name", type=str, help="the name under which this package will be registered")
rawArg.add_argument("url", type=str, help="the download url of the file")
rawArg.add_argument("packages", type=str, nargs="*", help="list of lpk files in that file, if none are given a file search for *.lpk will be done")
lazArg = sp.add_parser("lazarus", help="configure lazarus installations")
lazArg.add_argument("action", type=str, choices=["add", "delete", "select"], help="action to perform")
lazArg.add_argument("name", type=str, help="name of the lazarus installation (for references)")
lazArg.add_argument("path", nargs="?", type=str, help="path of the lazarus installation")
buildArg = sp.add_parser("build", help="buidling lazarus projects")
buildArg.add_argument("--yes", "-y", action="store_true", default=False, required=False, help="answer all yes-no questions with yes")
buildArg.add_argument("project", type=str, help="lpi file to build")
buildArg.add_argument("modes", type=str, nargs="*", help="the build modes to build, if left out, all are build")
selfUpdateArg = sp.add_parser("self-update", help="Update lpm via git")
args = parser.parse_args()
quiet = args.quiet
target = Path(args.target).expanduser()
makedirs(target, exist_ok=True)
logger = Logger(LogLevel.WARNING if quiet else LogLevel.DEBUG)
opm = OnlinePackageManager(target, logger)
opm.loadPackageList()
lpm = PackageManager(target, logger)
lpm.load()
action = args.mainaction
success = False
if action == "update":
success = performUpdate(opm)
elif action == "upgrade":
success = performUpgrade(lpm, opm, args.packages, logger)
elif action == "fetch":
success = performFetch(lpm, opm, args.packages, logger)
elif action == "install":
success = performInstall(lpm, opm, args.packages, logger)
elif action == "search":
success = performSearch(opm, args.searchstring)
elif action == "direct-download":
success = performDirectDownload(lpm, args.name, args.url, args.type, args.branch, args.packages, logger)
elif action == "lazarus":
success = handleLazarus(lpm, args.action, args.name, args.path)
elif action == "build":
success = performBuild(lpm, opm, args.project, args.modes, args.yes, logger)
elif action == "self-update":
success = performSelfUpdate()
lpm.save()
if not success:
sys.exit(1)
if __name__=="__main__":
main()