[SCM] GUI front-end for Debian Live. branch, master, updated. 72023d3200637edc6b81b8cc8d240b376a0d14df
Chris Lamb
chris at chris-lamb.co.uk
Wed Jul 9 23:14:01 UTC 2008
The following commit has been merged in the master branch:
commit c4bf2b42dbd1abf975d723e498f48a44b1653f5f
Author: Chris Lamb <chris at chris-lamb.co.uk>
Date: Wed Jul 9 23:54:05 2008 +0100
Add support for the entire build window running as root, chown-ing the build contents post-build, etc.
Signed-off-by: Chris Lamb <chris at chris-lamb.co.uk>
diff --git a/LiveMagic/__init__.py b/LiveMagic/__init__.py
index 7f60e50..ed5d1d9 100644
--- a/LiveMagic/__init__.py
+++ b/LiveMagic/__init__.py
@@ -17,13 +17,22 @@ class LiveMagic(object):
except RuntimeError, e:
sys.exit('E: %s. Exiting.' % e)
- optparser = optparse.OptionParser(version=__version__)
- _, args = optparser.parse_args()
-
- c = controllers.Controller(args)
+ parser = optparse.OptionParser(version=__version__)
+ parser.add_option('--build-for', dest='build_for',
+ metavar='owner:group', help="Perform build on behalf of owner:group. "
+ "This option is used internally.")
+ parser.add_option('--kde-full-session', dest='kde_full_session',
+ metavar='', help="Value of KDE_FULL_SESSION. "
+ "This option is used internally.")
+ parser.add_option('--gnome-desktop-session-id', dest='gnome_desktop_session_id',
+ metavar='', help="Value of GNOME_DESKTOP_SESSION_ID. "
+ "This option is used internally.")
+ options, args = parser.parse_args()
+
+ c = controllers.Controller()
v = views.View(c)
- c.ready()
+ c.ready(options, args)
gtk.gdk.threads_init()
gtk.main()
diff --git a/LiveMagic/controllers/__init__.py b/LiveMagic/controllers/__init__.py
index b999b85..a469efa 100644
--- a/LiveMagic/controllers/__init__.py
+++ b/LiveMagic/controllers/__init__.py
@@ -4,10 +4,10 @@ from hooks import HooksController as Hooks
from wizard import WizardController as Wizard
class Controller(Main, Build, Hooks, Wizard):
- def __init__(self, args):
+ def __init__(self):
self.model = None
- Main.__init__(self, args)
+ Main.__init__(self)
Build.__init__(self)
Hooks.__init__(self)
Wizard.__init__(self)
diff --git a/LiveMagic/controllers/build.py b/LiveMagic/controllers/build.py
index 0442b7a..f773fed 100644
--- a/LiveMagic/controllers/build.py
+++ b/LiveMagic/controllers/build.py
@@ -1,28 +1,27 @@
import os
+import pwd
import sys
import shutil
import gobject
import subprocess
-BUILDING, CANCELLED, CANCELLED_CLEAN, GKSU_ERROR, FAILED, \
- FAILED_CLEAN, OK, OK_CLEAN, DONE = range(9)
+BUILDING, CANCELLED, CANCELLED_CLEAN, FAILED, \
+ FAILED_CLEAN, OK, OK_CLEAN, DONE = range(8)
from LiveMagic.utils import find_resource
class BuildController(object):
- # GTK callbacks
-
- def on_build_activate(self, *_):
- # Save model if necessary
- if self.model.altered():
- self.model.save()
- self.do_show_build_window(self.set_window_main_sensitive)
-
def do_show_build_window(self, build_close_callback):
self.state = BUILDING
self.build_successful = False
+ self.uid, self.gid = [int(x) for x in self.options.build_for.split(':', 2)]
+
+ f = open(os.path.join(os.getcwd(), 'build-log.txt'), 'w')
+ f.write('I: live-magic respawned as root')
+ f.close()
+
# Set initial titles and state
self.view.set_build_status_change(initial=True)
@@ -30,11 +29,11 @@ class BuildController(object):
self.view.do_show_window_build(build_close_callback)
# Start pulsing
- gobject.timeout_add(100, self.do_pulse_cb)
+ gobject.timeout_add(80, self.do_pulse_cb)
# Fork command
- cmd = ['/usr/bin/gksu', '--', find_resource('live-magic-builder')]
- self.pid = self.view.vte_terminal.fork_command(cmd[0], cmd, None, self.model.dir)
+ cmd = [find_resource('live-magic-builder')]
+ self.pid = self.view.vte_terminal.fork_command(cmd[0], cmd, None, os.getcwd())
if self.pid < 0:
self.view.set_build_titles("Error creating Debian Live system!", \
@@ -48,12 +47,11 @@ class BuildController(object):
return True
def on_vte_child_exited(self, *_):
- self.pid = -1
- status_filename = os.path.join(self.model.dir, '.status')
+ status_filename = os.path.join(os.getcwd(), '.status')
def _exec(*cmds):
args = ['/bin/sh', '-c', '; '.join(cmds)]
- self.view.vte_terminal.fork_command(args[0], args, None, self.model.dir)
+ self.view.vte_terminal.fork_command(args[0], args, None, os.getcwd())
def set_cleaning_status():
os.remove(status_filename)
@@ -64,13 +62,21 @@ class BuildController(object):
def ok():
self.view.set_build_titles("Build process finished",
"Your Debian Live system has been created successfully.")
- subprocess.call(['xdg-open', '%s' % self.model.dir])
+
+ if self.options.kde_full_session != '-':
+ os.environ['KDE_FULL_SESSION'] = self.options.kde_full_session
+ if self.options.gnome_desktop_session_id != '-':
+ os.environ['GNOME_DESKTOP_SESSION_ID'] = self.options.gnome_desktop_session_id
+
+ cmd = ['su', pwd.getpwuid(self.uid)[0], '-c', 'xdg-open .']
+ subprocess.call(cmd)
return DONE
def ok_clean():
set_cleaning_status()
- _exec('lh_clean --chroot --stage --source --cache', 'rm -rf config/ binary/', \
- 'gzip build-log.txt')
+ _exec('lh_clean --chroot --stage --source --cache',
+ 'rm -rf config/ binary/',
+ 'chown -R %d:%d .' % (self.uid, self.gid))
return OK
def failed():
@@ -80,7 +86,8 @@ class BuildController(object):
def failed_clean():
set_cleaning_status()
- _exec('lh_clean --purge', 'rm -rf config/', 'gzip-build.log.txt')
+ _exec('lh_clean --purge', 'rm -rf config/',
+ 'chown -R . %d:%d' % (self.uid, self.gid))
return FAILED
def cancelled():
@@ -93,12 +100,6 @@ class BuildController(object):
_exec('lh_clean --purge', 'rm -rf $(pwd)')
return CANCELLED
- def gksu_error():
- self.view.set_build_titles("Error gaining superuser priviledges",
- "There was an error when trying to gain superuser priviledges.")
- shutil.rmtree(self.model.dir)
- return DONE
-
if self.state == BUILDING:
self.state = FAILED_CLEAN
try:
@@ -110,20 +111,20 @@ class BuildController(object):
finally:
f.close()
except:
- self.state = GKSU_ERROR
+ pass
self.state = {
CANCELLED: cancelled,
CANCELLED_CLEAN: cancelled_clean,
FAILED: failed,
FAILED_CLEAN: failed_clean,
- GKSU_ERROR: gksu_error,
OK: ok,
OK_CLEAN: ok_clean,
}[self.state]()
if self.state == DONE:
self.view.set_build_status_change(initial=False)
+ self.pid = -1
# Auto-close if requested
if self.view.get_build_auto_close() and self.build_successful:
@@ -139,4 +140,4 @@ class BuildController(object):
def on_button_build_cancel_clicked(self, *_):
self.state = CANCELLED_CLEAN
- subprocess.call(['gksu', '--', '/bin/kill', '-s', 'KILL', '-%d' % self.pid])
+ subprocess.call(['/bin/kill', '-s', 'KILL', '-%d' % self.pid])
diff --git a/LiveMagic/controllers/main.py b/LiveMagic/controllers/main.py
index 7dfe51d..5584873 100644
--- a/LiveMagic/controllers/main.py
+++ b/LiveMagic/controllers/main.py
@@ -1,89 +1,22 @@
+import os
import gtk
-
-import commands
+import sys
class MainController(object):
- def __init__(self, args):
- #self.model.attach_load_observer(self.notify_load)
- self.args = args
-
- def ready(self):
- sections = ('common', 'chroot', 'binary', 'bootstrap', 'source', 'hooks')
- self.view.setup_sections(sections)
-
- # Notify all the observers that depend on the model
- if len(self.args) == 0:
- self.view.do_show_wizard()
- else:
- self.view.do_show_main_window()
- self.model.notify_load_observers()
-
- # GTK callbacks
- def on_live_helper_value_changed(self, widget):
- namespace, key = widget.name.split("/")
- value = widget.get_text()
-
- # Call self.model.namespace.key = vaulue
- ns = getattr(self.model, namespace)
- setattr(ns, key, value)
-
- # Variables have been tainted, allow saving
- self.view.set_save_enabled(True)
- def on_choose_section(self, button):
- self.view.do_select_section(button)
+ def ready(self, options, args):
+ self.options = options
- def on_new(self, *_):
- if self.model.altered():
- print "Not newing as not saved"
+ if options.build_for:
+ self.do_show_build_window(lambda: gtk.main_quit())
else:
- self.model.new()
- self.view.set_save_enabled(True)
-
- def on_open(self, *_):
- def open_dialog(self):
- res, filename = self.view.do_folder_open()
- if res == gtk.RESPONSE_ACCEPT:
- try:
- self.model.open(filename)
- self.view.set_save_enabled(False)
- except IOError:
- self.view.do_show_loading_error()
- return self._confirm_save(lambda: open_dialog(self), quit_dialog=False)
-
- def on_save(self, *_):
- self.view.set_save_enabled(False)
- self.view.set_status_bar("Saving configuration to %s ..." % self.model.dir)
- self.model.save()
- self.view.set_status_bar("Saved configuration to %s" % self.model.dir)
-
- def on_save_as(self, *_):
- raise NotImplemented
-
- def _confirm_save(self, fn, **kw):
- if self.model.altered():
- res = self.view.do_confirm_save(**kw)
- if res == gtk.RESPONSE_ACCEPT: # Save
- self.on_save(None)
- fn()
- elif res == gtk.RESPONSE_REJECT: # Don't save
- fn()
- else:
- return True # Cancel
- else:
- # We are up to date
- fn()
+ self.view.do_show_wizard()
def on_quit_request(self, *_):
return self._confirm_save(lambda: gtk.main_quit(), quit_dialog=True)
- def on_about_activate(self, *_):
- self.view.do_show_about_dialog()
-
- def set_window_main_sensitive(self):
- self.view.do_show_main_window(True)
-
def get_host_architecture(self):
+ import commands
status, output = commands.getstatusoutput('dpkg --print-architecture')
assert status == 0
return output
diff --git a/LiveMagic/controllers/wizard.py b/LiveMagic/controllers/wizard.py
index 9e4fd23..454400d 100644
--- a/LiveMagic/controllers/wizard.py
+++ b/LiveMagic/controllers/wizard.py
@@ -1,17 +1,23 @@
+import os
import gtk
-import os.path
+import time
+import popen2
+import shutil
+import threading
+import subprocess
-from DebianLive import Config, utils
+from LiveMagic import utils
+from DebianLive import Config
+from DebianLive.utils import SourcesList, get_build_dir
class WizardController(object):
-
def on_wizard_apply(self, _):
- build_dir = utils.get_build_dir()
+ build_dir = get_build_dir()
data = self.view.get_wizard_completed_details()
# Use cdebootstrap in some situations
if os.path.exists('/usr/bin/cdebootstrap') and \
- data['distribution' in ('etch', 'lenny'):
+ data['distribution'] in ('etch', 'lenny'):
data['bootstrap'] = 'cdebootstrap'
# Disabling caching
@@ -21,15 +27,39 @@ class WizardController(object):
self.model = Config(build_dir, **data)
self.view.do_dim_wizard()
- self.do_show_build_window(lambda: gtk.main_quit())
- def on_wizard_expert_mode_selected(self, _):
- self.view.do_hide_wizard()
- self.view.do_show_main_window()
+ os.chdir(build_dir)
+ build_for = '%d:%d' % (os.geteuid(), os.getegid())
+
+ def gain_superuser():
+ title = "Enter your password to continue"
+ text = "Live-magic requires superuser capabilities to build your Debian Live system."
+
+ for _ in range(3):
+ cmd = ['gksu', '--disable-grab', '--preserve-env',
+ '--message', '<big><b>%s</b></big>\n\n%s' % (title, text), '--',
+ utils.find_resource('live-magic'), '--build-for', build_for,
+ '--kde-full-session', os.environ.get('KDE_FULL_SESSION', '-'),
+ '--gnome-desktop-session-id', os.environ.get('GNOME_DESKTOP_SESSION_ID', '-')]
+ p = subprocess.Popen(cmd)
+
+ os.waitpid(p.pid, 0)
+ try:
+ os.stat(os.path.join(self.model.dir, 'build-log.txt'))
+ gtk.main_quit()
+ return
+ except:
+ pass
+
+ self.view.do_undim_wizard()
+ os.chdir('..')
+ shutil.rmtree(self.model.dir)
+
+ threading.Thread(target=gain_superuser).start()
def get_suggested_mirror(self):
- s = utils.SourcesList()
- return s.get_mirror()
+ return SourcesList().get_mirror()
def on_wizard_cancel(self, *args):
if self.view.do_show_wizard_cancel_confirm_window():
+ gtk.main_quit()
diff --git a/LiveMagic/utils.py b/LiveMagic/utils.py
index b192eb5..d996cb7 100644
--- a/LiveMagic/utils.py
+++ b/LiveMagic/utils.py
@@ -3,6 +3,7 @@ import os
def find_resource(resource):
dirs = (
os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'misc'),
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
'/usr/share/live-magic',
'/usr/local/share/live-magic',
)
diff --git a/LiveMagic/views/__init__.py b/LiveMagic/views/__init__.py
index 19346b3..3353670 100644
--- a/LiveMagic/views/__init__.py
+++ b/LiveMagic/views/__init__.py
@@ -11,7 +11,7 @@ class View(Main, Build, Hooks, Wizard):
def __init__(self, controller):
self.controller = controller
- self.xml = gtk.glade.XML(find_resource('main.glade'))
+ self.xml = gtk.glade.XML(find_resource('live-magic.glade'))
self.xml.signal_autoconnect(self.controller)
Main.__init__(self)
diff --git a/LiveMagic/views/wizard.py b/LiveMagic/views/wizard.py
index 7a73c71..0ae89ef 100644
--- a/LiveMagic/views/wizard.py
+++ b/LiveMagic/views/wizard.py
@@ -60,6 +60,9 @@ class WizardView(object):
def do_dim_wizard(self):
self.asst.set_sensitive(False)
+ def do_undim_wizard(self):
+ self.asst.set_sensitive(True)
+
def do_hide_wizard(self):
self.asst.hide()
diff --git a/TODO b/TODO
index d7cf67f..61b34d1 100644
--- a/TODO
+++ b/TODO
@@ -6,10 +6,6 @@ Release blockers
* Build process needs to be cancellable
- * Password entry problems
- - Run the entire "build" process as root, passing original uid/gid
- as arguments so that results can be used by the original user.
-
* Ability to select location of build in the wizard
Other
--
GUI front-end for Debian Live.
More information about the debian-live-changes
mailing list