#!/usr/bin/python # versioned_repos.py: # Directory of "versioned" repositories, sharing hard-linked files # # Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) # Copyright (C) 2010 Red Hat, Inc. # Written by Colin Walters import os import sys import logging import glib import gio import rpm import rpmUtils import rpmUtils.miscutils from . import subtask class BaseRepo(object): def __init__(self, dirpath, name): self._dir = dirpath self.name = name self._task_basename = 'repo-%s' % (name, ) if not os.path.isdir(self._dir): os.makedirs(self._dir) def get_dir(self): return self._dir def add_rpm(self, rpm_path): basename = os.path.basename(rpm_path) dest = os.path.join(self._dir, basename) logging.debug("Linking %r to %r" % (rpm_path, dest)) os.link(rpm_path, dest) def iter_rpms(self): for filename in os.listdir(self._dir): if filename.endswith('.rpm'): yield os.path.join(self._dir, filename) def _delete_old_rpms_in_dir(self, dirpath): output = subtask.spawn_sync_get_output('repomanage-' + self._task_basename, ['repomanage', '-o', '.'], cwd=dirpath) for line in output.split('\n'): path = os.path.join(self._dir, line) if line.endswith('.rpm') and os.path.exists(path): os.unlink(path) def update_sync(self): self._delete_old_rpms_in_dir(self._dir) subtask.spawn_sync('createrepo' + self._task_basename, ['createrepo', '.'], cwd=self._dir) class Repo(BaseRepo): def __init__(self, basedir, name, version): dirname = '%d' % (version, ) dirpath = os.path.join(basedir, dirname) BaseRepo.__init__(self, dirpath, name) self.version = version class VersionedRepo(object): def __init__(self, dirpath): self._dir = dirpath if not os.path.isdir(self._dir): os.makedirs(self._dir) self._name = os.path.basename(dirpath) self._versions = {} self._last_version = -1 self._reload() def get_versions(self): return self._versions def _reload(self): self._versions = {} for filename in os.listdir(self._dir): path = os.path.join(self._dir, filename) if not os.path.isdir(path): continue try: revision = int(filename) except ValueError, e: continue self._versions[revision] = Repo(self._dir, self._name, revision) if revision > self._last_version: self._last_version = revision def get_latest_version(self): if self._last_version == -1: return None return self._versions[self._last_version] def get_latest_path(self): latest = self.get_latest_version() if latest is None: return None return latest.get_dir() def commit_sync(self, new_rpms): rev = self._last_version + 1 new_repo = Repo(self._dir, self._name, rev) if rev > 0: prev_repo = self._versions[self._last_version] for rpm in prev_repo.iter_rpms(): new_repo.add_rpm(rpm) for rpm in new_rpms: new_repo.add_rpm(rpm) new_repo.update_sync() self._versions[rev] = new_repo self._last_version = rev return rev