summaryrefslogtreecommitdiff
path: root/portato.py
blob: 7cca894a53f0d39de88dbf61890bfb9dc1534daa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python
# -*- coding: utf-8 -*-

#
# File: portato.py
# This file is part of the Portato-Project, a graphical portage-frontend.
#
# Copyright (C) 2006-2007 René 'Necoro' Neumann
# This is free software.  You may redistribute copies of it under the terms of
# the GNU General Public License version 2.
# There is NO WARRANTY, to the extent permitted by law.
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>

from __future__ import with_statement, absolute_import

import sys, os, subprocess
import gettext, locale
from optparse import OptionParser, SUPPRESS_HELP

try:
	import shm_wrapper as shm
except ImportError:
	from portato.shm import shm_wrapper as shm

from portato import get_listener
from portato.constants import VERSION, FRONTENDS, STD_FRONTEND, XSD_LOCATION, LOCALE_DIR, APP, SU_COMMAND

def get_frontend_list ():
	return ", ".join(["'%s'" % x for x in FRONTENDS])

def main ():
	# set gettext stuff
	locale.setlocale(locale.LC_ALL, '')
	gettext.bindtextdomain(APP, LOCALE_DIR)
	gettext.textdomain(APP)
	_ = gettext.lgettext

	# build the parser
	desc = "Portato - A Portage GUI."
	usage = "%prog [options] [frontend]"
	vers =  "%%prog v. %s" % VERSION

	parser = OptionParser(version = vers, prog = "Portato", description = desc, usage = usage)
	
	parser.add_option("--check", action = "store_true", dest = "check", default = False,
			help = _("runs pychecker (should only be used by developers)"))
	
	parser.add_option("-f", "--frontend", action = "store", choices = FRONTENDS, default = STD_FRONTEND, dest = "frontend",
			help = _("the frontend to use - possible values are: %s [default: %%default]") % get_frontend_list())

	parser.add_option("-e", "--ebuild", action = "store", dest = "ebuild",
			help = _("opens the ebuild viewer instead of launching Portato"))

	parser.add_option("--shm", action = "store", nargs = 3, type="long", dest = "shm",
			help = SUPPRESS_HELP)

	parser.add_option("-x", "--validate", action = "store", dest = "validate", metavar="PLUGIN",
			help = _("validates the given plugin xml instead of launching Portato"))

	parser.add_option("-L", "--no-listener", action = "store_true", dest = "nolistener", default = False, 
			help = _("do not start listener"))

	# run parser
	(options, args) = parser.parse_args()

	# evaluate parser's results
	if options.check: # run pychecker
		os.environ['PYCHECKER'] = "--limit 100"
		import pychecker.checker
	
	if len(args): # additional arguments overwrite given frontend
		arg = args[0]
		if arg not in FRONTENDS:
			print _("Unknown frontend '%(frontend)s'. Correct frontends are: %(list)s") % {"frontend": arg, "list": get_frontend_list()}
			sys.exit(2)
		else:
			options.frontend = arg

	try:
		exec ("from portato.gui.%s import run, show_ebuild" % options.frontend)
	except ImportError, e:
		print _("'%(frontend)s' should be installed, but cannot be imported. This is definitly a bug. (%(error)s)") % {"frontend": options.frontend, "error": e[0]}
		sys.exit(1)

	if options.ebuild: # show ebuild
		show_ebuild(options.ebuild)
	elif options.validate: # validate a plugin
		from lxml import etree
		try:
			etree.XMLSchema(file = XSD_LOCATION).assertValid(etree.parse(options.validate))
		except etree.XMLSyntaxError, e:
			print _("Validation failed. XML syntax error: %s.") % e[0]
			sys.exit(3)
		except etree.DocumentInvalid:
			print _("Validation failed. Does not comply with schema.")
			sys.exit(3)
		else:
			print _("Validation succeeded.")
			return

	elif options.nolistener or os.getuid() == 0: # start GUI
		if options.shm:
			get_listener().set_send(*options.shm)
		else:
			get_listener().set_send()
		
		run()
		
	else: # start us again in root modus and launch listener
		
		mem = shm.create_memory(1024, permissions=0600)
		sig = shm.create_semaphore(InitialValue = 0, permissions = 0600)
		rw = shm.create_semaphore(InitialValue = 1, permissions = 0600)
		
		additional = []
		if options.check:
			additional.append("--check")
		if options.frontend:
			additional.extend(["--frontend", options.frontend])

		# set DBUS_SESSION_BUS_ADDRESS to "" to make dbus work as root ;)
		env = os.environ.copy()
		env.update(DBUS_SESSION_BUS_ADDRESS="")
		cmd = SU_COMMAND.split()
		subprocess.Popen(cmd+["%s --no-listener --shm %ld %ld %ld %s" % (sys.argv[0], mem.key, sig.key, rw.key, " ".join(additional))], env = env, close_fds = False)
		
		get_listener().set_recv(mem, sig, rw)

if __name__ == "__main__":
	main()