diff --git a/bin/isrepo b/bin/isrepo
index ccc0c41f7a0e35f0fc7858aa1238708d97670dfa..e625d4baec23ddfd20a236dfe35807e728e40f61 100755
--- a/bin/isrepo
+++ b/bin/isrepo
@@ -81,10 +81,10 @@ p_add =  subparsers.add_parser("add", help = add.__doc__.lower())
 p_add.add_argument("path")
 p_add.set_defaults(func = add)
 # Del command parser
-#p_del =  subparsers.add_parser("del", help=delete.__doc__.lower())
-#p_del.add_argument("image_name", type=str)
-#p_del.add_argument("image_version", type=str)
-#p_del.set_defaults(func=delete)
+p_del =  subparsers.add_parser("del", help = delete.__doc__.lower())
+p_del.add_argument("image_name")
+p_del.add_argument("image_version")
+p_del.set_defaults(func = delete)
 try:
     # Parse and run
     args = p_main.parse_args()
diff --git a/installsystems/database.py b/installsystems/database.py
index cd78da9357d71cad2f6a4ca7e0480553da8b908b..e7e8f111016ae3684a88756d35172d6b4d317dfb 100644
--- a/installsystems/database.py
+++ b/installsystems/database.py
@@ -50,26 +50,23 @@ class Database(object):
         self.conn = sqlite3.connect(self.path, isolation_level=None)
         self.conn.execute("PRAGMA foreign_keys = ON")
 
-    def get(self, name, version):
-        '''Return a description dict from a image name'''
-        # parse tarball
-        try:
-            self.file.seek(0)
-            tarball = Tarball.open(fileobj=self.file, mode="r:gz")
-            rdata = tarball.get_str("%s-%s" % (name, version))
-            tarball.close()
-        except KeyError:
-            raise Exception("No image %s version %s in metadata" % (name, version))
-        except Exception as e:
-            raise Exception("Unable to read db %s version %s: %s" % (name, version, e))
-        # convert loaded data into dict (json parser)
-        try:
-            return json.loads(rdata)
-        except Exception as e:
-            raise Exception("Invalid metadata in image %s version %s: e" % (name, version, e))
+    def begin(self):
+        '''
+        Start a db transaction
+        '''
+        self.conn.execute("BEGIN TRANSACTION")
+
+    def commit(self):
+        '''
+        Commit current db transaction
+        '''
+        self.conn.execute("COMMIT TRANSACTION")
+
 
     def ask(self, sql, args=()):
-        '''Ask question to db'''
+        '''
+        Ask question to db
+        '''
         return self.conn.execute(sql, args)
 
     def add(self, image):
@@ -81,7 +78,7 @@ class Database(object):
             self.conn.execute("BEGIN TRANSACTION")
             # insert image information
             arrow("Add image metadata")
-            self.conn.execute("INSERT OR REPLACE INTO image values (?,?,?,?,?,?,?)",
+            self.conn.execute("INSERT INTO image values (?,?,?,?,?,?,?)",
                               (image.md5,
                                image.name,
                                image.version,
@@ -93,7 +90,7 @@ class Database(object):
             # insert data informations
             arrow("Add payload metadata")
             for name, obj in image.payload.items():
-                self.conn.execute("INSERT OR REPLACE INTO payload values (?,?,?,?,?)",
+                self.conn.execute("INSERT INTO payload values (?,?,?,?,?)",
                                   (obj.md5,
                                    image.md5,
                                    name,
@@ -106,25 +103,3 @@ class Database(object):
             arrowlevel(-1)
         except Exception as e:
             raise Exception("Adding metadata fail: %s" % e)
-
-    def delete(self, name, version):
-        '''Delete a packaged image'''
-        arrow("Removing metadata from db")
-        # check locality
-        if istools.pathtype(self.path) != "file":
-            raise NotImplementedError("Database deletion must be local")
-        newdb_path = "%s.new" % self.path
-        fname = "%s-%s.json" % (name, version)
-        try:
-            db = Tarball.open(self.path, mode='r:gz')
-            newdb = Tarball.open(newdb_path, mode='w:gz')
-            for ti in db.getmembers():
-                if ti.name != fname:
-                    newdb.addfile(ti, db.extractfile(ti))
-            db.close()
-            newdb.close()
-            # preserve permission and stats when moving
-            shutil.copystat(self.path, newdb_path)
-            os.rename(newdb_path, self.path)
-        except Exception as e:
-            raise Exception("Removing metadata fail: %s" % e)
diff --git a/installsystems/printer.py b/installsystems/printer.py
index 8f40c1afdb67a41b78431f81023635f8d14719c4..1ee21a62addc2fa602da5edbb99dea4f919e8dec 100644
--- a/installsystems/printer.py
+++ b/installsystems/printer.py
@@ -70,7 +70,7 @@ def debug(message, fd=sys.stderr, endl=os.linesep):
     if installsystems.debug:
         out("#light##black#%s#reset#" % message, fd, endl)
 
-def arrowlevel(inc=None,level=None):
+def arrowlevel(inc=None, level=None):
     global _arrow_level
     old_level = _arrow_level
     if level is not None:
@@ -79,12 +79,11 @@ def arrowlevel(inc=None,level=None):
         _arrow_level = max(1, min(4, _arrow_level + inc))
     return old_level
 
-def arrow(message, level=None, fd=sys.stdout, endl=os.linesep):
+def arrow(message, inclevel=None, level=None, fd=sys.stdout, endl=os.linesep):
     if installsystems.quiet:
         return
-    # set a one shot level
-    if level is not None:
-        old_level = arrowlevel(level=level)
+    # define new level
+    old_level = arrowlevel(inc=inclevel, level=level)
     if _arrow_level == 1:
         out("#light##red#=>#reset# %s" % message)
     elif _arrow_level == 2:
@@ -94,5 +93,4 @@ def arrow(message, level=None, fd=sys.stdout, endl=os.linesep):
     elif _arrow_level == 4:
         out("  #light##green#=>#reset# %s" % message)
     # restore old on one shot level
-    if level is not None:
-        arrowlevel(level=old_level)
+    arrowlevel(level = old_level)
diff --git a/installsystems/repository.py b/installsystems/repository.py
index e6ee69e34cd25115edf9f68f56a1f16aaa2e10fb..7baa8a506e15c3aaa983064b8e5b757e2e5f4269 100644
--- a/installsystems/repository.py
+++ b/installsystems/repository.py
@@ -31,10 +31,12 @@ class Repository(object):
 
     @classmethod
     def create(cls, config):
-        '''Create an empty base repository'''
+        '''
+        Create an empty base repository
+        '''
         # check local repository
         if istools.pathtype(config.path) != "file":
-            raise NotImplementedError("Repository creation must be local")
+            raise Exception("Repository creation must be local")
         # create base directories
         arrow("Creating base directories")
         arrowlevel(1)
@@ -58,10 +60,12 @@ class Repository(object):
         return self
 
     def update_last(self):
-        '''Update last file to current time'''
+        '''
+        Update last file to current time
+        '''
         # check local repository
         if istools.pathtype(self.config.path) != "file":
-            raise NotImplementedError("Repository addition must be local")
+            raise Exception("Repository addition must be local")
         try:
             arrow("Updating last file")
             last_path = os.path.join(self.config.path, self.config.lastname)
@@ -71,7 +75,9 @@ class Repository(object):
             raise Exception("Update last file failed: %s" % e)
 
     def last(self):
-        '''Return the last value'''
+        '''
+        Return the last value
+        '''
         try:
             last_path = os.path.join(config.path, config.lastname)
             return int(istools.uopen(last_path, "r").read().rstrip())
@@ -80,10 +86,15 @@ class Repository(object):
         return 0
 
     def add(self, image):
-        '''Add a packaged image to repository'''
+        '''
+        Add a packaged image to repository
+        '''
         # check local repository
         if istools.pathtype(self.config.path) != "file":
-            raise NotImplementedError("Repository addition must be local")
+            raise Exception("Repository addition must be local")
+        # cannot add already existant image
+        if self.has(image.name, image.version):
+            raise Exception("Image already in database, delete first!")
         # checking data tarballs md5 before copy
         image.check("Check image and payload before copy")
         # adding file to repository
@@ -112,43 +123,60 @@ class Repository(object):
         self.update_last()
 
     def delete(self, name, version):
-        '''Delete an image from repository'''
-        raise NotImplementedError()
+        '''
+        Delete an image from repository
+        '''
         # check local repository
         if istools.pathtype(self.config.path) != "file":
-            raise NotImplementedError("Repository deletion must be local")
-        desc = self.db.find(name, version)
-        if desc is None:
-            error("Unable to find %s version %s in database" % (name, version))
-        # removing script tarballs
-        arrow("Removing script tarball")
-        arrowlevel(1)
-        tpath = os.path.join(self.config.path,
-                             "%s-%s%s" % (name, version, Image.extension))
-        if os.path.exists(tpath):
-            os.unlink(tpath)
-            arrow("%s removed" % os.path.basename(tpath))
+            raise Exception("Repository deletion must be local")
+        # get md5 of files related to images (exception is raised if not exists
+        md5s = self.getmd5(name, version)
+        # cleaning db (must be done before cleaning)
+        arrow("Cleaning database")
+        arrow("Remove payloads from database", 1)
+        self.db.begin()
+        for md5 in md5s[1:]:
+            self.db.ask("DELETE FROM payload WHERE md5 = ? AND image_md5 = ?",
+                        (md5, md5s[0])).fetchone()
+        arrow("Remove image from database", 1)
+        self.db.ask("DELETE FROM image WHERE md5 = ?",
+                        (md5s[0],)).fetchone()
+        self.db.commit()
+        # Removing script image
+        arrow("Removing files from pool")
         arrowlevel(1)
-        # removing data tarballs
-        arrow("Removing data tarballs")
-        arrowlevel(1)
-        for tb in self.db.databalls(name, version):
-            tpath = os.path.join(self.config.data, tb)
-            if os.path.exists(tpath):
-                os.unlink(tpath)
-                arrow("%s removed" % tb)
+        for md5 in md5s:
+            self._remove_file(md5)
         arrowlevel(-1)
-        # removing metadata
-        self.db.delete(name, version)
         # update last file
-        arrow("Updating last file")
         self.update_last()
 
+    def _remove_file(self, filename):
+        '''
+        Remove a filename from pool. Check if it's not needed by db before
+        '''
+        # check existance in table image
+        have = False
+        for table in ("image", "payload"):
+            have = have or  self.db.ask("SELECT md5 FROM %s WHERE md5 = ? LIMIT 1" % table,
+                                        (filename,)).fetchone() is not None
+        # if no reference, delete!
+        if not have:
+            arrow("%s, deleted" % filename)
+            os.unlink(os.path.join(self.config.path, filename))
+        else:
+            arrow("%s, skipped" % filename)
+
     def has(self, name, version):
-        return self.db.ask("select name,version from image where name = ? and version = ? limit 1", (name,version)).fetchone() is not None
+        '''
+        Return the existance of a package
+        '''
+        return self.db.ask("SELECT name,version FROM image WHERE name = ? AND version = ? LIMIT 1", (name,version)).fetchone() is not None
 
     def get(self, name, version):
-        '''return a image from a name and version of pakage'''
+        '''
+        return a image from a name and version
+        '''
         # get file md5 from db
         r = self.db.ask("select md5 from image where name = ? and version = ? limit 1",
                         (name,version)).fetchone()
@@ -156,11 +184,29 @@ class Repository(object):
             raise Exception("No such image %s version %s" % name, version)
         path = os.path.join(self.config.path, r[0])
         debug("Getting %s v%s from %s" % (name, version, path))
-        return PackageImage(path, md5name=True)
+        pkg = PackageImage(path, md5name=True)
+        pkg.md5 = r[0]
+        return pkg
+
+    def getmd5(self, name, version):
+        '''
+        return a image md5 and payload md5 from name and version. Order matter !
+        image md5 will still be the first
+        '''
+        # get file md5 from db
+        a = self.db.ask("SELECT md5 FROM image WHERE name = ? AND version = ? LIMIT 1",
+                        (name,version)).fetchone()
+        if a is None:
+            raise Exception("No such image %s version %s" % name, version)
+        b = self.db.ask("SELECT md5 FROM payload WHERE image_md5 = ?",
+                        (a[0],)).fetchall()
+        return [ a[0] ] + [ x[0] for x in b ]
 
     def last(self, name):
-        '''Return last version of name in repo or -1 if not found'''
-        r = self.db.ask("select version from image where name = ? order by version desc limit 1", (name,)).fetchone()
+        '''
+        Return last version of name in repo or -1 if not found
+        '''
+        r = self.db.ask("SELECT version FROM image WHERE name = ? ORDER BY version DESC LIMIT 1", (name,)).fetchone()
         # no row => no way
         if r is None:
             return -1