summaryrefslogtreecommitdiffstats
path: root/sortedtransaction.py
blob: 2adcf1b31c77e4e3817469467fc79307efb1b1d5 (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
#!/usr/bin/python

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

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 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")