* fix 571:

- refactor remove operation for a builder pattern
  - smart remove
    - first write, then remove leftover files
    - don't remove entries from db until necessary
  - tested, but needs more testing to see if it has
    not broken anything
* unremoved stuff:
  - give a warning
  - something's fishy there. what's the deal with all
    the directories that are remnant of removed packages?
This commit is contained in:
Eray Özkural
2005-10-03 10:12:53 +00:00
parent c83fac8f89
commit d1e4858091
2 changed files with 67 additions and 36 deletions
+22 -5
View File
@@ -49,7 +49,7 @@ class Installer:
self.ask_reinstall = ask_reinstall self.ask_reinstall = ask_reinstall
self.check_requirements() self.check_requirements()
self.check_relations() self.check_relations()
self.reinstall() self.check_reinstall()
self.extract_install() self.extract_install()
self.store_pisi_files() self.store_pisi_files()
if ctx.comard: if ctx.comard:
@@ -81,11 +81,12 @@ class Installer:
' not satisfied') ' not satisfied')
raise InstallError("Package not installable") raise InstallError("Package not installable")
def reinstall(self): def check_reinstall(self):
"check reinstall, confirm action, and remove package if reinstall" "check reinstall, confirm action, and schedule reinstall"
pkg = self.pkginfo pkg = self.pkginfo
self.reinstall = False
if ctx.installdb.is_installed(pkg.name): # is this a reinstallation? if ctx.installdb.is_installed(pkg.name): # is this a reinstallation?
(iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name) (iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name)
@@ -130,8 +131,10 @@ class Installer:
if not ctx.ui.confirm(x): if not ctx.ui.confirm(x):
raise InstallError('Package downgrade declined') raise InstallError('Package downgrade declined')
# remove old package then # schedule for reinstall
operations.remove_single(pkg.name) self.old_files = ctx.installdb.files(pkg.name)
self.reinstall = True
operations.run_preremove(pkg.name)
def extract_install(self): def extract_install(self):
"unzip package in place" "unzip package in place"
@@ -139,6 +142,17 @@ class Installer:
ctx.ui.info('Extracting files,') ctx.ui.info('Extracting files,')
self.package.extract_dir_flat('install', ctx.config.destdir) self.package.extract_dir_flat('install', ctx.config.destdir)
if self.reinstall:
# remove left over files
new = set(map(lambda x: str(x.path), self.files.list))
old = set(map(lambda x: str(x.path), self.old_files.list))
leftover = old - new
old_fileinfo = {}
for fileinfo in self.old_files.list:
old_fileinfo[str(fileinfo.path)] = fileinfo
for path in leftover:
operations.remove_file( old_fileinfo[path] )
def store_pisi_files(self): def store_pisi_files(self):
"""put files.xml, metadata.xml, actions.py and COMAR scripts """put files.xml, metadata.xml, actions.py and COMAR scripts
somewhere in the file system. We'll need these in future...""" somewhere in the file system. We'll need these in future..."""
@@ -179,6 +193,9 @@ class Installer:
def update_databases(self): def update_databases(self):
"update databases" "update databases"
if self.reinstall:
operations.remove_db(self.metadata.package.name)
# installdb # installdb
ctx.installdb.install(self.metadata.package.name, ctx.installdb.install(self.metadata.package.name,
self.metadata.package.version, self.metadata.package.version,
+42 -28
View File
@@ -21,6 +21,45 @@ from pisi.uri import URI
# single package operations # single package operations
# remove stuff
def remove_file(fileinfo):
fpath = os.path.join(ctx.config.destdir, fileinfo.path)
# TODO: We have to store configuration files for futher
# usage. Currently we'are doing it like rpm does, saving
# with a prefix and leaving the user to edit it. In the future
# we'll have a plan for these configuration files.
if fileinfo.type == ctx.const.conf:
if os.path.isfile(fpath):
os.rename(fpath, fpath + ".pisi")
else:
# check if file is removed manually.
# And we don't remove directories!
# TODO: remove directory if there is nothing under it?
if os.path.isfile(fpath) or os.path.islink(fpath):
os.unlink(fpath)
else:
ctx.ui.warning('Not removing non-file, non-link %d' % fpath)
def run_preremove(package_name):
if ctx.comard:
com = ctx.comard
# TODO: run preremove scripts...
# com.call("System.Package", "preremove")
com.remove(package_name)
while 1:
reply = com.read_cmd()
if reply[0] == com.RESULT:
break
elif reply[1] == com.ERROR:
raise Error, "COMAR.remove failed!"
def remove_db(package_name):
ctx.installdb.remove(package_name)
packagedb.remove_package(package_name) #FIXME: this looks like a mistake!
def remove_single(package_name): def remove_single(package_name):
"""Remove a single package""" """Remove a single package"""
inst_packagedb = packagedb.inst_packagedb inst_packagedb = packagedb.inst_packagedb
@@ -31,38 +70,13 @@ def remove_single(package_name):
if not ctx.installdb.is_installed(package_name): if not ctx.installdb.is_installed(package_name):
raise Exception('Trying to remove nonexistent package ' raise Exception('Trying to remove nonexistent package '
+ package_name) + package_name)
if ctx.comard:
com = ctx.comard
# TODO: run preremove scripts... run_preremove(package_name)
# com.call("System.Package", "preremove")
com.remove(package_name)
while 1:
reply = com.read_cmd()
if reply[0] == com.RESULT:
break
elif reply[1] == com.ERROR:
raise Error, "COMAR.remove failed!"
for fileinfo in ctx.installdb.files(package_name).list: for fileinfo in ctx.installdb.files(package_name).list:
fpath = os.path.join(ctx.config.destdir, fileinfo.path) remove_file(fileinfo)
# TODO: We have to store configuration files for futher
# usage. Currently we'are doing it like rpm does, saving
# with a prefix and leaving the user to edit it. In the future
# we'll have a plan for these configuration files.
if fileinfo.type == ctx.const.conf:
if os.path.isfile(fpath):
os.rename(fpath, fpath + ".pisi")
else:
# check if file is removed manually.
# And we don't remove directories!
# FIXME: should give a warning if it is...
if os.path.isfile(fpath) or os.path.islink(fpath):
os.unlink(fpath)
remove_db(package_name)
ctx.installdb.remove(package_name)
packagedb.remove_package(package_name)
def install_single(pkg, upgrade = False): def install_single(pkg, upgrade = False):
"""install a single package from URI or ID""" """install a single package from URI or ID"""