From 94f0c281a22d4614d62f352896d16d0e691bec76 Mon Sep 17 00:00:00 2001 From: Anders Blomdell <anders.blomdell@control.lth.se> Date: Mon, 8 Sep 2008 10:08:11 +0100 Subject: [PATCH] Version 2008-09-08 11:08 --- src/mio/exception.py | 7 +++ src/mio/installer.py | 58 ++++++++++++++++++- src/mio/log.py | 6 +- src/mio/node.py | 135 +++++++++++++++++++++++++++---------------- src/mio/parser.py | 3 + 5 files changed, 157 insertions(+), 52 deletions(-) diff --git a/src/mio/exception.py b/src/mio/exception.py index b831988..bb0ff40 100755 --- a/src/mio/exception.py +++ b/src/mio/exception.py @@ -53,6 +53,13 @@ class GroupException(InstallerException): self.value_1 = "'%s'" % (decl_1.decl.group[0:] or "") self.value_2 = "'%s'" % (decl_2.decl.group[0:] or "") +class DeleteException(InstallerException): + def __init__(self, decl_1, decl_2): + self._1 = decl_1 + self._2 = decl_2 + self.value_1 = "'%s'" % (decl_1.delete) + self.value_2 = "'%s'" % (decl_2.delete) + class TargetException(MioException): def __init__(self, group_1, group_2): only_in_1 = [] diff --git a/src/mio/installer.py b/src/mio/installer.py index 01978d2..f83ad4f 100755 --- a/src/mio/installer.py +++ b/src/mio/installer.py @@ -29,6 +29,61 @@ class Installer: else: chain = list(chain) chain.append(group) + for node in g._children: + if node._tag == 'description': + pass + + elif node._tag == 'dependency': + # Dependencies are handled after everything else + pass + + elif node._tag == 'pre': + if node.command[0]: + group.add_pre(command_node(node)) + if node.script[0]: + group.add_pre(script_node(node)) + + elif node._tag == 'post': + if node.command[0]: + group.add_post(command_node(node)) + if node.script[0]: + group.add_post(script_node(node)) + + elif node._tag == 'rpm': + rpm = rpm_node(node.name[0], node, group) + if rpm in exclude: + mio.log.log(CHATTY, + "excluding rpm '%s'" % node.name[0]) + else: + group.add_rpm(rpm) + + elif node._tag == 'dir': + dir = dir_node(node.name[0], node, group) + if dir in exclude: + mio.log.log(CHATTY, + "excluding dir '%s'" % node.name[0]) + else: + group.add_dir(dir) + + elif node._tag == 'symlink': + symlink = symlink_node(node.name[0], node, group) + if symlink in exclude: + mio.log.log(CHATTY, + "excluding symlink '%s'" % node.name[0]) + else: + group.add_symlink(symlink) + + elif node._tag == 'file': + file = file_node(node.name[0], node, group) + if file in exclude: + mio.log.log(CHATTY, + "excluding file '%s'" % node.name[0]) + else: + group.add_file(file) + + else: + raise Exception("unknown tag '%s'" % node._tag) + """ for a in g._pre_: # Add pre actions if a.command[0]: @@ -75,7 +130,8 @@ class Installer: mio.log.log(CHATTY, "excluding file '%s'" % target.name[0]) else: group.add_file(file) - + """ + if group in self.group: (old_group, old_chain) = self.group[group][0] try: diff --git a/src/mio/log.py b/src/mio/log.py index 6c80a06..e1d7e7c 100755 --- a/src/mio/log.py +++ b/src/mio/log.py @@ -1,3 +1,5 @@ +import sys + MUTE=0 SILENT=1 NORMAL=2 @@ -12,7 +14,9 @@ def set_verbosity(level): def log(level, *message): if verbosity >= level: - print " ".join(message) + sys.stderr.write(" ".join(message)) + sys.stderr.write("\n") + sys.stderr.flush() def declaration(node): try: diff --git a/src/mio/node.py b/src/mio/node.py index 86d67dc..fe77351 100755 --- a/src/mio/node.py +++ b/src/mio/node.py @@ -1,14 +1,24 @@ import mio.exception import mio.filecache import mio.util -import os.path +import errno +import os import sha import shutil +import tempfile from mio.exception import * from mio.log import log, declaration, SILENT, NORMAL, VERBOSE - +def parse_boolean(value): + if value == None: + return False + if value.upper() == 'YES' or value.upper() == 'TRUE': + return True + if value.upper() == 'NO' or value.upper() == 'FALSE': + return False + raise Exception("yes, no, true or false expected (not '%s')" % value) + class target_node: def __init__(self, kind, name, decl, group): assert name != None @@ -53,7 +63,6 @@ class target_node: self.is_installed = True self.do_install(prefix, backup) - def test(self, prefix): if self.trigged(prefix) and not self.is_tested: self.is_tested = True @@ -96,6 +105,9 @@ class group_node(target_node): def add_post(self, post): self.post.append(post) + def add_post(self, post): + self.post.append(post) + def do_trig(self, prefix): for t in self.target: if t.trigged(prefix): @@ -217,6 +229,7 @@ class file_node(target_node): self.mode = mio.util.filemode(decl) self.uid = mio.util.uid(decl) self.gid = mio.util.gid(decl) + self.delete = parse_boolean(self.decl.delete[0]) def assert_identical(self, other): if self.__cmp__(other) != 0: @@ -227,8 +240,10 @@ class file_node(target_node): raise SourceException(self, other) if self.uid != other.uid: raise OwnerException(self, other) - if self.gid!= other.gid: + if self.gid != other.gid: raise GroupException(self, other) + if self.delete != other.delete: + raise DeleteException(self, other) def digest(self, name): f = open(name) @@ -240,53 +255,56 @@ class file_node(target_node): result = False dir = os.path.dirname(self.decl._url) self.target = mio.filecache.locatefile([prefix, self.decl.name[0]]) - if self.decl.source[0] != "": - file = self.decl.source[0] or self.decl.name[0] - self.source = mio.filecache.loadfile([dir, - self.decl.files[0:], - file]) - source_sum = self.digest(self.source) - try: - target_sum = self.digest(self.target) - except: - target_sum = None - - if os.path.islink(self.target): - if self.decl.force[0] == 'yes': - self.action.append(self.unlink) + if self.delete: + if os.path.exists(self.target): + if os.path.islink(self.target): + raise Exception("%s is a link" % self.target) + elif not os.path.isfile(self.target): + raise Exception("%s is not a file" % self.target) + self.action.append(self.unlink) + result = True + else: + if self.decl.source[0] != "": + file = self.decl.source[0] or self.decl.name[0] + self.source = mio.filecache.loadfile([dir, + self.decl.files[0:], + file]) + source_sum = self.digest(self.source) + try: + target_sum = self.digest(self.target) + except: + target_sum = None + + if os.path.islink(self.target): + if parse_boolean(self.decl.force[0]): + self.action.append(self.unlink) + self.action.append(self.copy) + return True + else: + raise Exception("%s is a link" % self.target) + + if source_sum != target_sum: self.action.append(self.copy) - self.action.append(self.chown) - self.action.append(self.chmod) - self.action.append(self.mtime) return True - else: - raise Exception("%s is a link" % self.target) - - if source_sum != target_sum: - self.action.append(self.copy) + + tstat = os.stat(self.target) + sstat = os.stat(self.source) + if tstat.st_mtime != sstat.st_mtime: + result = True + self.action.append(self.mtime) + else: + # No source file, we will only set owner and mode + tstat = os.stat(self.target) + + + if self.uid != tstat.st_uid or self.gid != tstat.st_gid: + result = True self.action.append(self.chown) - self.action.append(self.chmod) - self.action.append(self.mtime) - return True - - tstat = os.stat(self.target) - sstat = os.stat(self.source) - if tstat.st_mtime != sstat.st_mtime: + + if self.mode != (tstat.st_mode & 07777): result = True - self.action.append(self.mtime) - else: - # No surce file, we will only set owner and mode - tstat = os.stat(self.target) + self.action.append(self.chmod) - - if self.uid != tstat.st_uid or self.gid != tstat.st_gid: - result = True - self.action.append(self.chown) - - if self.mode != (tstat.st_mode & 07777): - result = True - self.action.append(self.chmod) - return result @@ -308,6 +326,7 @@ class file_node(target_node): mio.exception.Report(e, self.decl, a) def unlink(self, backup): + # TODO: backup here? os.unlink(self.target) def copy(self, backup): @@ -327,10 +346,27 @@ class file_node(target_node): dirmode = mio.util.dirmode(self.decl._parent) os.makedirs(dir, dirmode) - # Copy file - shutil.copyfile(self.source, self.target) - + # Copy file to a temporary file + (fd, target) = tempfile.mkstemp( + dir=os.path.dirname(self.target), + prefix=os.path.basename(self.target) + '.') + os.close(fd) + shutil.copyfile(self.source, target) + # Change owner, mode and date on temporary + os.chown(target, self.uid, self.gid) + os.chmod(target, self.mode) + stat = os.stat(self.source) + os.utime(target, (stat.st_atime, stat.st_mtime)) + # Replace target with temporary file + try: + os.unlink(self.target) + except: + pass + os.link(target, self.target) + os.unlink(target) + def chmod(self, backup): + # Change mode os.chmod(self.target, self.mode) def chown(self, backup): @@ -342,7 +378,6 @@ class file_node(target_node): stat = os.stat(self.source) os.utime(self.target, (stat.st_atime, stat.st_mtime)) - class symlink_node(target_node): def __init__(self, name, decl=None, group=None): target_node.__init__(self, 'symlink', name, decl, group) diff --git a/src/mio/parser.py b/src/mio/parser.py index 8be620b..be97647 100755 --- a/src/mio/parser.py +++ b/src/mio/parser.py @@ -421,6 +421,9 @@ class Node: child._parent = self self._children.append(child) + def __repr__(self): + return self._xml() + class Parser(xml.sax.ContentHandler): def __init__(self, url): -- GitLab