]> git.ipfire.org Git - people/stevee/pakfire.git/blame - python/pakfire/cli.py
Fix creating the source package in default build process.
[people/stevee/pakfire.git] / python / 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
936f6b37 23import os
b913e798 24import shutil
47a4cb89 25import sys
b913e798 26import tempfile
47a4cb89 27
c62d93f1
MT
28import pakfire.api as pakfire
29
30import client
31import config
60845a36 32import logger
47a4cb89 33import packages
fa6d335b 34import repository
677ff42a 35import server
e9c20259 36import util
47a4cb89 37
c62d93f1 38from system import system
47a4cb89
MT
39from constants import *
40from i18n import _
41
60845a36
MT
42# Initialize a very simple logging that is removed when a Pakfire instance
43# is started.
44logger.setup_logging()
45
47a4cb89 46class Cli(object):
47a4cb89
MT
47 def __init__(self):
48 self.parser = argparse.ArgumentParser(
49 description = _("Pakfire command line interface."),
50 )
51
52 self.parse_common_arguments()
53
2ba449f0 54 self.parser.add_argument("--root", metavar="PATH",
d2e26956 55 default="/",
47a4cb89
MT
56 help=_("The path where pakfire should operate in."))
57
58 # Add sub-commands.
59 self.sub_commands = self.parser.add_subparsers()
60
61 self.parse_command_install()
5e87fa4f 62 self.parse_command_localinstall()
0ca71090 63 self.parse_command_reinstall()
a39fd08b 64 self.parse_command_remove()
47a4cb89
MT
65 self.parse_command_info()
66 self.parse_command_search()
e38914be 67 self.parse_command_check_update()
47a4cb89 68 self.parse_command_update()
67d1ddbd 69 self.parse_command_downgrade()
fa6d335b 70 self.parse_command_provides()
c1962d40 71 self.parse_command_grouplist()
ce2764c1 72 self.parse_command_groupinstall()
67bc4528 73 self.parse_command_repolist()
31267a64 74 self.parse_command_clean()
35d89fd7 75 self.parse_command_check()
b25a3d84 76 self.parse_command_resolvdep()
47a4cb89
MT
77
78 # Finally parse all arguments from the command line and save them.
79 self.args = self.parser.parse_args()
80
47a4cb89 81 self.action2func = {
5e87fa4f
MT
82 "install" : self.handle_install,
83 "localinstall" : self.handle_localinstall,
0ca71090 84 "reinstall" : self.handle_reinstall,
a39fd08b 85 "remove" : self.handle_remove,
e38914be 86 "check_update" : self.handle_check_update,
5e87fa4f 87 "update" : self.handle_update,
67d1ddbd 88 "downgrade" : self.handle_downgrade,
5e87fa4f
MT
89 "info" : self.handle_info,
90 "search" : self.handle_search,
fa6d335b 91 "provides" : self.handle_provides,
c1962d40 92 "grouplist" : self.handle_grouplist,
ce2764c1 93 "groupinstall" : self.handle_groupinstall,
67bc4528 94 "repolist" : self.handle_repolist,
31267a64 95 "clean_all" : self.handle_clean_all,
35d89fd7 96 "check" : self.handle_check,
b25a3d84 97 "resolvdep" : self.handle_resolvdep,
47a4cb89
MT
98 }
99
7c8f2953
MT
100 @property
101 def pakfire_args(self):
6557ff4c
MT
102 ret = { "mode" : "normal" }
103
2ba449f0
MT
104 if hasattr(self.args, "root"):
105 ret["path"] = self.args.root
f9a012a8
MT
106
107 if hasattr(self.args, "disable_repo"):
108 ret["disable_repos"] = self.args.disable_repo
109
110 if hasattr(self.args, "enable_repo"):
111 ret["enable_repos"] = self.args.enable_repo
112
6a509182
MT
113 if hasattr(self.args, "offline"):
114 ret["offline"] = self.args.offline
115
f9a012a8 116 return ret
7c8f2953 117
c62d93f1 118 def parse_common_arguments(self, repo_manage_switches=True, offline_switch=True):
50381f5c
MT
119 self.parser.add_argument("--version", action="version",
120 version="%(prog)s " + PAKFIRE_VERSION)
121
47a4cb89
MT
122 self.parser.add_argument("-v", "--verbose", action="store_true",
123 help=_("Enable verbose output."))
124
125 self.parser.add_argument("-c", "--config", nargs="?",
126 help=_("Path to a configuration file to load."))
127
c62d93f1
MT
128 if repo_manage_switches:
129 self.parser.add_argument("--disable-repo", nargs="*", metavar="REPO",
130 help=_("Disable a repository temporarily."))
f781b1ab 131
c62d93f1
MT
132 self.parser.add_argument("--enabled-repo", nargs="*", metavar="REPO",
133 help=_("Enable a repository temporarily."))
f9a012a8 134
c62d93f1
MT
135 if offline_switch:
136 self.parser.add_argument("--offline", action="store_true",
137 help=_("Run pakfire in offline mode."))
6a509182 138
47a4cb89
MT
139 def parse_command_install(self):
140 # Implement the "install" command.
141 sub_install = self.sub_commands.add_parser("install",
142 help=_("Install one or more packages to the system."))
143 sub_install.add_argument("package", nargs="+",
144 help=_("Give name of at least one package to install."))
145 sub_install.add_argument("action", action="store_const", const="install")
146
5e87fa4f
MT
147 def parse_command_localinstall(self):
148 # Implement the "localinstall" command.
149 sub_install = self.sub_commands.add_parser("localinstall",
150 help=_("Install one or more packages from the filesystem."))
151 sub_install.add_argument("package", nargs="+",
152 help=_("Give filename of at least one package."))
153 sub_install.add_argument("action", action="store_const", const="localinstall")
154
0ca71090
MT
155 def parse_command_reinstall(self):
156 # Implement the "reinstall" command.
157 sub_install = self.sub_commands.add_parser("reinstall",
158 help=_("Reinstall one or more packages."))
159 sub_install.add_argument("package", nargs="+",
160 help=_("Give name of at least one package to reinstall."))
161 sub_install.add_argument("action", action="store_const", const="reinstall")
162
a39fd08b
MT
163 def parse_command_remove(self):
164 # Implement the "remove" command.
165 sub_remove = self.sub_commands.add_parser("remove",
166 help=_("Remove one or more packages from the system."))
167 sub_remove.add_argument("package", nargs="+",
168 help=_("Give name of at least one package to remove."))
169 sub_remove.add_argument("action", action="store_const", const="remove")
170
05fb1da0
MT
171 @staticmethod
172 def _parse_command_update(parser):
173 parser.add_argument("package", nargs="*",
174 help=_("Give a name of a package to update or leave emtpy for all."))
175 parser.add_argument("--exclude", "-x", nargs="+",
176 help=_("Exclude package from update."))
177 parser.add_argument("--allow-vendorchange", action="store_true",
178 help=_("Allow changing the vendor of packages."))
179 parser.add_argument("--allow-archchange", action="store_true",
180 help=_("Allow changing the architecture of packages."))
181
47a4cb89
MT
182 def parse_command_update(self):
183 # Implement the "update" command.
184 sub_update = self.sub_commands.add_parser("update",
185 help=_("Update the whole system or one specific package."))
47a4cb89 186 sub_update.add_argument("action", action="store_const", const="update")
05fb1da0 187 self._parse_command_update(sub_update)
47a4cb89 188
e38914be
MT
189 def parse_command_check_update(self):
190 # Implement the "check-update" command.
191 sub_check_update = self.sub_commands.add_parser("check-update",
192 help=_("Check, if there are any updates available."))
e38914be 193 sub_check_update.add_argument("action", action="store_const", const="check_update")
05fb1da0 194 self._parse_command_update(sub_check_update)
e38914be 195
67d1ddbd
MT
196 def parse_command_downgrade(self):
197 # Implement the "downgrade" command.
198 sub_downgrade = self.sub_commands.add_parser("downgrade",
199 help=_("Downgrade one or more packages."))
200 sub_downgrade.add_argument("package", nargs="*",
201 help=_("Give a name of a package to downgrade."))
202 sub_downgrade.add_argument("--allow-vendorchange", action="store_true",
203 help=_("Allow changing the vendor of packages."))
204 sub_downgrade.add_argument("--allow-archchange", action="store_true",
205 help=_("Allow changing the architecture of packages."))
206 sub_downgrade.add_argument("action", action="store_const", const="downgrade")
207
47a4cb89
MT
208 def parse_command_info(self):
209 # Implement the "info" command.
210 sub_info = self.sub_commands.add_parser("info",
211 help=_("Print some information about the given package(s)."))
212 sub_info.add_argument("package", nargs="+",
213 help=_("Give at least the name of one package."))
214 sub_info.add_argument("action", action="store_const", const="info")
215
216 def parse_command_search(self):
217 # Implement the "search" command.
218 sub_search = self.sub_commands.add_parser("search",
219 help=_("Search for a given pattern."))
220 sub_search.add_argument("pattern",
221 help=_("A pattern to search for."))
222 sub_search.add_argument("action", action="store_const", const="search")
223
fa6d335b
MT
224 def parse_command_provides(self):
225 # Implement the "provides" command
226 sub_provides = self.sub_commands.add_parser("provides",
227 help=_("Get a list of packages that provide a given file or feature."))
228 sub_provides.add_argument("pattern", nargs="+",
229 help=_("File or feature to search for."))
230 sub_provides.add_argument("action", action="store_const", const="provides")
231
c1962d40
MT
232 def parse_command_grouplist(self):
233 # Implement the "grouplist" command
234 sub_grouplist = self.sub_commands.add_parser("grouplist",
235 help=_("Get list of packages that belong to the given group."))
236 sub_grouplist.add_argument("group", nargs=1,
237 help=_("Group name to search for."))
238 sub_grouplist.add_argument("action", action="store_const", const="grouplist")
239
ce2764c1
MT
240 def parse_command_groupinstall(self):
241 # Implement the "grouplist" command
242 sub_groupinstall = self.sub_commands.add_parser("groupinstall",
243 help=_("Install all packages that belong to the given group."))
244 sub_groupinstall.add_argument("group", nargs=1,
245 help=_("Group name."))
246 sub_groupinstall.add_argument("action", action="store_const", const="groupinstall")
247
67bc4528
MT
248 def parse_command_repolist(self):
249 # Implement the "repolist" command
250 sub_repolist = self.sub_commands.add_parser("repolist",
251 help=_("List all currently enabled repositories."))
252 sub_repolist.add_argument("action", action="store_const", const="repolist")
ce2764c1 253
31267a64
MT
254 def parse_command_clean(self):
255 sub_clean = self.sub_commands.add_parser("clean", help=_("Cleanup commands."))
256
257 sub_clean_commands = sub_clean.add_subparsers()
258
259 self.parse_command_clean_all(sub_clean_commands)
260
261 def parse_command_clean_all(self, sub_commands):
262 sub_create = sub_commands.add_parser("all",
263 help=_("Cleanup all temporary files."))
264 sub_create.add_argument("action", action="store_const", const="clean_all")
265
35d89fd7
MT
266 def parse_command_check(self):
267 # Implement the "check" command
268 sub_check = self.sub_commands.add_parser("check",
269 help=_("Check the system for any errors."))
270 sub_check.add_argument("action", action="store_const", const="check")
271
b25a3d84
MT
272 def parse_command_resolvdep(self):
273 # Implement the "resolvdep" command.
274 sub_resolvdep = self.sub_commands.add_parser("resolvdep",
275 help=_("Check the dependencies for a particular package."))
276 sub_resolvdep.add_argument("package", nargs="+",
277 help=_("Give name of at least one package to check."))
278 sub_resolvdep.add_argument("action", action="store_const", const="resolvdep")
279
47a4cb89
MT
280 def run(self):
281 action = self.args.action
282
47a4cb89
MT
283 try:
284 func = self.action2func[action]
285 except KeyError:
c62d93f1 286 raise Exception, "Unhandled action: %s" % action
47a4cb89
MT
287
288 return func()
289
9afa5620 290 def handle_info(self, long=False):
7c8f2953 291 pkgs = pakfire.info(self.args.package, **self.pakfire_args)
47a4cb89 292
7c8f2953
MT
293 for pkg in pkgs:
294 print pkg.dump(long=long)
47a4cb89
MT
295
296 def handle_search(self):
7c8f2953 297 pkgs = pakfire.search(self.args.pattern, **self.pakfire_args)
47a4cb89
MT
298
299 for pkg in pkgs:
300 print pkg.dump(short=True)
301
05fb1da0
MT
302 def handle_update(self, **args):
303 args.update(self.pakfire_args)
304
305 pakfire.update(self.args.package, excludes=self.args.exclude,
306 allow_vendorchange=self.args.allow_vendorchange,
307 allow_archchange=self.args.allow_archchange,
308 **args)
47a4cb89 309
e38914be 310 def handle_check_update(self):
05fb1da0 311 self.handle_update(check=True)
e38914be 312
67d1ddbd
MT
313 def handle_downgrade(self, **args):
314 args.update(self.pakfire_args)
315
316 pakfire.downgrade(self.args.package,
317 allow_vendorchange=self.args.allow_vendorchange,
318 allow_archchange=self.args.allow_archchange,
319 **args)
320
e0b99370
MT
321 def handle_install(self):
322 pakfire.install(self.args.package, **self.pakfire_args)
5e87fa4f
MT
323
324 def handle_localinstall(self):
e0b99370 325 pakfire.localinstall(self.args.package, **self.pakfire_args)
5e87fa4f 326
0ca71090
MT
327 def handle_reinstall(self):
328 pakfire.reinstall(self.args.package, **self.pakfire_args)
329
a39fd08b
MT
330 def handle_remove(self):
331 pakfire.remove(self.args.package, **self.pakfire_args)
332
fa6d335b 333 def handle_provides(self):
7c8f2953 334 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
fa6d335b
MT
335
336 for pkg in pkgs:
337 print pkg.dump()
338
c1962d40 339 def handle_grouplist(self):
7c8f2953 340 pkgs = pakfire.grouplist(self.args.group[0], **self.pakfire_args)
c1962d40
MT
341
342 for pkg in pkgs:
343 print " * %s" % pkg
344
ce2764c1 345 def handle_groupinstall(self):
7c8f2953 346 pakfire.groupinstall(self.args.group[0], **self.pakfire_args)
ce2764c1 347
67bc4528 348 def handle_repolist(self):
7c8f2953 349 repos = pakfire.repo_list(**self.pakfire_args)
67bc4528 350
c605d735 351 FORMAT = " %-20s %8s %12s %12s "
67bc4528 352
c605d735 353 title = FORMAT % (_("Repository"), _("Enabled"), _("Priority"), _("Packages"))
67bc4528
MT
354 print title
355 print "=" * len(title) # spacing line
356
357 for repo in repos:
358 # Skip the installed repository.
359 if repo.name == "installed":
360 continue
361
c605d735 362 print FORMAT % (repo.name, repo.enabled, repo.priority, len(repo))
67bc4528 363
31267a64
MT
364 def handle_clean_all(self):
365 print _("Cleaning up everything...")
366
367 pakfire.clean_all(**self.pakfire_args)
368
35d89fd7
MT
369 def handle_check(self):
370 pakfire.check(**self.pakfire_args)
371
b25a3d84
MT
372 def handle_resolvdep(self):
373 pakfire.resolvdep(self.args.package, **self.pakfire_args)
374
47a4cb89
MT
375
376class CliBuilder(Cli):
377 def __init__(self):
936f6b37
MT
378 # Check if we are already running in a pakfire container. In that
379 # case, we cannot start another pakfire-builder.
380 if os.environ.get("container", None) == "pakfire-builder":
381 raise PakfireContainerError, _("You cannot run pakfire-builder in a pakfire chroot.")
382
47a4cb89
MT
383 self.parser = argparse.ArgumentParser(
384 description = _("Pakfire builder command line interface."),
385 )
386
387 self.parse_common_arguments()
388
389 # Add sub-commands.
390 self.sub_commands = self.parser.add_subparsers()
391
392 self.parse_command_build()
393 self.parse_command_dist()
394 self.parse_command_info()
395 self.parse_command_search()
396 self.parse_command_shell()
397 self.parse_command_update()
4fbd4216 398 self.parse_command_provides()
2c84aceb 399 self.parse_command_grouplist()
67bc4528 400 self.parse_command_repolist()
31267a64 401 self.parse_command_clean()
b25a3d84 402 self.parse_command_resolvdep()
3817ae8e 403 self.parse_command_cache()
47a4cb89
MT
404
405 # Finally parse all arguments from the command line and save them.
406 self.args = self.parser.parse_args()
407
47a4cb89 408 self.action2func = {
fa6d335b
MT
409 "build" : self.handle_build,
410 "dist" : self.handle_dist,
411 "update" : self.handle_update,
412 "info" : self.handle_info,
413 "search" : self.handle_search,
414 "shell" : self.handle_shell,
4fbd4216 415 "provides" : self.handle_provides,
2c84aceb 416 "grouplist" : self.handle_grouplist,
67bc4528 417 "repolist" : self.handle_repolist,
31267a64 418 "clean_all" : self.handle_clean_all,
b25a3d84 419 "resolvdep" : self.handle_resolvdep,
3817ae8e
MT
420 "cache_create": self.handle_cache_create,
421 "cache_cleanup": self.handle_cache_cleanup,
47a4cb89
MT
422 }
423
7c8f2953
MT
424 @property
425 def pakfire_args(self):
6557ff4c 426 ret = { "mode" : "builder" }
f9a012a8
MT
427
428 if hasattr(self.args, "disable_repo"):
429 ret["disable_repos"] = self.args.disable_repo
430
431 if hasattr(self.args, "enable_repo"):
432 ret["enable_repos"] = self.args.enable_repo
433
6a509182
MT
434 if hasattr(self.args, "offline"):
435 ret["offline"] = self.args.offline
436
f9a012a8 437 return ret
7c8f2953 438
47a4cb89
MT
439 def parse_command_update(self):
440 # Implement the "update" command.
441 sub_update = self.sub_commands.add_parser("update",
442 help=_("Update the package indexes."))
443 sub_update.add_argument("action", action="store_const", const="update")
444
445 def parse_command_build(self):
446 # Implement the "build" command.
447 sub_build = self.sub_commands.add_parser("build",
448 help=_("Build one or more packages."))
449 sub_build.add_argument("package", nargs=1,
450 help=_("Give name of at least one package to build."))
451 sub_build.add_argument("action", action="store_const", const="build")
452
453 sub_build.add_argument("-a", "--arch",
454 help=_("Build the package for the given architecture."))
455 sub_build.add_argument("--resultdir", nargs="?",
456 help=_("Path were the output files should be copied to."))
f22069bb
MT
457 sub_build.add_argument("-m", "--mode", nargs="?", default="development",
458 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
1710ccec
MT
459 sub_build.add_argument("--after-shell", action="store_true",
460 help=_("Run a shell after a successful build."))
47a4cb89
MT
461
462 def parse_command_shell(self):
463 # Implement the "shell" command.
464 sub_shell = self.sub_commands.add_parser("shell",
465 help=_("Go into a shell."))
042266f3 466 sub_shell.add_argument("package", nargs="?",
47a4cb89
MT
467 help=_("Give name of a package."))
468 sub_shell.add_argument("action", action="store_const", const="shell")
469
470 sub_shell.add_argument("-a", "--arch",
471 help=_("Emulated architecture in the shell."))
6ee3d6b9
MT
472 sub_shell.add_argument("-m", "--mode", nargs="?", default="development",
473 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
47a4cb89
MT
474
475 def parse_command_dist(self):
476 # Implement the "dist" command.
477 sub_dist = self.sub_commands.add_parser("dist",
478 help=_("Generate a source package."))
e412b8dc
MT
479 sub_dist.add_argument("package", nargs="+",
480 help=_("Give name(s) of a package(s)."))
47a4cb89
MT
481 sub_dist.add_argument("action", action="store_const", const="dist")
482
483 sub_dist.add_argument("--resultdir", nargs="?",
484 help=_("Path were the output files should be copied to."))
485
3817ae8e
MT
486 def parse_command_cache(self):
487 # Implement the "cache" command.
488 sub_cache = self.sub_commands.add_parser("cache",
489 help=_("Create a build environment cache."))
490
491 # Implement subcommands.
492 sub_cache_commands = sub_cache.add_subparsers()
493
494 self.parse_command_cache_create(sub_cache_commands)
495 self.parse_command_cache_cleanup(sub_cache_commands)
496
497 def parse_command_cache_create(self, sub_commands):
498 sub_create = sub_commands.add_parser("create",
499 help=_("Create a new build environment cache."))
500 sub_create.add_argument("action", action="store_const", const="cache_create")
501
502 def parse_command_cache_cleanup(self, sub_commands):
503 sub_cleanup = sub_commands.add_parser("cleanup",
504 help=_("Remove all cached build environments."))
505 sub_cleanup.add_argument("action", action="store_const", const="cache_cleanup")
506
9afa5620
MT
507 def handle_info(self):
508 Cli.handle_info(self, long=True)
509
47a4cb89 510 def handle_build(self):
47a4cb89
MT
511 # Get the package descriptor from the command line options
512 pkg = self.args.package[0]
513
514 # Check, if we got a regular file
515 if os.path.exists(pkg):
516 pkg = os.path.abspath(pkg)
517
47a4cb89 518 else:
7c8f2953 519 raise FileNotFoundError, pkg
47a4cb89 520
7c8f2953
MT
521 # Create distribution configuration from command line.
522 distro_config = {
523 "arch" : self.args.arch,
524 }
525
c07a3ca7
MT
526 pakfire.build(pkg, builder_mode=self.args.mode,
527 distro_config=distro_config, resultdirs=[self.args.resultdir,],
1710ccec 528 shell=True, after_shell=self.args.after_shell, **self.pakfire_args)
47a4cb89
MT
529
530 def handle_shell(self):
042266f3
MT
531 pkg = None
532
47a4cb89 533 # Get the package descriptor from the command line options
042266f3 534 if self.args.package:
ad1b844f 535 pkg = self.args.package
47a4cb89 536
7c8f2953
MT
537 # Check, if we got a regular file
538 if os.path.exists(pkg):
539 pkg = os.path.abspath(pkg)
47a4cb89 540
7c8f2953
MT
541 else:
542 raise FileNotFoundError, pkg
47a4cb89 543
7c8f2953
MT
544 # Create distribution configuration from command line.
545 distro_config = {
546 "arch" : self.args.arch,
547 }
47a4cb89 548
6ee3d6b9
MT
549 pakfire.shell(pkg, builder_mode=self.args.mode,
550 distro_config=distro_config, **self.pakfire_args)
47a4cb89
MT
551
552 def handle_dist(self):
e412b8dc
MT
553 # Get the packages from the command line options
554 pkgs = []
47a4cb89 555
e412b8dc
MT
556 for pkg in self.args.package:
557 # Check, if we got a regular file
558 if os.path.exists(pkg):
559 pkg = os.path.abspath(pkg)
7c8f2953 560 pkgs.append(pkg)
47a4cb89 561
e412b8dc 562 else:
7c8f2953
MT
563 raise FileNotFoundError, pkg
564
7d40ac70
MT
565 # Put packages to where the user said or our
566 # current working directory.
567 resultdir = self.args.resultdir or os.getcwd()
568
569 # Change the default pakfire configuration, because
570 # packaging source packages can be done in server mode.
571 pakfire_args = self.pakfire_args
572 pakfire_args["mode"] = "server"
573
574 for pkg in pkgs:
575 pakfire.dist(pkg, resultdir=resultdir, **pakfire_args)
47a4cb89 576
c605d735
MT
577 def handle_provides(self):
578 pkgs = pakfire.provides(self.args.pattern, **self.pakfire_args)
579
580 for pkg in pkgs:
581 print pkg.dump(long=True)
582
3817ae8e
MT
583 def handle_cache_create(self):
584 pakfire.cache_create(**self.pakfire_args)
585
586 def handle_cache_cleanup(self):
587 for env in os.listdir(CACHE_ENVIRON_DIR):
588 if not env.endswith(".cache"):
589 continue
590
591 print _("Removing environment cache file: %s..." % env)
592 env = os.path.join(CACHE_ENVIRON_DIR, env)
593
594 try:
595 os.unlink(env)
596 except OSError:
597 print _("Could not remove file: %s") % env
598
47a4cb89 599
3ad4bb5a 600class CliServer(Cli):
677ff42a
MT
601 def __init__(self):
602 self.parser = argparse.ArgumentParser(
3ad4bb5a 603 description = _("Pakfire server command line interface."),
677ff42a
MT
604 )
605
606 self.parse_common_arguments()
607
608 # Add sub-commands.
609 self.sub_commands = self.parser.add_subparsers()
610
a52f536c 611 self.parse_command_build()
677ff42a 612 self.parse_command_keepalive()
8276111d 613 self.parse_command_repoupdate()
df9c4f62 614 self.parse_command_repo()
aad6f600 615 self.parse_command_info()
677ff42a
MT
616
617 # Finally parse all arguments from the command line and save them.
618 self.args = self.parser.parse_args()
619
269c59f3 620 self.server = server.Server(**self.pakfire_args)
677ff42a
MT
621
622 self.action2func = {
8276111d 623 "build" : self.handle_build,
aad6f600 624 "info" : self.handle_info,
8276111d
MT
625 "keepalive" : self.handle_keepalive,
626 "repoupdate" : self.handle_repoupdate,
df9c4f62 627 "repo_create": self.handle_repo_create,
677ff42a
MT
628 }
629
6557ff4c
MT
630 @property
631 def pakfire_args(self):
632 ret = { "mode" : "server" }
633
6a509182
MT
634 if hasattr(self.args, "offline"):
635 ret["offline"] = self.args.offline
636
6557ff4c
MT
637 return ret
638
a52f536c
MT
639 def parse_command_build(self):
640 # Implement the "build" command.
c62d93f1
MT
641 sub_build = self.sub_commands.add_parser("build",
642 help=_("Send a scrach build job to the server."))
643 sub_build.add_argument("package", nargs=1,
644 help=_("Give name of at least one package to build."))
645 sub_build.add_argument("--arch", "-a",
646 help=_("Limit build to only these architecture(s)."))
647 sub_build.add_argument("action", action="store_const", const="build")
a52f536c 648
677ff42a
MT
649 def parse_command_keepalive(self):
650 # Implement the "keepalive" command.
651 sub_keepalive = self.sub_commands.add_parser("keepalive",
652 help=_("Send a keepalive to the server."))
653 sub_keepalive.add_argument("action", action="store_const",
654 const="keepalive")
655
8276111d
MT
656 def parse_command_repoupdate(self):
657 # Implement the "repoupdate" command.
658 sub_repoupdate = self.sub_commands.add_parser("repoupdate",
659 help=_("Update all repositories."))
660 sub_repoupdate.add_argument("action", action="store_const",
661 const="repoupdate")
662
df9c4f62
MT
663 def parse_command_repo(self):
664 sub_repo = self.sub_commands.add_parser("repo",
665 help=_("Repository management commands."))
666
667 sub_repo_commands = sub_repo.add_subparsers()
668
669 self.parse_command_repo_create(sub_repo_commands)
670
671 def parse_command_repo_create(self, sub_commands):
672 sub_create = sub_commands.add_parser("create",
673 help=_("Create a new repository index."))
674 sub_create.add_argument("path", nargs=1, help=_("Path to the packages."))
675 sub_create.add_argument("inputs", nargs="+", help=_("Path to input packages."))
676 sub_create.add_argument("action", action="store_const", const="repo_create")
677
aad6f600
MT
678 def parse_command_info(self):
679 sub_info = self.sub_commands.add_parser("info",
680 help=_("Dump some information about this machine."))
681 sub_info.add_argument("action", action="store_const", const="info")
682
677ff42a 683 def handle_keepalive(self):
3ad4bb5a 684 self.server.update_info()
9613a111 685
a52f536c 686 def handle_build(self):
c62d93f1
MT
687 # Arch.
688 if self.args.arch:
689 arches = self.args.arch.split()
690
691 (package,) = self.args.package
692
693 self.server.create_scratch_build({})
694 return
695
696 # Temporary folter for source package.
697 tmpdir = "/tmp/pakfire-%s" % util.random_string()
698
699 try:
700 os.makedirs(tmpdir)
701
702 pakfire.dist(package, resultdir=[tmpdir,])
703
704 for file in os.listdir(tmpdir):
705 file = os.path.join(tmpdir, file)
706
707 print file
708
709 finally:
710 if os.path.exists(tmpdir):
711 util.rm(tmpdir)
8276111d
MT
712
713 def handle_repoupdate(self):
714 self.server.update_repositories()
df9c4f62
MT
715
716 def handle_repo_create(self):
717 path = self.args.path[0]
718
719 pakfire.repo_create(path, self.args.inputs, **self.pakfire_args)
c07a3ca7 720
aad6f600
MT
721 def handle_info(self):
722 info = self.server.info()
723
724 print "\n".join(info)
725
c07a3ca7 726
9b875540 727class CliBuilderIntern(Cli):
c07a3ca7
MT
728 def __init__(self):
729 self.parser = argparse.ArgumentParser(
730 description = _("Pakfire builder command line interface."),
731 )
732
733 self.parse_common_arguments()
734
735 # Add sub-commands.
736 self.sub_commands = self.parser.add_subparsers()
737
738 self.parse_command_build()
739
740 # Finally parse all arguments from the command line and save them.
741 self.args = self.parser.parse_args()
742
743 self.action2func = {
744 "build" : self.handle_build,
745 }
746
747 def parse_command_build(self):
748 # Implement the "build" command.
749 sub_build = self.sub_commands.add_parser("build",
750 help=_("Build one or more packages."))
751 sub_build.add_argument("package", nargs=1,
752 help=_("Give name of at least one package to build."))
753 sub_build.add_argument("action", action="store_const", const="build")
754
755 sub_build.add_argument("-a", "--arch",
756 help=_("Build the package for the given architecture."))
757 sub_build.add_argument("--resultdir", nargs="?",
758 help=_("Path were the output files should be copied to."))
759 sub_build.add_argument("-m", "--mode", nargs="?", default="development",
760 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
761 sub_build.add_argument("--nodeps", action="store_true",
762 help=_("Do not verify build dependencies."))
763
764 def handle_build(self):
765 # Get the package descriptor from the command line options
766 pkg = self.args.package[0]
767
768 # Check, if we got a regular file
769 if os.path.exists(pkg):
770 pkg = os.path.abspath(pkg)
771 else:
772 raise FileNotFoundError, pkg
773
774 # Create distribution configuration from command line.
775 distro_config = {
776 "arch" : self.args.arch,
777 }
778
779 pakfire._build(pkg, builder_mode=self.args.mode,
c62d93f1
MT
780 distro_config=distro_config, resultdir=self.args.resultdir,)
781
782
783class CliClient(Cli):
784 def __init__(self):
785 self.parser = argparse.ArgumentParser(
786 description = _("Pakfire client command line interface."),
787 )
788
789 self.parse_common_arguments(repo_manage_switches=True, offline_switch=True)
790
791 # Add sub-commands.
792 self.sub_commands = self.parser.add_subparsers()
793
794 self.parse_command_build()
795 self.parse_command_connection_check()
796 self.parse_command_info()
797
798 # Finally parse all arguments from the command line and save them.
799 self.args = self.parser.parse_args()
800
801 self.action2func = {
802 "build" : self.handle_build,
803 "conn-check" : self.handle_connection_check,
804 "info" : self.handle_info,
805 }
806
807 # Read configuration for the pakfire client.
808 self.conf = conf = config.ConfigClient()
809
810 # Create connection to pakfire hub.
811 self.client = client.PakfireUserClient(
812 conf.get("client", "server"),
813 conf.get("client", "username"),
814 conf.get("client", "password"),
815 )
816
817 def parse_command_build(self):
818 # Parse "build" command.
819 sub_build = self.sub_commands.add_parser("build",
820 help=_("Build a package remotely."))
821 sub_build.add_argument("package", nargs=1,
822 help=_("Give name of a package to build."))
823 sub_build.add_argument("action", action="store_const", const="build")
824
825 sub_build.add_argument("-a", "--arch",
826 help=_("Build the package for the given architecture."))
827
828 def parse_command_info(self):
829 # Implement the "info" command.
830 sub_info = self.sub_commands.add_parser("info",
831 help=_("Print some information about this host."))
832 sub_info.add_argument("action", action="store_const", const="info")
833
834 def parse_command_connection_check(self):
835 # Implement the "conn-check" command.
836 sub_conn_check = self.sub_commands.add_parser("conn-check",
837 help=_("Check the connection to the hub."))
838 sub_conn_check.add_argument("action", action="store_const", const="conn-check")
839
840 def handle_build(self):
841 (package,) = self.args.package
842
843 # XXX just for now, we do only upload source pfm files.
844 assert os.path.exists(package)
845
b913e798
MT
846 # Create a temporary directory.
847 temp_dir = tempfile.mkdtemp()
848
849 try:
850 if package.endswith(".%s" % MAKEFILE_EXTENSION):
851 pakfire_args = { "mode" : "server" }
852
853 # Create a source package from the makefile.
854 package = pakfire.dist(package, temp_dir, **pakfire_args)
855
856 elif package.endswith(".%s" % PACKAGE_EXTENSION):
857 pass
c62d93f1 858
b913e798
MT
859 else:
860 raise Exception, "Unknown filetype: %s" % package
861
862 # Format arches.
863 if self.args.arch:
864 arches = self.args.arch.replace(",", " ")
865 else:
866 arches = None
c62d93f1 867
b913e798
MT
868 # Create a new build on the server.
869 build = self.client.build_create(package, arches=arches)
870
871 # XXX Print the resulting build.
872 print build
873
874 finally:
875 # Cleanup the temporary directory and all files.
876 if os.path.exists(temp_dir):
877 shutil.rmtree(temp_dir, ignore_errors=True)
c62d93f1
MT
878
879 def handle_info(self):
880 ret = []
881
882 ret.append("")
883 ret.append(" PAKFIRE %s" % PAKFIRE_VERSION)
884 ret.append("")
885 ret.append(" %-20s: %s" % (_("Hostname"), system.hostname))
886 ret.append(" %-20s: %s" % (_("Pakfire hub"), self.conf.get("client", "server")))
887 if self.conf.get("client", "username") and self.conf.get("client", "password"):
888 ret.append(" %-20s: %s" % \
889 (_("Username"), self.conf.get("client", "username")))
890 ret.append("")
891
892 # Hardware information
893 ret.append(" %s:" % _("Hardware information"))
894 ret.append(" %-16s: %s" % (_("CPU model"), system.cpu_model))
895 ret.append(" %-16s: %s" % (_("Memory"), util.format_size(system.memory)))
896 ret.append("")
790a44cc
MT
897 ret.append(" %-16s: %s" % (_("Native arch"), system.native_arch))
898 if not system.arch == system.native_arch:
899 ret.append(" %-16s: %s" % (_("Default arch"), system.arch))
c62d93f1
MT
900
901 header = _("Supported arches")
902 for arch in system.supported_arches:
903 ret.append(" %-16s: %s" % (header, arch))
904 header = ""
905 ret.append("")
906
907 for line in ret:
908 print line
909
910 def handle_connection_check(self):
911 ret = []
912
913 address = self.client.get_my_address()
914 ret.append(" %-20s: %s" % (_("Your IP address"), address))
915 ret.append("")
916
917 authenticated = self.client.check_auth()
918 if authenticated:
919 ret.append(" %s" % _("You are authenticated to the build service:"))
920
921 user = self.client.get_user_profile()
922 assert user, "Could not fetch user infomation"
923
924 keys = [
925 ("name", _("User name")),
926 ("realname", _("Real name")),
927 ("email", _("Email address")),
928 ("registered", _("Registered")),
929 ]
930
931 for key, desc in keys:
932 ret.append(" %-18s: %s" % (desc, user.get(key)))
933
934 else:
935 ret.append(_("You could not be authenticated to the build service."))
936
937 for line in ret:
938 print line
939
940
941class CliDaemon(Cli):
942 def __init__(self):
943 self.parser = argparse.ArgumentParser(
944 description = _("Pakfire daemon command line interface."),
945 )
946
947 self.parse_common_arguments(repo_manage_switches=True, offline_switch=True)
948
949 # Finally parse all arguments from the command line and save them.
950 self.args = self.parser.parse_args()
951
952 def run(self):
953 """
954 Runs the pakfire daemon with provided settings.
955 """
956 # Read the configuration file for the daemon.
957 conf = config.ConfigDaemon()
958
959 # Create daemon instance.
960 d = pakfire.client.PakfireDaemon(
961 server = conf.get("daemon", "server"),
962 hostname = conf.get("daemon", "hostname"),
963 secret = conf.get("daemon", "secret"),
964 )
965
966 try:
967 d.run()
968
969 # We cannot just kill the daemon, it needs a smooth shutdown.
970 except (SystemExit, KeyboardInterrupt):
971 d.shutdown()