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