There are changes on code, that handles the internal and remote database.
return pkgs
- def repo_create(self, path):
+ def repo_create(self, path, input_paths):
if not os.path.exists(path) or not os.path.isdir(path):
raise PakfireError, "Given path is not existant or not a directory: %s" % path
- repo = repository.RemoteRepository(
+ repo = repository.LocalRepository(
self,
name="new",
description="New repository.",
- url="file://%s" % path,
- gpgkey="XXX",
- enabled=True,
+ path=path,
)
- repo.save_index()
+ for input_path in input_paths:
+ repo._collect_packages(input_path)
sub_create = sub_commands.add_parser("create",
help=_("Create a new repository index."))
sub_create.add_argument("path", nargs=1, help=_("Path to the packages."))
+ sub_create.add_argument("inputs", nargs="+", help=_("Path to input packages."))
sub_create.add_argument("action", action="store_const", const="repo_create")
def handle_build(self):
def handle_repo_create(self):
path = self.args.path[0]
- self.pakfire.repo_create(path)
+ self.pakfire.repo_create(path, self.args.inputs)
LOCAL_BUILD_REPO_PATH = "/var/lib/pakfire/local"
-PACKAGES_DB = "var/lib/pakfire/packages.db"
+PACKAGES_DB_DIR = "var/lib/pakfire"
+PACKAGES_DB = os.path.join(PACKAGES_DB_DIR, "packages.db")
REPOSITORY_DB = "index.db"
BUFFER_SIZE = 1024**2
import logging
import os
import sqlite3
+import time
import packages
+from constants import *
+
class Database(object):
def __init__(self, pakfire, filename):
self.pakfire = pakfire
pkg INTEGER,
size INTEGER,
type INTEGER,
- hash1 TEXT,
- installed INTEGER,
- changed INTEGER
+ hash1 TEXT
);
CREATE TABLE packages(
version TEXT,
release TEXT,
filename TEXT,
- installed INTEGER,
- reason TEXT,
- repository TEXT,
hash1 TEXT,
provides TEXT,
requires TEXT,
for i in c:
ret = i["id"]
break
-
+
c.close()
return ret
def add_package(self, pkg):
+ raise NotImplementedError
+
+
+class RemotePackageDatabase(PackageDatabase):
+ def add_package(self, pkg, reason=None):
if self.package_exists(pkg):
logging.debug("Skipping package which already exists in database: %s" % pkg.friendly_name)
return
logging.debug("Adding package to database: %s" % pkg.friendly_name)
+ filename = ""
+ if pkg.repo.local:
+ filename = pkg.filename[len(pkg.repo.path) + 1:]
+
c = self.cursor()
c.execute("""
INSERT INTO packages(
version,
release,
filename,
+ hash1,
provides,
- requires
- ) VALUES(?, ?, ?, ?, ?, ?, ?)""",
+ requires,
+ conflicts,
+ obsoletes,
+ license,
+ summary,
+ description,
+ build_id,
+ build_host,
+ build_date
+ ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(
pkg.name,
pkg.epoch,
pkg.version,
pkg.release,
- pkg.filename,
+ filename,
+ pkg.hash1,
" ".join(pkg.provides),
" ".join(pkg.requires),
+ " ".join(pkg.conflicts),
+ " ".join(pkg.obsoletes),
+ pkg.license,
+ pkg.summary,
+ pkg.description,
+ pkg.build_id,
+ pkg.build_host,
+ pkg.build_date
)
)
- c.close()
self.commit()
+ c.close()
pkg_id = self.get_id_by_pkg(pkg)
for file in pkg.filelist:
c.execute("INSERT INTO files(name, pkg) VALUES(?, ?)", (file, pkg_id))
+ self.commit()
c.close()
+
+ return pkg_id
+
+
+class LocalPackageDatabase(RemotePackageDatabase):
+ def __init__(self, pakfire):
+ # Generate filename for package database
+ filename = os.path.join(pakfire.path, PACKAGES_DB)
+
+ RemotePackageDatabase.__init__(self, pakfire, filename)
+
+ def create(self):
+ RemotePackageDatabase.create(self)
+
+ # Alter the database layout to store additional local information.
+ logging.debug("Altering database table for local information.")
+ c = self.cursor()
+ c.executescript("""
+ ALTER TABLE packages ADD COLUMN installed INT;
+ ALTER TABLE packages ADD COLUMN reason TEXT;
+ ALTER TABLE packages ADD COLUMN repository TEXT;
+ """)
self.commit()
+ c.close()
+ def add_package(self, pkg, reason=None):
+ # Insert all the information to the database we have in the remote database
+ pkg_id = RemotePackageDatabase.add_package(self, pkg)
-class LocalPackageDatabase(PackageDatabase):
- def add_package(self, pkg, installed=True):
+ # then: add some more information
c = self.cursor()
- c.execute("INSERT INTO packages(name, epoch, version, release, installed, \
- provides, requires, build_id, build_host, build_date) \
- VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (
- pkg.name,
- pkg.epoch,
- pkg.version,
- pkg.release,
- int(installed),
- " ".join(pkg.provides),
- " ".join(pkg.requires),
- pkg.build_id,
- pkg.build_host,
- pkg.build_date
- ))
-
- #c.close()
-
- # Get the id from the package
- #c = self.cursor()
- #c.execute("SELECT * FROM packages WHERE build_id = ? LIMIT 1", (pkg.build_id))
- c.execute("SELECT * FROM packages WHERE name = ? AND version = ? AND \
- release = ? AND epoch = ? LIMIT 1", (pkg.name, pkg.version, pkg.release, pkg.epoch))
+ # Save timestamp when the package was installed.
+ c.execute("UPDATE packages SET installed = ? WHERE id = ?", (time.time(), pkg_id))
- ret = None
- for pkg in c:
- ret = packages.InstalledPackage(self.pakfire, self, pkg)
- break
+ # Add repository information.
+ c.execute("UPDATE packages SET repository = ? WHERE id = ?", (pkg.repo.name, pkg_id))
- assert ret
- c.close()
+ # Save reason of installation (if any).
+ if reason:
+ c.execute("UPDATE packages SET reason = ? WHERE id = ?", (reason, pkg_id))
- return ret
+ # Update the filename information.
+ c.execute("UPDATE packages SET filename = ? WHERE id = ?", (pkg.filename, pkg_id))
+ self.commit()
+ c.close()
import database
import packages
+import repository
from constants import *
def update(self, force=False):
raise NotImplementedError
+ def add_package(self, pkg):
+ raise NotImplementedError
+
class DirectoryIndex(Index):
def __init__(self, pakfire, repo, path):
+ if path.startswith("file://"):
+ path = path[7:]
self.path = path
Index.__init__(self, pakfire, repo)
class DatabaseIndex(Index):
- def __init__(self, pakfire, repo, db):
- self.db = db
-
+ def __init__(self, pakfire, repo):
Index.__init__(self, pakfire, repo)
+ self.db = None
+
+ if isinstance(repo, repository.InstalledRepository):
+ self.db = database.LocalPackageDatabase(self.pakfire)
+
+ else:
+ # Generate path to database file.
+ filename = os.path.join(repo.path, "XXX-to-be-renamed.db")
+ self.db = database.RemotePackageDatabase(self.pakfire, filename)
+
+ @property
+ def local(self):
+ pass
+
def update(self, force=False):
"""
Nothing to do here.
c.close()
+ def add_package(self, pkg, reason=None):
+ return self.db.add_package(pkg, reason)
+
# XXX maybe this can be removed later?
class InstalledIndex(DatabaseIndex):
def provides(self):
return self.metadata.get("PKG_PROVIDES").split()
+ @property
+ def conflicts(self):
+ return self.metadata.get("PKG_CONFLICTS", "").split()
+
+ @property
+ def obsoletes(self):
+ return self.metadata.get("PKG_OBSOLETES", "").split()
+
def get_extractor(self, pakfire):
return packager.Extractor(pakfire, self)
import os
import re
+import util
+
from pakfire.errors import FileError
from base import Package
return ret or None
+ @property
+ def hash1(self):
+ """
+ Calculate the hash1 of this package.
+ """
+ return util.calc_hash1(self.filename)
+
#!/usr/bin/python
-import hashlib
-import time
-
-import util
-
from base import Package
class DatabasePackage(Package):
c.close()
- ## database methods
-
- def set_installed(self, installed):
- c = self.db.cursor()
- c.execute("UPDATE packages SET installed = ? WHERE id = ?", (installed, self.id))
- c.close()
-
- def add_file(self, filename, type=None, size=None, hash1=None, **kwargs):
- if not hash1:
- hash1 = util.calc_hash1(filename)
-
- if size is None:
- size = os.path.getsize(filename)
-
- c = self.db.cursor()
- c.execute("INSERT INTO files(name, pkg, size, type, hash1, installed) \
- VALUES(?, ?, ?, ?, ?, ?)",
- (filename, self.id, size, type, hash1, time.time()))
- c.close()
-
# XXX maybe we can remove this later?
class InstalledPackage(DatabasePackage):
import base
import database
import index
+import packages
from constants import *
self._repos = []
# Create the local repository
- self.local = LocalRepository(self.pakfire)
+ self.local = InstalledRepository(self.pakfire)
self.add_repo(self.local)
# If we running in build mode, we include our local build repository.
def priority(self):
raise NotImplementedError
+ @property
+ def local(self):
+ """
+ Say if a repository is a local one or remotely located.
+
+ Used to check if we need to download files.
+ """
+ return False
+
def update_index(self, force=False):
"""
A function that is called to update the local data of
class LocalRepository(RepositoryFactory):
- def __init__(self, pakfire):
- RepositoryFactory.__init__(self, pakfire, "installed", "Installed packages")
+ def __init__(self, pakfire, name, description, path):
+ RepositoryFactory.__init__(self, pakfire, name, description)
- self.path = os.path.join(self.pakfire.path, PACKAGES_DB)
+ # Save location of the repository
+ self.path = path
- self.db = database.LocalPackageDatabase(self.pakfire, self.path)
+ self.index = index.DatabaseIndex(self.pakfire, self)
- self.index = index.InstalledIndex(self.pakfire, self, self.db)
+ @property
+ def local(self):
+ # This is obviously local.
+ return True
@property
def priority(self):
"""
- The local repository has always the highest priority.
+ The local repository has always a high priority.
"""
- return 0
+ return 10
# XXX need to implement better get_by_name
+ def _collect_packages(self, path):
+ logging.info("Collecting packages from %s." % path)
+
+ for dir, subdirs, files in os.walk(path):
+ for file in files:
+ if not file.endswith(".%s" % PACKAGE_EXTENSION):
+ continue
+
+ file = os.path.join(dir, file)
+
+ pkg = packages.BinaryPackage(self.pakfire, self, file)
+ self._add_package(pkg)
+
+ def _add_package(self, pkg):
+ # XXX gets an instance of binary package and puts it into the
+ # repo location if not done yet
+ # then: the package gets added to the index
+
+ if not isinstance(pkg, packages.BinaryPackage):
+ raise Exception
+
+ repo_filename = os.path.join(self.path, pkg.arch, os.path.basename(pkg.filename))
+
+ pkg_exists = None
+ if os.path.exists(repo_filename):
+ pkg_exists = packages.BinaryPackage(self.pakfire, self, repo_filename)
+
+ # If package in the repo is equivalent to the given one, we can
+ # skip any further processing.
+ if pkg == pkg_exists:
+ logging.debug("The package does already exist in this repo: %s" % pkg.friendly_name)
+ return
+
+ logging.debug("Copying package '%s' to repository." % pkg.friendly_name)
+ repo_dirname = os.path.dirname(repo_filename)
+ if not os.path.exists(repo_dirname):
+ os.makedirs(repo_dirname)
+
+ os.link(pkg.filename, repo_filename)
+
+ # Create new package object, that is connected to this repository
+ # and so we can do stuff.
+ pkg = packages.BinaryPackage(self.pakfire, self, repo_filename)
+
+ logging.info("Adding package '%s' to repository." % pkg.friendly_name)
+ self.index.add_package(pkg)
+
+
+class InstalledRepository(RepositoryFactory):
+ def __init__(self, pakfire):
+ RepositoryFactory.__init__(self, pakfire, "installed", "Installed packages")
+
+ self.index = index.InstalledIndex(self.pakfire, self)
+
+ @property
+ def local(self):
+ # This is obviously local.
+ return True
+
+ @property
+ def priority(self):
+ """
+ The installed repository has always the highest priority.
+ """
+ return 0
+
class LocalBuildRepository(LocalRepository):
def __init__(self, pakfire):
else:
self.enabled = False
- if self.url.startswith("file://"):
- self.index = index.DirectoryIndex(self.pakfire, self, self.url[7:])
-
+ if self.local:
+ self.index = index.DirectoryIndex(self.pakfire, self, self.url)
else:
- self.index = None
+ self.index = index.DatabaseIndex(self.pakfire, self)
logging.debug("Created new repository(name='%s', url='%s', enabled='%s')" % \
(self.name, self.url, self.enabled))
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.url)
+ @property
+ def local(self):
+ # If files are located somewhere in the filesystem we assume it is
+ # local.
+ if self.url.startswith("file://"):
+ return True
+
+ # Otherwise not.
+ return False
+
+ @property
+ def path(self):
+ if self.local:
+ return self.url[7:]
+
+ raise Exception, "XXX find some cache dir"
+
@property
def priority(self):
priority = 100
logging.debug("Extracting package %s" % self.pkg.friendly_name)
# Create package in the database
- virtpkg = self.local.db.add_package(self.pkg, installed=False)
+ virtpkg = self.local.index.add_package(self.pkg)
# Grab an instance of the extractor and set it up
extractor = self.pkg.get_extractor(self.pakfire)
# Extract all files to instroot
- extractor.extractall(self.pakfire.path, callback=virtpkg.add_file)
-
- # Mark package as installed
- virtpkg.set_installed(True)
- #self.db.commit()
+ extractor.extractall(self.pakfire.path)
# Remove all temporary files
extractor.cleanup()
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-02-06 15:13+0100\n"
+"POT-Creation-Date: 2011-02-19 17:57+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../pakfire/cli.py:25
+#: ../pakfire/cli.py:26
#, python-format
msgid "%s [y/N]"
msgstr ""
-#: ../pakfire/cli.py:36
+#: ../pakfire/cli.py:37
msgid "Pakfire command line interface."
msgstr ""
-#: ../pakfire/cli.py:43
+#: ../pakfire/cli.py:44
msgid "The path where pakfire should operate in."
msgstr ""
-#: ../pakfire/cli.py:72
+#: ../pakfire/cli.py:77
msgid "Enable verbose output."
msgstr ""
-#: ../pakfire/cli.py:75
+#: ../pakfire/cli.py:80
msgid "Path to a configuration file to load."
msgstr ""
-#: ../pakfire/cli.py:78
+#: ../pakfire/cli.py:83
msgid "Disable a repository temporarily."
msgstr ""
-#: ../pakfire/cli.py:83
+#: ../pakfire/cli.py:88
msgid "Install one or more packages to the system."
msgstr ""
-#: ../pakfire/cli.py:85
+#: ../pakfire/cli.py:90
msgid "Give name of at least one package to install."
msgstr ""
-#: ../pakfire/cli.py:91
+#: ../pakfire/cli.py:96
+msgid "Install one or more packages from the filesystem."
+msgstr ""
+
+#: ../pakfire/cli.py:98
+msgid "Give filename of at least one package."
+msgstr ""
+
+#: ../pakfire/cli.py:104
msgid "Update the whole system or one specific package."
msgstr ""
-#: ../pakfire/cli.py:93
+#: ../pakfire/cli.py:106
msgid "Give a name of a package to update or leave emtpy for all."
msgstr ""
-#: ../pakfire/cli.py:99
+#: ../pakfire/cli.py:112
msgid "Print some information about the given package(s)."
msgstr ""
-#: ../pakfire/cli.py:101
+#: ../pakfire/cli.py:114
msgid "Give at least the name of one package."
msgstr ""
-#: ../pakfire/cli.py:107
+#: ../pakfire/cli.py:120
msgid "Search for a given pattern."
msgstr ""
-#: ../pakfire/cli.py:109
+#: ../pakfire/cli.py:122
msgid "A pattern to search for."
msgstr ""
-#: ../pakfire/cli.py:149
+#: ../pakfire/cli.py:128
+msgid "Get a list of packages that provide a given file or feature."
+msgstr ""
+
+#: ../pakfire/cli.py:130
+msgid "File or feature to search for."
+msgstr ""
+
+#: ../pakfire/cli.py:192
msgid "Pakfire builder command line interface."
msgstr ""
-#: ../pakfire/cli.py:185
+#: ../pakfire/cli.py:232
msgid "Update the package indexes."
msgstr ""
-#: ../pakfire/cli.py:191
+#: ../pakfire/cli.py:238
msgid "Build one or more packages."
msgstr ""
-#: ../pakfire/cli.py:193
+#: ../pakfire/cli.py:240
msgid "Give name of at least one package to build."
msgstr ""
-#: ../pakfire/cli.py:197
+#: ../pakfire/cli.py:244
msgid "Build the package for the given architecture."
msgstr ""
-#: ../pakfire/cli.py:199 ../pakfire/cli.py:221
+#: ../pakfire/cli.py:246 ../pakfire/cli.py:268
msgid "Path were the output files should be copied to."
msgstr ""
-#: ../pakfire/cli.py:204
+#: ../pakfire/cli.py:251
msgid "Go into a shell."
msgstr ""
-#: ../pakfire/cli.py:206 ../pakfire/cli.py:217
+#: ../pakfire/cli.py:253 ../pakfire/cli.py:264
msgid "Give name of a package."
msgstr ""
-#: ../pakfire/cli.py:210
+#: ../pakfire/cli.py:257
msgid "Emulated architecture in the shell."
msgstr ""
-#: ../pakfire/cli.py:215
+#: ../pakfire/cli.py:262
msgid "Generate a source package."
msgstr ""
-#: ../pakfire/__init__.py:156
+#: ../pakfire/cli.py:272
+msgid "Repository management commands."
+msgstr ""
+
+#: ../pakfire/cli.py:280
+msgid "Create a new repository index."
+msgstr ""
+
+#: ../pakfire/cli.py:281
+msgid "Path to the packages."
+msgstr ""
+
+#: ../pakfire/cli.py:282
+msgid "Path to input packages."
+msgstr ""
+
+#: ../pakfire/__init__.py:165
msgid "Is this okay?"
msgstr ""
-#: ../pakfire/packages/base.py:42
+#: ../pakfire/packages/base.py:47
msgid "Name"
msgstr ""
-#: ../pakfire/packages/base.py:43 ../pakfire/transaction.py:231
+#: ../pakfire/packages/base.py:48 ../pakfire/transaction.py:227
msgid "Arch"
msgstr ""
-#: ../pakfire/packages/base.py:44 ../pakfire/transaction.py:231
+#: ../pakfire/packages/base.py:49 ../pakfire/transaction.py:227
msgid "Version"
msgstr ""
-#: ../pakfire/packages/base.py:45
+#: ../pakfire/packages/base.py:50
msgid "Release"
msgstr ""
-#: ../pakfire/packages/base.py:46 ../pakfire/transaction.py:231
+#: ../pakfire/packages/base.py:51 ../pakfire/transaction.py:227
msgid "Size"
msgstr ""
-#. (_("Repo"), self.repo),
-#: ../pakfire/packages/base.py:48
+#: ../pakfire/packages/base.py:52
+msgid "Repo"
+msgstr ""
+
+#: ../pakfire/packages/base.py:53
msgid "Summary"
msgstr ""
-#. (_("URL"), self.url),
-#: ../pakfire/packages/base.py:50
+#: ../pakfire/packages/base.py:54
+msgid "URL"
+msgstr ""
+
+#: ../pakfire/packages/base.py:55
msgid "License"
msgstr ""
-#: ../pakfire/packages/base.py:53
+#: ../pakfire/packages/base.py:58
msgid "Description"
msgstr ""
-#: ../pakfire/packages/packager.py:67
+#: ../pakfire/packages/packager.py:70
msgid "Extracting"
msgstr ""
-#: ../pakfire/packages/packager.py:122
+#: ../pakfire/packages/packager.py:125
msgid "Extracting:"
msgstr ""
-#: ../pakfire/transaction.py:231
+#: ../pakfire/transaction.py:227
msgid "Package"
msgstr ""
-#: ../pakfire/transaction.py:231
+#: ../pakfire/transaction.py:227
msgid "Repository"
msgstr ""
-#: ../pakfire/transaction.py:235
+#: ../pakfire/transaction.py:231
msgid "Installing:"
msgstr ""
-#: ../pakfire/transaction.py:241
+#: ../pakfire/transaction.py:237
msgid "Updating:"
msgstr ""
-#: ../pakfire/transaction.py:247
+#: ../pakfire/transaction.py:243
msgid "Removing:"
msgstr ""
-#: ../pakfire/transaction.py:252
+#: ../pakfire/transaction.py:248
msgid "Transaction Summary"
msgstr ""
-#: ../pakfire/transaction.py:258
+#: ../pakfire/transaction.py:254
msgid "Install"
msgstr ""
-#: ../pakfire/transaction.py:258 ../pakfire/transaction.py:261
-#: ../pakfire/transaction.py:264
+#: ../pakfire/transaction.py:254 ../pakfire/transaction.py:257
+#: ../pakfire/transaction.py:260
msgid "Package(s)"
msgstr ""
-#: ../pakfire/transaction.py:261
+#: ../pakfire/transaction.py:257
msgid "Updates"
msgstr ""
-#: ../pakfire/transaction.py:264
+#: ../pakfire/transaction.py:260
msgid "Remove"
msgstr ""
-#: ../pakfire/transaction.py:267
+#: ../pakfire/transaction.py:263
#, python-format
msgid "Total download size: %s"
msgstr ""