summaryrefslogtreecommitdiffstats
path: root/sortedtransaction.py
blob: 23547e53becd91cca2acb80b02343eec7251ca43 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/python

from yum.transactioninfo import TransactionData, TransactionMember
from yum.Errors import YumBaseError

import urlparse
urlparse.uses_fragment.append('media')

WHITE = 0
GREY = 1
BLACK = 2

class SortableTransactionData(TransactionData):
    def __init__(self):
        self._sorted = []
        self.path = []
        self.loops = []
        self.changed = True
        TransactionData.__init__(self)

    def _visit(self, txmbr):
        self.path.append(txmbr.name)
        txmbr.sortColour = GREY
        for (relation, reltype) in txmbr.relatedto:
            if reltype != 'dependson':
                continue 
            vertex = self.getMembers(pkgtup=relation)[0]
            if vertex.sortColour == GREY:
                self._doLoop(vertex.name)
            if vertex.sortColour == WHITE:
                self._visit(vertex)
        txmbr.sortColour = BLACK
        self._sorted.insert(0, txmbr.pkgtup)

    def _doLoop(self, name):
        self.path.append(name)
        loop = self.path[self.path.index(self.path[-1]):]
        if len(loop) > 2:
            self.loops.append(loop)

    def add(self, txmember):
        txmember.sortColour = WHITE
        TransactionData.add(self, txmember)
        self.changed = True

    def remove(self, pkgtup):
        TransactionData.remove(self, pkgtup)
        self.changed = True

    def sort(self):
        if self._sorted and not self.changed:
            return self._sorted
        self._sorted = []
        self.changed = False
        # loop over all members
        for txmbr in self.getMembers():
            if txmbr.sortColour == WHITE:
                self.path = [ ]
                self._visit(txmbr)
        self._sorted.reverse()
        return self._sorted

class SplitMediaTransactionData(SortableTransactionData):
    def __init__(self):
        SortableTransactionData.__init__(self)
        self.reqmedia = {}
        self.curmedia = 0 

    def __getMedia(self, po):
        try:
            uri = po.returnSimple('basepath')
            (scheme, netloc, path, query, fragid) = urlparse.urlsplit(uri)
            if scheme != "media" or not fragid:
                return 0
            else:
                return int(fragid)
        except (KeyError, AttributeError):
            return 0

    def getMembers(self, pkgtup=None):
        if not self.curmedia:
            return TransactionData.getMembers(self, pkgtup)
        if pkgtup is None:
            returnlist = []
            for key in self.reqmedia[self.curmedia]:
                returnlist.extend(self.pkgdict[key])

            return returnlist

        if self.reqmedia[self.curmedia].has_key(pkgtup):
            return self.pkgdict[pkgtup]
        else:
            return []

    def add(self, txmember):
        id = self.__getMedia(txmember.po)
        if id:
            if id not in self.reqmedia.keys():
                self.reqmedia[id] = [ txmember.pkgtup ]
            else:
                self.reqmedia[id].append(txmember.pkgtup)
        SortableTransactionData.add(self, txmember)

    def remove(self, pkgtup):
        if not self.pkgdict.has_key(pkgtup):
            return
        txmembers = self.pkgdict[pkgtup]
        if len(txmembers) > 0:
            for txmbr in txmembers:
                id = self.__getMedia(txmbr.po)
                if id:
                    self.reqmedia[id].remove(pktup)
                del txmbr
                SortableTransactionData.remove(self, pkgtup)

class TransactionConstraintMetError(YumBaseError):
    def __init__(self, args=None):
        YumBaseError.__init__(self)
        self.args = args
        
class ConstrainedTransactionData(SortableTransactionData):
    def __init__(self, constraint=lambda txmbr: False):
        """Arbitrary constraint on transaction member
           @param constraint form:
              function(self, TransactionMember)
              constraint function returns True/False.
           @type constraint function"""
        self.constraint = constraint
        SortableTransactionData.__init__(self)

    def add(self, txmbr):
        """@param txmbr: TransactionMember
           @raise TransactionConstraintMetError: if 
               constraint returns True when adding"""
        if self.constraint and not self.constraint(txmbr):
            SortableTransactionData.add(self, txmbr)
        else:
            raise TransactionConstraintMetError("Constraint met")