[PATCH] Deal gracefully with repeated uploads of the same package.

Serafeim Zanikolas serzan at hellug.gr
Wed Feb 25 01:33:34 CET 2009


---
 bin/debexpo-importer |   64 +++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/bin/debexpo-importer b/bin/debexpo-importer
index b9b6382..d9c4bcb 100755
--- a/bin/debexpo-importer
+++ b/bin/debexpo-importer
@@ -40,6 +40,7 @@ from optparse import OptionParser
 import ConfigParser
 from datetime import datetime
 from debian_bundle import deb822
+from glob import glob
 import logging
 import logging.config
 import os
@@ -47,6 +48,7 @@ import re
 import sys
 import shutil
 from stat import *
+from tempfile import mkdtemp
 
 from sqlalchemy import exceptions
 
@@ -79,6 +81,8 @@ class Importer(object):
         self.user_id = user_id
         self.changes = None
         self.user = None
+        self.prev_upload_dir = None
+        self.files = None
 
     def _remove_changes(self):
         """
@@ -90,7 +94,7 @@ class Importer(object):
         """
         Removes all the files uploaded.
         """
-        if hasattr(self, 'files'):
+        if self.files is not None:
             for file in self.files:
                 if os.path.exists(file):
                     os.remove(file)
@@ -246,13 +250,49 @@ class Importer(object):
         # Get uploader's User object
         self.user = meta.session.query(User).filter_by(id=self.user_id).filter_by(verification=None).first()
         if self.user is None:
+            # Before giving up, restore the previous upload's files.
+            if self.prev_upload_dir is not None:
+                incoming_dir = self.config['debexpo.upload.incoming']
+                for file in glob(os.path.join("self.prev_upload_dir", "*")):
+                    shutil.move(file, incoming_dir)
             self._fail('Couldn\'t find user with id %s. Exiting.' % self.user_id)
+        else:
+            # Assume the import as successful and delete the previous upload's files.
+            if self.prev_upload_dir is not None:
+                shutil.rmtree(self.prev_upload_dir)
 
         # Check whether package is already in the database
         package_query = meta.session.query(Package).filter_by(name=self.changes['Source'])
-        if package_query.count() is 1:
+        if package_query.count() > 0:
             log.debug('Package %s already exists in the database' % self.changes['Source'])
+            # Delete the relevant BinaryPackage, SourcePackage & PackageFile records
             package = package_query.one()
+
+            bin_packages = meta.session.query(BinaryPackage)\
+                    .filter(BinaryPackage.package_version_id==PackageVersion.id)\
+                    .filter(PackageVersion.package_id==package.id)
+            if bin_packages.count() > 0:
+                log.debug('Deleting %d bin pkg rec(s)' % bin_packages.count())
+                for r in bin_packages.all():
+                    meta.session.delete(r)
+
+            src_packages = meta.session.query(SourcePackage)\
+                    .filter(SourcePackage.package_version_id==PackageVersion.id)\
+                    .filter(PackageVersion.package_id==package.id)
+            if src_packages.count() > 0:
+                log.debug('Deleting %d src pkg rec(s)' % src_packages.count())
+                for r in src_packages.all():
+                    meta.session.delete(r)
+
+            package_files = meta.session.query(PackageFile)\
+                    .filter(PackageFile.binary_package_id==None)\
+                    .filter(PackageFile.source_package_id==None)
+            if package_files.count() > 0:
+                log.debug('Deleting %d pkg file rec(s)' % src_packages.count())
+                for r in package_files.all():
+                    meta.session.delete(r)
+
+            meta.session.flush()
         else:
             log.debug('Package %s is new to the system' % self.changes['Source'])
             package = Package(name=self.changes['Source'], user=self.user)
@@ -426,19 +466,17 @@ class Importer(object):
                 log.debug('Creating directory: %s' % destdir)
                 os.mkdir(destdir)
 
-        # Check whether the files are already present
-        toinstall = []
-        for file in self.files:
-            if os.path.isfile(os.path.join(destdir, file)):
-                if not file.endswith('orig.tar.gz'):
-                    self._reject('File "%s" already exists' % file)
-                else:
-                    log.warning('%s is not being installed as it already exists' % file)
-            else:
-                toinstall.append(file)
+        # Move to prev_upload_dir any files from a previous upload, just in
+        # case this import fails.
+        files = [os.path.join(destdir, file) for file in self.files]
+        previously_uploaded = [file for file in files if os.path.isfile(file)]
+        if previously_uploaded is not []:
+            self.prev_upload_dir = mkdtemp()
+            for file in previously_uploaded:
+                shutil.move(file, self.prev_upload_dir)
 
         # Install files in repository
-        for file in toinstall:
+        for file in self.files:
             shutil.move(file, os.path.join(destdir, file))
 
         # Create the database rows
-- 
1.6.2.1


--huq684BweRXVnRxX--


More information about the debexpo-devel mailing list