summaryrefslogtreecommitdiffstats
path: root/rpmci/versioned_repos.py
blob: 6ee4b6cd2dac3124a8b76ad0f1b380c8b38f2bdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/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 <walters@verbum.org>

import os
import sys
import logging

import glib
import gio
import rpm
import rpmUtils
import rpmUtils.miscutils

from . import subtask

class Repo(object):
    def __init__(self, basedir, name, version):
        self.name = name
        self.version = version
        self._dirname = '%d' % (version, )
        self._dir = os.path.join(basedir, self._dirname)
        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 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