]> git.ipfire.org Git - people/stevee/pakfire.git/blame - pakfire/cli.py
Fix typo in README.
[people/stevee/pakfire.git] / pakfire / cli.py
CommitLineData
47a4cb89 1#!/usr/bin/python
b792d887
MT
2###############################################################################
3# #
4# Pakfire - The IPFire package management system #
5# Copyright (C) 2011 Pakfire development team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
47a4cb89
MT
21
22import argparse
23import sys
24
60845a36 25import logger
47a4cb89 26import packages
fa6d335b 27import repository
677ff42a 28import server
e9c20259 29import util
47a4cb89 30
18edfe75 31import pakfire.api as pakfire
47a4cb89
MT
32from constants import *
33from i18n import _
34
60845a36
MT
35# Initialize a very simple logging that is removed when a Pakfire instance
36# is started.
37logger.setup_logging()
38
47a4cb89 39class Cli(object):
47a4cb89
MT
40 def __init__(self):
41 self.parser = argparse.ArgumentParser(
42 description = _("Pakfire command line interface."),
43 )
44
45 self.parse_common_arguments()
46
2ba449f0 47 self.parser.add_argument("--root", metavar="PATH",
d2e26956 48 default="/",
47a4cb89
MT
49 help=_("The path where pakfire should operate in."))
50
51 # Add sub-commands.
52 self.sub_commands = self.parser.add_subparsers()
53
54 self.parse_command_install()
5e87fa4f 55 self.parse_command_localinstall()
a39fd08b 56 self.parse_command_remove()
47a4cb89
MT
57 self.parse_command_info()
58 self.parse_command_search()
59 self.parse_command_update()
fa6d335b 60 self.parse_command_provides()
c1962d40 61 self.parse_command_grouplist()
ce2764c1 62 self.parse_command_groupinstall()
67bc4528 63 self.parse_command_repolist()
31267a64 64 self.parse_command_clean()
35d89fd7 65 self.parse_command_check()
47a4cb89
MT
66
67 # Finally parse all arguments from the command line and save them.
68 self.args = self.parser.parse_args()
69
47a4cb89 70 self.action2func = {
5e87fa4f
MT
71 "install" : self.handle_install,
72 "localinstall" : self.handle_localinstall,
a39fd08b 73 "remove" : self.handle_remove,
5e87fa4f
MT
74 "update" : self.handle_update,
75 "info" : self.handle_info,
76 "search" : self.handle_search,
fa6d335b 77 "provides" : self.handle_provides,
c1962d40 78 "grouplist" : self.handle_grouplist,
ce2764c1 79 "groupinstall" : self.handle_groupinstall,
67bc4528 80 "repolist" : self.handle_repolist,
31267a64 81 "clean_all" : self.handle_clean_all,
35d89fd7 82 "check" : self.handle_check,
47a4cb89
MT
83 }
84
7c8f2953
MT
85 @property
86 def pakfire_args(self):
6557ff4c
MT
87 ret = { "mode" : "normal" }
88
2ba449f0
MT
89 if hasattr(self.args, "root"):
90 ret["path"] = self.args.root
f9a012a8
MT
91
92 if hasattr(self.args, "disable_repo"):
93 ret["disable_repos"] = self.args.disable_repo
94
95 if hasattr(self.args, "enable_repo"):
96 ret["enable_repos"] = self.args.enable_repo
97
6a509182
MT
98 if hasattr(self.args, "offline"):
99 ret["offline"] = self.args.offline
100
f9a012a8 101 return ret
7c8f2953 102
47a4cb89
MT
103 def parse_common_arguments(self):
104 self.parser.add_argument("-v", "--verbose", action="store_true",
105 help=_("Enable verbose output."))
106
107 self.parser.add_argument("-c", "--config", nargs="?",
108 help=_("Path to a configuration file to load."))
109
f781b1ab
MT
110 self.parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
111 help=_("Disable a repository temporarily."))
112
f9a012a8
MT
113 self.parser.add_argument("--enabled-repo", nargs="*", metavar="REPO",
114 help=_("Enable a repository temporarily."))
115
6a509182
MT
116 self.parser.add_argument("--offline", action="store_true",
117 help=_("Run pakfire in offline mode."))
118
47a4cb89
MT
119 def parse_command_install(self):
120 # Implement the "install" command.
121 sub_install = self.sub_commands.add_parser("install",
122 help=_("Install one or more packages to the system."))
123 sub_install.add_argument("package", nargs="+",
124 help=_("Give name of at least one package to install."))
125 sub_install.add_argument("action", action="store_const", const="install")
126
5e87fa4f
MT
127 def parse_command_localinstall(self):
128 # Implement the "localinstall" command.
129 sub_install = self.sub_commands.add_parser("localinstall",
130 help=_("Install one or more packages from the filesystem."))
131 sub_install.add_argument("package", nargs="+",
132 help=_("Give filename of at least one package."))
133 sub_install.add_argument("action", action="store_const", const="localinstall")
134
a39fd08b
MT
135 def parse_command_remove(self):
136 # Implement the "remove" command.
137 sub_remove = self.sub_commands.add_parser("remove",
138 help=_("Remove one or more packages from the system."))
139 sub_remove.add_argument("package", nargs="+",
140 help=_("Give name of at least one package to remove."))
141 sub_remove.add_argument("action", action="store_const", const="remove")
142
47a4cb89
MT
143 def parse_command_update(self):
144 # Implement the "update" command.
145 sub_update = self.sub_commands.add_parser("update",
146 help=_("Update the whole system or one specific package."))
147 sub_update.add_argument("package", nargs="*",
148 help=_("Give a name of a package to update or leave emtpy for all."))
149 sub_update.add_argument("action", action="store_const", const="update")
150
151 def parse_command_info(self):
152 # Implement the "info" command.
153 sub_info = self.sub_commands.add_parser("info",
154 help=_("Print some information about the given package(s)."))
155 sub_info.add_argument("package", nargs="+",
156 help=_("Give at least the name of one package."))
157 sub_info.add_argument("action", action="store_const", const="info")
158
159 def parse_command_search(self):
160 # Implement the "search" command.
161 sub_search = self.sub_commands.add_parser("search",
162 help=_("Search for a given pattern."))
163 sub_search.add_argument("pattern",
164 help=_("A pattern to search for."))
165 sub_search.add_argument("action", action="store_const", const="search")
166
fa6d335b
MT
167 def parse_command_provides(self):
168 # Implement the "provides" command
169 sub_provides = self.sub_commands.add_parser("provides",
170 help=_("Get a list of packages that provide a given file or feature."))
171 sub_provides.add_argument("pattern", nargs="+",
172 help=_("File or feature to search for."))
173 sub_provides.add_argument("action", action="store_const", const="provides")
174
c1962d40
MT
175 def parse_command_grouplist(self):
176 # Implement the "grouplist" command
177 sub_grouplist = self.sub_commands.add_parser("grouplist",
178 help=_("Get list of packages that belong to the given group."))
179 sub_grouplist.add_argument("group", nargs=1,
180 help=_("Group name to search for."))
181 sub_grouplist.add_argument("action", action="store_const", const="grouplist")
182
ce2764c1
MT
183 def parse_command_groupinstall(self):
184 # Implement the "grouplist" command
185 sub_groupinstall = self.sub_commands.add_parser("groupinstall",
186 help=_("Install all packages that belong to the given group."))
187 sub_groupinstall.add_argument("group", nargs=1,
188 help=_("Group name."))
189 sub_groupinstall.add_argument("action", action="store_const", const="groupinstall")
190
67bc4528
MT
191 def parse_command_repolist(self):
192 # Implement the "repolist" command
193 sub_repolist = self.sub_commands.add_parser("repolist",
194 help=_("List all currently enabled repositories."))
195 sub_repolist.add_argument("action", action="store_const", const="repolist")
ce2764c1 196
31267a64
MT
197 def parse_command_clean(self):
198 sub_clean = self.sub_commands.add_parser("clean", help=_("Cleanup commands."))
199
200 sub_clean_commands = sub_clean.add_subparsers()
201
202 self.parse_command_clean_all(sub_clean_commands)
203
204 def parse_command_clean_all(self, sub_commands):
205 sub_create = sub_commands.add_parser("all",
206 help=_("Cleanup all temporary files."))
207 sub_create.add_argument("action", action="store_const", const="clean_all")
208
35d89fd7
MT
209 def parse_command_check(self):
210 # Implement the "check" command
211 sub_check = self.sub_commands.add_parser("check",
212 help=_("Check the system for any errors."))
213 sub_check.add_argument("action", action="store_const", const="check")
214
47a4cb89
MT
215 def run(self):
216 action = self.args.action
217
218 if not self.action2func.has_key(action):
219 raise
220
221 try:
222 func = self.action2func[action]
223 except KeyError:
224 raise # XXX catch and return better error message
225
226 return func()
227
9afa5620 228 def handle_info(self, long=False):
7c8f2953 229 pkgs = pakfire.info(self.args.package, **self.pakfire_args)
47a4cb89 230
7c8f2953
MT
231 for pkg in pkgs:
232 print pkg.dump(long=long)
47a4cb89
MT
233
234 def handle_search(self):
7c8f2953 235 pkgs = pakfire.search(self.args.pattern, **self.pakfire_args)
47a4cb89
MT
236
237 for pkg in pkgs:
238 print pkg.dump(short=True)
239
240 def handle_update(self):
7c8f2953 241 pakfire.update(self.args.package, **self.pakfire_args)
47a4cb89 242
e0b99370
MT
243 def handle_install(self):
244 pakfire.install(self.args.package, **self.pakfire_args)
5e87fa4f
MT
245
246 def handle_localinstall(self):
e0b99370 247 pakfire.localinstall(self.args.package, **self.pakfire_args)
5e87fa4f 248
a39fd08b
MT
249 def handle_remove(self):
250 pakfire.remove(self.args.package, **self.pakfire_args)
251
fa6d335b 252 def handle_provides(self):
7c8f2953 253 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
fa6d335b
MT
254
255 for pkg in pkgs:
256 print pkg.dump()
257
c1962d40 258 def handle_grouplist(self):
7c8f2953 259 pkgs = pakfire.grouplist(self.args.group[0], **self.pakfire_args)
c1962d40
MT
260
261 for pkg in pkgs:
262 print " * %s" % pkg
263
ce2764c1 264 def handle_groupinstall(self):
7c8f2953 265 pakfire.groupinstall(self.args.group[0], **self.pakfire_args)
ce2764c1 266
67bc4528 267 def handle_repolist(self):
7c8f2953 268 repos = pakfire.repo_list(**self.pakfire_args)
67bc4528 269
c605d735 270 FORMAT = " %-20s %8s %12s %12s "
67bc4528 271
c605d735 272 title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
67bc4528
MT
273 print title
274 print "=" * len(title) # spacing line
275
276 for repo in repos:
277 # Skip the installed repository.
278 if repo.name == "installed":
279 continue
280
c605d735 281 print FORMAT % (repo.name, repo.enabled, repo.priority, len(repo))
67bc4528 282
31267a64
MT
283 def handle_clean_all(self):
284 print _("Cleaning up everything...")
285
286 pakfire.clean_all(**self.pakfire_args)
287
35d89fd7
MT
288 def handle_check(self):
289 pakfire.check(**self.pakfire_args)
290
47a4cb89
MT
291
292class CliBuilder(Cli):
293 def __init__(self):
294 self.parser = argparse.ArgumentParser(
295 description = _("Pakfire builder command line interface."),
296 )
297
298 self.parse_common_arguments()
299
300 # Add sub-commands.
301 self.sub_commands = self.parser.add_subparsers()
302
303 self.parse_command_build()
304 self.parse_command_dist()
305 self.parse_command_info()
306 self.parse_command_search()
307 self.parse_command_shell()
308 self.parse_command_update()
4fbd4216 309 self.parse_command_provides()
2c84aceb 310 self.parse_command_grouplist()
67bc4528 311 self.parse_command_repolist()
31267a64 312 self.parse_command_clean()
47a4cb89
MT
313
314 # Finally parse all arguments from the command line and save them.
315 self.args = self.parser.parse_args()
316
47a4cb89 317 self.action2func = {
fa6d335b
MT
318 "build" : self.handle_build,
319 "dist" : self.handle_dist,
320 "update" : self.handle_update,
321 "info" : self.handle_info,
322 "search" : self.handle_search,
323 "shell" : self.handle_shell,
4fbd4216 324 "provides" : self.handle_provides,
2c84aceb 325 "grouplist" : self.handle_grouplist,
67bc4528 326 "repolist" : self.handle_repolist,
31267a64 327 "clean_all" : self.handle_clean_all,
47a4cb89
MT
328 }
329
7c8f2953
MT
330 @property
331 def pakfire_args(self):
6557ff4c 332 ret = { "mode" : "builder" }
f9a012a8
MT
333
334 if hasattr(self.args, "disable_repo"):
335 ret["disable_repos"] = self.args.disable_repo
336
337 if hasattr(self.args, "enable_repo"):
338 ret["enable_repos"] = self.args.enable_repo
339
6a509182
MT
340 if hasattr(self.args, "offline"):
341 ret["offline"] = self.args.offline
342
f9a012a8 343 return ret
7c8f2953 344
47a4cb89
MT
345 def parse_command_update(self):
346 # Implement the "update" command.
347 sub_update = self.sub_commands.add_parser("update",
348 help=_("Update the package indexes."))
349 sub_update.add_argument("action", action="store_const", const="update")
350
351 def parse_command_build(self):
352 # Implement the "build" command.
353 sub_build = self.sub_commands.add_parser("build",
354 help=_("Build one or more packages."))
355 sub_build.add_argument("package", nargs=1,
356 help=_("Give name of at least one package to build."))
357 sub_build.add_argument("action", action="store_const", const="build")
358
359 sub_build.add_argument("-a", "--arch",
360 help=_("Build the package for the given architecture."))
361 sub_build.add_argument("--resultdir", nargs="?",
362 help=_("Path were the output files should be copied to."))
f22069bb
MT
363 sub_build.add_argument("-m", "--mode", nargs="?", default="development",
364 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
47a4cb89
MT
365
366 def parse_command_shell(self):
367 # Implement the "shell" command.
368 sub_shell = self.sub_commands.add_parser("shell",
369 help=_("Go into a shell."))
042266f3 370 sub_shell.add_argument("package", nargs="?",
47a4cb89
MT
371 help=_("Give name of a package."))
372 sub_shell.add_argument("action", action="store_const", const="shell")
373
374 sub_shell.add_argument("-a", "--arch",
375 help=_("Emulated architecture in the shell."))
6ee3d6b9
MT
376 sub_shell.add_argument("-m", "--mode", nargs="?", default="development",
377 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
47a4cb89
MT
378
379 def parse_command_dist(self):
380 # Implement the "dist" command.
381 sub_dist = self.sub_commands.add_parser("dist",
382 help=_("Generate a source package."))
e412b8dc
MT
383 sub_dist.add_argument("package", nargs="+",
384 help=_("Give name(s) of a package(s)."))
47a4cb89
MT
385 sub_dist.add_argument("action", action="store_const", const="dist")
386
387 sub_dist.add_argument("--resultdir", nargs="?",
388 help=_("Path were the output files should be copied to."))
389
9afa5620
MT
390 def handle_info(self):
391 Cli.handle_info(self, long=True)
392
47a4cb89 393 def handle_build(self):
47a4cb89
MT
394 # Get the package descriptor from the command line options
395 pkg = self.args.package[0]
396
397 # Check, if we got a regular file
398 if os.path.exists(pkg):
399 pkg = os.path.abspath(pkg)
400
47a4cb89 401 else:
7c8f2953 402 raise FileNotFoundError, pkg
47a4cb89 403
7c8f2953
MT
404 # Create distribution configuration from command line.
405 distro_config = {
406 "arch" : self.args.arch,
407 }
408
f22069bb
MT
409 pakfire.build(pkg, builder_mode=self.args.mode, distro_config=distro_config,
410 resultdirs=[self.args.resultdir,], shell=True, **self.pakfire_args)
47a4cb89
MT
411
412 def handle_shell(self):
042266f3
MT
413 pkg = None
414
47a4cb89 415 # Get the package descriptor from the command line options
042266f3 416 if self.args.package:
ad1b844f 417 pkg = self.args.package
47a4cb89 418
7c8f2953
MT
419 # Check, if we got a regular file
420 if os.path.exists(pkg):
421 pkg = os.path.abspath(pkg)
47a4cb89 422
7c8f2953
MT
423 else:
424 raise FileNotFoundError, pkg
47a4cb89 425
7c8f2953
MT
426 # Create distribution configuration from command line.
427 distro_config = {
428 "arch" : self.args.arch,
429 }
47a4cb89 430
6ee3d6b9
MT
431 pakfire.shell(pkg, builder_mode=self.args.mode,
432 distro_config=distro_config, **self.pakfire_args)
47a4cb89
MT
433
434 def handle_dist(self):
e412b8dc
MT
435 # Get the packages from the command line options
436 pkgs = []
47a4cb89 437
e412b8dc
MT
438 for pkg in self.args.package:
439 # Check, if we got a regular file
440 if os.path.exists(pkg):
441 pkg = os.path.abspath(pkg)
7c8f2953 442 pkgs.append(pkg)
47a4cb89 443
e412b8dc 444 else:
7c8f2953
MT
445 raise FileNotFoundError, pkg
446
6519843a
MT
447 pakfire.dist(pkgs, resultdirs=[self.args.resultdir,],
448 **self.pakfire_args)
47a4cb89 449
c605d735
MT
450 def handle_provides(self):
451 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
452
453 for pkg in pkgs:
454 print pkg.dump(long=True)
455
47a4cb89 456
3ad4bb5a 457class CliServer(Cli):
677ff42a
MT
458 def __init__(self):
459 self.parser = argparse.ArgumentParser(
3ad4bb5a 460 description = _("Pakfire server command line interface."),
677ff42a
MT
461 )
462
463 self.parse_common_arguments()
464
465 # Add sub-commands.
466 self.sub_commands = self.parser.add_subparsers()
467
a52f536c 468 self.parse_command_build()
677ff42a 469 self.parse_command_keepalive()
8276111d 470 self.parse_command_repoupdate()
df9c4f62 471 self.parse_command_repo()
677ff42a
MT
472
473 # Finally parse all arguments from the command line and save them.
474 self.args = self.parser.parse_args()
475
3ad4bb5a 476 self.server = server.Server()
677ff42a
MT
477
478 self.action2func = {
8276111d
MT
479 "build" : self.handle_build,
480 "keepalive" : self.handle_keepalive,
481 "repoupdate" : self.handle_repoupdate,
df9c4f62 482 "repo_create": self.handle_repo_create,
677ff42a
MT
483 }
484
6557ff4c
MT
485 @property
486 def pakfire_args(self):
487 ret = { "mode" : "server" }
488
6a509182
MT
489 if hasattr(self.args, "offline"):
490 ret["offline"] = self.args.offline
491
6557ff4c
MT
492 return ret
493
a52f536c
MT
494 def parse_command_build(self):
495 # Implement the "build" command.
496 sub_keepalive = self.sub_commands.add_parser("build",
497 help=_("Request a build job from the server."))
498 sub_keepalive.add_argument("action", action="store_const", const="build")
499
677ff42a
MT
500 def parse_command_keepalive(self):
501 # Implement the "keepalive" command.
502 sub_keepalive = self.sub_commands.add_parser("keepalive",
503 help=_("Send a keepalive to the server."))
504 sub_keepalive.add_argument("action", action="store_const",
505 const="keepalive")
506
8276111d
MT
507 def parse_command_repoupdate(self):
508 # Implement the "repoupdate" command.
509 sub_repoupdate = self.sub_commands.add_parser("repoupdate",
510 help=_("Update all repositories."))
511 sub_repoupdate.add_argument("action", action="store_const",
512 const="repoupdate")
513
df9c4f62
MT
514 def parse_command_repo(self):
515 sub_repo = self.sub_commands.add_parser("repo",
516 help=_("Repository management commands."))
517
518 sub_repo_commands = sub_repo.add_subparsers()
519
520 self.parse_command_repo_create(sub_repo_commands)
521
522 def parse_command_repo_create(self, sub_commands):
523 sub_create = sub_commands.add_parser("create",
524 help=_("Create a new repository index."))
525 sub_create.add_argument("path", nargs=1, help=_("Path to the packages."))
526 sub_create.add_argument("inputs", nargs="+", help=_("Path to input packages."))
527 sub_create.add_argument("action", action="store_const", const="repo_create")
528
677ff42a 529 def handle_keepalive(self):
3ad4bb5a 530 self.server.update_info()
9613a111 531
a52f536c 532 def handle_build(self):
3ad4bb5a 533 self.server.build_job()
8276111d
MT
534
535 def handle_repoupdate(self):
536 self.server.update_repositories()
df9c4f62
MT
537
538 def handle_repo_create(self):
539 path = self.args.path[0]
540
541 pakfire.repo_create(path, self.args.inputs, **self.pakfire_args)