]> git.ipfire.org Git - people/ms/pakfire.git/blame - pakfire/cli.py
Merge branch 'master' of git://git.ipfire.org/oddments/pakfire into server
[people/ms/pakfire.git] / pakfire / cli.py
CommitLineData
47a4cb89
MT
1#!/usr/bin/python
2
3import argparse
4import sys
5
6import packages
fa6d335b 7import repository
677ff42a 8import server
e9c20259 9import util
47a4cb89
MT
10
11from pakfire import Pakfire
12
13from constants import *
14from i18n import _
15
16def ask_user(question):
17 """
18 Ask the user the question, he or she can answer with yes or no.
19
20 This function returns True for "yes" and False for "no".
21
22 If the software is running in a non-inteactive shell, no question
23 is asked at all and the answer is always "yes".
24 """
e9c20259 25 if not util.cli_is_interactive():
47a4cb89
MT
26 return True
27
28 print _("%s [y/N]") % question,
29 ret = raw_input()
30
ced5e511 31 return ret in ("y", "Y", "z", "Z", "j", "J")
47a4cb89
MT
32
33class Cli(object):
47a4cb89
MT
34 def __init__(self):
35 self.parser = argparse.ArgumentParser(
36 description = _("Pakfire command line interface."),
37 )
38
39 self.parse_common_arguments()
40
41 self.parser.add_argument("--instroot", metavar="PATH",
d2e26956 42 default="/",
47a4cb89
MT
43 help=_("The path where pakfire should operate in."))
44
45 # Add sub-commands.
46 self.sub_commands = self.parser.add_subparsers()
47
48 self.parse_command_install()
5e87fa4f 49 self.parse_command_localinstall()
47a4cb89
MT
50 self.parse_command_info()
51 self.parse_command_search()
52 self.parse_command_update()
fa6d335b 53 self.parse_command_provides()
b0bcdb49 54 self.parse_command_requires()
c1962d40 55 self.parse_command_grouplist()
ce2764c1 56 self.parse_command_groupinstall()
67bc4528 57 self.parse_command_repolist()
47a4cb89
MT
58
59 # Finally parse all arguments from the command line and save them.
60 self.args = self.parser.parse_args()
61
62 # Create instance of the wonderful pakfire :)
63 self.pakfire = Pakfire(
64 self.args.instroot,
65 configs = [self.args.config],
f781b1ab 66 disable_repos = self.args.disable_repo,
47a4cb89
MT
67 )
68
69 self.action2func = {
5e87fa4f
MT
70 "install" : self.handle_install,
71 "localinstall" : self.handle_localinstall,
72 "update" : self.handle_update,
73 "info" : self.handle_info,
74 "search" : self.handle_search,
fa6d335b 75 "provides" : self.handle_provides,
b0bcdb49 76 "requires" : self.handle_requires,
c1962d40 77 "grouplist" : self.handle_grouplist,
ce2764c1 78 "groupinstall" : self.handle_groupinstall,
67bc4528 79 "repolist" : self.handle_repolist,
47a4cb89
MT
80 }
81
82 def parse_common_arguments(self):
83 self.parser.add_argument("-v", "--verbose", action="store_true",
84 help=_("Enable verbose output."))
85
86 self.parser.add_argument("-c", "--config", nargs="?",
87 help=_("Path to a configuration file to load."))
88
f781b1ab
MT
89 self.parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
90 help=_("Disable a repository temporarily."))
91
47a4cb89
MT
92 def parse_command_install(self):
93 # Implement the "install" command.
94 sub_install = self.sub_commands.add_parser("install",
95 help=_("Install one or more packages to the system."))
96 sub_install.add_argument("package", nargs="+",
97 help=_("Give name of at least one package to install."))
98 sub_install.add_argument("action", action="store_const", const="install")
99
5e87fa4f
MT
100 def parse_command_localinstall(self):
101 # Implement the "localinstall" command.
102 sub_install = self.sub_commands.add_parser("localinstall",
103 help=_("Install one or more packages from the filesystem."))
104 sub_install.add_argument("package", nargs="+",
105 help=_("Give filename of at least one package."))
106 sub_install.add_argument("action", action="store_const", const="localinstall")
107
47a4cb89
MT
108 def parse_command_update(self):
109 # Implement the "update" command.
110 sub_update = self.sub_commands.add_parser("update",
111 help=_("Update the whole system or one specific package."))
112 sub_update.add_argument("package", nargs="*",
113 help=_("Give a name of a package to update or leave emtpy for all."))
114 sub_update.add_argument("action", action="store_const", const="update")
115
116 def parse_command_info(self):
117 # Implement the "info" command.
118 sub_info = self.sub_commands.add_parser("info",
119 help=_("Print some information about the given package(s)."))
120 sub_info.add_argument("package", nargs="+",
121 help=_("Give at least the name of one package."))
122 sub_info.add_argument("action", action="store_const", const="info")
123
124 def parse_command_search(self):
125 # Implement the "search" command.
126 sub_search = self.sub_commands.add_parser("search",
127 help=_("Search for a given pattern."))
128 sub_search.add_argument("pattern",
129 help=_("A pattern to search for."))
130 sub_search.add_argument("action", action="store_const", const="search")
131
fa6d335b
MT
132 def parse_command_provides(self):
133 # Implement the "provides" command
134 sub_provides = self.sub_commands.add_parser("provides",
135 help=_("Get a list of packages that provide a given file or feature."))
136 sub_provides.add_argument("pattern", nargs="+",
137 help=_("File or feature to search for."))
138 sub_provides.add_argument("action", action="store_const", const="provides")
139
b0bcdb49
MT
140 def parse_command_requires(self):
141 # Implement the "requires" command
142 sub_requires = self.sub_commands.add_parser("requires",
143 help=_("Get a list of packages that require a given file or feature."))
144 sub_requires.add_argument("pattern", nargs="+",
145 help=_("File or feature to search for."))
146 sub_requires.add_argument("action", action="store_const", const="requires")
147
c1962d40
MT
148 def parse_command_grouplist(self):
149 # Implement the "grouplist" command
150 sub_grouplist = self.sub_commands.add_parser("grouplist",
151 help=_("Get list of packages that belong to the given group."))
152 sub_grouplist.add_argument("group", nargs=1,
153 help=_("Group name to search for."))
154 sub_grouplist.add_argument("action", action="store_const", const="grouplist")
155
ce2764c1
MT
156 def parse_command_groupinstall(self):
157 # Implement the "grouplist" command
158 sub_groupinstall = self.sub_commands.add_parser("groupinstall",
159 help=_("Install all packages that belong to the given group."))
160 sub_groupinstall.add_argument("group", nargs=1,
161 help=_("Group name."))
162 sub_groupinstall.add_argument("action", action="store_const", const="groupinstall")
163
67bc4528
MT
164 def parse_command_repolist(self):
165 # Implement the "repolist" command
166 sub_repolist = self.sub_commands.add_parser("repolist",
167 help=_("List all currently enabled repositories."))
168 sub_repolist.add_argument("action", action="store_const", const="repolist")
ce2764c1 169
47a4cb89
MT
170 def run(self):
171 action = self.args.action
172
173 if not self.action2func.has_key(action):
174 raise
175
176 try:
177 func = self.action2func[action]
178 except KeyError:
179 raise # XXX catch and return better error message
180
181 return func()
182
9afa5620 183 def handle_info(self, long=False):
47a4cb89
MT
184 for pattern in self.args.package:
185 pkgs = self.pakfire.repos.get_by_glob(pattern)
186
187 pkgs = packages.PackageListing(pkgs)
188
189 for pkg in pkgs:
9afa5620 190 print pkg.dump(long=long)
47a4cb89
MT
191
192 def handle_search(self):
193 pkgs = self.pakfire.repos.search(self.args.pattern)
194
195 pkgs = packages.PackageListing(pkgs)
196
197 for pkg in pkgs:
198 print pkg.dump(short=True)
199
200 def handle_update(self):
a412c989 201 self.pakfire.update(self.args.package)
47a4cb89 202
5e87fa4f
MT
203 def handle_install(self, local=False):
204 if local:
205 repo = repository.FileSystemRepository(self.pakfire)
206
207 pkgs = []
208 for pkg in self.args.package:
209 if local and os.path.exists(pkg):
210 pkg = packages.BinaryPackage(self.pakfire, repo, pkg)
211
212 pkgs.append(pkg)
213
214 self.pakfire.install(pkgs)
215
216 def handle_localinstall(self):
217 return self.handle_install(local=True)
218
fa6d335b
MT
219 def handle_provides(self):
220 pkgs = self.pakfire.provides(self.args.pattern)
221
222 for pkg in pkgs:
223 print pkg.dump()
224
b0bcdb49
MT
225 def handle_requires(self):
226 pkgs = self.pakfire.requires(self.args.pattern)
227
228 for pkg in pkgs:
229 print pkg.dump()
230
c1962d40
MT
231 def handle_grouplist(self):
232 pkgs = self.pakfire.grouplist(self.args.group[0])
233
234 for pkg in pkgs:
235 print " * %s" % pkg
236
ce2764c1
MT
237 def handle_groupinstall(self):
238 self.pakfire.groupinstall(self.args.group[0])
239
67bc4528
MT
240 def handle_repolist(self):
241 repos = self.pakfire.repolist()
242 repos.sort()
243
244 FORMAT = " %-20s %8s %12s "
245
246 title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"))
247 print title
248 print "=" * len(title) # spacing line
249
250 for repo in repos:
251 # Skip the installed repository.
252 if repo.name == "installed":
253 continue
254
255 print FORMAT % (repo.name, repo.enabled, repo.priority)
256
47a4cb89
MT
257
258class CliBuilder(Cli):
259 def __init__(self):
260 self.parser = argparse.ArgumentParser(
261 description = _("Pakfire builder command line interface."),
262 )
263
264 self.parse_common_arguments()
265
266 # Add sub-commands.
267 self.sub_commands = self.parser.add_subparsers()
268
269 self.parse_command_build()
270 self.parse_command_dist()
271 self.parse_command_info()
272 self.parse_command_search()
273 self.parse_command_shell()
274 self.parse_command_update()
4fbd4216 275 self.parse_command_provides()
b0bcdb49 276 self.parse_command_requires()
2c84aceb 277 self.parse_command_grouplist()
67bc4528 278 self.parse_command_repolist()
47a4cb89
MT
279
280 # Finally parse all arguments from the command line and save them.
281 self.args = self.parser.parse_args()
282
283 self.pakfire = Pakfire(
284 builder = True,
285 configs = [self.args.config],
f781b1ab 286 disable_repos = self.args.disable_repo,
47a4cb89
MT
287 )
288
289 self.action2func = {
fa6d335b
MT
290 "build" : self.handle_build,
291 "dist" : self.handle_dist,
292 "update" : self.handle_update,
293 "info" : self.handle_info,
294 "search" : self.handle_search,
295 "shell" : self.handle_shell,
4fbd4216 296 "provides" : self.handle_provides,
b0bcdb49 297 "requires" : self.handle_requires,
2c84aceb 298 "grouplist" : self.handle_grouplist,
67bc4528 299 "repolist" : self.handle_repolist,
47a4cb89
MT
300 }
301
302 def parse_command_update(self):
303 # Implement the "update" command.
304 sub_update = self.sub_commands.add_parser("update",
305 help=_("Update the package indexes."))
306 sub_update.add_argument("action", action="store_const", const="update")
307
308 def parse_command_build(self):
309 # Implement the "build" command.
310 sub_build = self.sub_commands.add_parser("build",
311 help=_("Build one or more packages."))
312 sub_build.add_argument("package", nargs=1,
313 help=_("Give name of at least one package to build."))
314 sub_build.add_argument("action", action="store_const", const="build")
315
316 sub_build.add_argument("-a", "--arch",
317 help=_("Build the package for the given architecture."))
318 sub_build.add_argument("--resultdir", nargs="?",
319 help=_("Path were the output files should be copied to."))
320
321 def parse_command_shell(self):
322 # Implement the "shell" command.
323 sub_shell = self.sub_commands.add_parser("shell",
324 help=_("Go into a shell."))
042266f3 325 sub_shell.add_argument("package", nargs="?",
47a4cb89
MT
326 help=_("Give name of a package."))
327 sub_shell.add_argument("action", action="store_const", const="shell")
328
329 sub_shell.add_argument("-a", "--arch",
330 help=_("Emulated architecture in the shell."))
331
332 def parse_command_dist(self):
333 # Implement the "dist" command.
334 sub_dist = self.sub_commands.add_parser("dist",
335 help=_("Generate a source package."))
e412b8dc
MT
336 sub_dist.add_argument("package", nargs="+",
337 help=_("Give name(s) of a package(s)."))
47a4cb89
MT
338 sub_dist.add_argument("action", action="store_const", const="dist")
339
340 sub_dist.add_argument("--resultdir", nargs="?",
341 help=_("Path were the output files should be copied to."))
342
9afa5620
MT
343 def handle_info(self):
344 Cli.handle_info(self, long=True)
345
47a4cb89 346 def handle_build(self):
47a4cb89
MT
347 # Get the package descriptor from the command line options
348 pkg = self.args.package[0]
349
350 # Check, if we got a regular file
351 if os.path.exists(pkg):
352 pkg = os.path.abspath(pkg)
353
354 if pkg.endswith(MAKEFILE_EXTENSION):
3723913b 355 pkg = packages.Makefile(self.pakfire, pkg)
47a4cb89
MT
356
357 elif pkg.endswith(PACKAGE_EXTENSION):
3723913b
MT
358 repo = repository.FileSystemRepository(self.pakfire)
359 pkg = packages.SourcePackage(self.pakfire, repo, pkg)
47a4cb89
MT
360
361 else:
362 # XXX walk through the source tree and find a matching makefile
363 pass
364
0ec833c6 365 self.pakfire.build(pkg, arch=self.args.arch, resultdirs=[self.args.resultdir,])
47a4cb89
MT
366
367 def handle_shell(self):
042266f3
MT
368 pkg = None
369
47a4cb89 370 # Get the package descriptor from the command line options
042266f3 371 if self.args.package:
ad1b844f 372 pkg = self.args.package
47a4cb89
MT
373
374 # Check, if we got a regular file
042266f3 375 if pkg and os.path.exists(pkg):
47a4cb89
MT
376 pkg = os.path.abspath(pkg)
377
378 if pkg.endswith(MAKEFILE_EXTENSION):
3723913b 379 pkg = packages.Makefile(self.pakfire, pkg)
47a4cb89
MT
380
381 elif pkg.endswith(PACKAGE_EXTENSION):
3723913b
MT
382 repo = repository.FileSystemRepository(self.pakfire)
383 pkg = packages.SourcePackage(self.pakfire, repo, pkg)
47a4cb89
MT
384
385 else:
386 # XXX walk through the source tree and find a matching makefile
387 pass
388
389 self.pakfire.shell(pkg, arch=self.args.arch)
390
391 def handle_dist(self):
e412b8dc
MT
392 # Get the packages from the command line options
393 pkgs = []
47a4cb89 394
e412b8dc
MT
395 for pkg in self.args.package:
396 # Check, if we got a regular file
397 if os.path.exists(pkg):
398 pkg = os.path.abspath(pkg)
47a4cb89 399
e412b8dc
MT
400 if pkg.endswith(MAKEFILE_EXTENSION):
401 pkg = packages.Makefile(self.pakfire, pkg)
402 pkgs.append(pkg)
47a4cb89 403
e412b8dc
MT
404 else:
405 # XXX walk through the source tree and find a matching makefile
406 pass
47a4cb89 407
e412b8dc 408 self.pakfire.dist(pkgs, resultdirs=[self.args.resultdir,])
47a4cb89 409
9613a111 410class CliRepo(Cli):
92806f47
MT
411 def __init__(self):
412 self.parser = argparse.ArgumentParser(
9613a111 413 description = _("Pakfire repo command line interface."),
92806f47
MT
414 )
415
416 self.parse_common_arguments()
417
418 # Add sub-commands.
419 self.sub_commands = self.parser.add_subparsers()
420
421 self.parse_command_repo()
422
423 # Finally parse all arguments from the command line and save them.
424 self.args = self.parser.parse_args()
425
426 self.pakfire = Pakfire(
427 builder = True,
428 configs = [self.args.config],
429 disable_repos = self.args.disable_repo,
430 )
431
432 self.action2func = {
433 "repo_create" : self.handle_repo_create,
434 }
435
436 def parse_command_repo(self):
437 sub_repo = self.sub_commands.add_parser("repo",
438 help=_("Repository management commands."))
439
440 sub_repo_commands = sub_repo.add_subparsers()
441
442 self.parse_command_repo_create(sub_repo_commands)
443
444 def parse_command_repo_create(self, sub_commands):
445 sub_create = sub_commands.add_parser("create",
446 help=_("Create a new repository index."))
447 sub_create.add_argument("path", nargs=1, help=_("Path to the packages."))
448 sub_create.add_argument("inputs", nargs="+", help=_("Path to input packages."))
449 sub_create.add_argument("action", action="store_const", const="repo_create")
450
fa6d335b
MT
451 def handle_repo_create(self):
452 path = self.args.path[0]
453
66af936c 454 self.pakfire.repo_create(path, self.args.inputs)
9613a111
MT
455
456
457class CliMaster(Cli):
677ff42a
MT
458 def __init__(self):
459 self.parser = argparse.ArgumentParser(
460 description = _("Pakfire master command line interface."),
461 )
462
463 self.parse_common_arguments()
464
465 # Add sub-commands.
466 self.sub_commands = self.parser.add_subparsers()
467
468 self.parse_command_update()
469
470 # Finally parse all arguments from the command line and save them.
471 self.args = self.parser.parse_args()
472
473 self.pakfire = Pakfire(
474 builder = True,
475 configs = [self.args.config],
476 disable_repos = self.args.disable_repo,
477 )
478
479 self.master = server.master.Master(self.pakfire)
480
481 self.action2func = {
482 "update" : self.handle_update,
483 }
484
485 def parse_command_update(self):
486 # Implement the "update" command.
487 sub_update = self.sub_commands.add_parser("update",
488 help=_("Update the sources."))
489 sub_update.add_argument("action", action="store_const", const="update")
490
491 def handle_update(self):
492 self.master.update_sources()
9613a111
MT
493
494
495class CliSlave(Cli):
677ff42a
MT
496 def __init__(self):
497 self.parser = argparse.ArgumentParser(
498 description = _("Pakfire slave command line interface."),
499 )
500
501 self.parse_common_arguments()
502
503 # Add sub-commands.
504 self.sub_commands = self.parser.add_subparsers()
505
a52f536c 506 self.parse_command_build()
677ff42a
MT
507 self.parse_command_keepalive()
508
509 # Finally parse all arguments from the command line and save them.
510 self.args = self.parser.parse_args()
511
512 self.pakfire = Pakfire(
513 builder = True,
514 configs = [self.args.config],
515 disable_repos = self.args.disable_repo,
516 )
517
518 self.slave = server.slave.Slave(self.pakfire)
519
520 self.action2func = {
a52f536c 521 "build" : self.handle_build,
677ff42a
MT
522 "keepalive" : self.handle_keepalive,
523 }
524
a52f536c
MT
525 def parse_command_build(self):
526 # Implement the "build" command.
527 sub_keepalive = self.sub_commands.add_parser("build",
528 help=_("Request a build job from the server."))
529 sub_keepalive.add_argument("action", action="store_const", const="build")
530
677ff42a
MT
531 def parse_command_keepalive(self):
532 # Implement the "keepalive" command.
533 sub_keepalive = self.sub_commands.add_parser("keepalive",
534 help=_("Send a keepalive to the server."))
535 sub_keepalive.add_argument("action", action="store_const",
536 const="keepalive")
537
538 def handle_keepalive(self):
539 self.slave.keepalive()
9613a111 540
a52f536c
MT
541 def handle_build(self):
542 self.slave.build_job()