import repository from arizona
[raven.git] / lib / ravenlib / package / transaction.py
1 """
2 <Program Name>
3    storktransaction.py
4
5 <Started>
6    Jan 19, 2007
7
8 <Author>
9    Programmed by Scott Baker.
10
11 <Purpose>
12    Creation and maintenance of transaction lists. A transaction list is a list
13    of packages to install, remove, and/or upgrade.
14
15    Transaction List: A translaction list is a list of transaction entries
16
17    Transaction entry format: A transaction is a dictionary with the following
18    keys:
19       trans['op']:
20          operation to perform: INSTALL, UPGRADE, or REMOVE
21       trans['filename']:
22          local filename of rpm file (usually in /tmp). Used during INSTALL and
23          UPGRADE operations.
24       trans['conflicts']:
25          list of installed package names that conflict. Used during UPGRADE
26          operations.
27       trans['packname']:
28          name of package. Used during REMOVE operations.
29
30    Transaction lists are created with:
31       tl = storktransaction.tl_create()
32
33    New entries are added to the tail of the list via any of the following:
34       tl = storktransaction.tl_install(tl, package_filename)
35       tl = storktransaction.tl_upgrade(tl, package_filename, conflict_list)
36       tl = storktransaction.tl_remove(tl, package_name)
37 """
38
39 import ravenlib.typecheck
40 import ravenlib.listutil
41 import os
42
43 # these constants may be used when inspecting the 'op' field of a transaction
44 # entry:
45
46 INSTALL = "INSTALL"
47 UPGRADE = "UPGRADE"
48 REMOVE = "REMOVE"
49
50 def tl_create():
51    """
52    <Purpose>
53       Creates an empty transaction list.
54
55    <Arguments>
56       None.
57
58    <Exceptions>
59       None.
60       
61    <Side Effects>
62       None.
63
64    <Returns>
65       An empty transaction list.
66    """
67    return []
68
69 def tl_add(tl, transaction):
70    """
71    <Purpose>
72       Appends a transaction entry to the tail of a transaction list
73
74    <Arguments>
75       tl - transaction list
76       transaction - transaction entry
77
78    <Exceptions>
79       None.
80       
81    <Side Effects>
82       The transaction is added to the end of the list.
83
84    <Returns>
85       None.
86    """
87    ravenlib.typecheck.simple(tl, "tl", list, "storktransaction.tl_add")
88    
89    tl.append(transaction)
90
91 def tl_install(tl, filename):
92    """
93    <Purpose>
94       Adds an INSTALL operation to a transaction list.
95
96    <Arguments>
97       tl - transaction list
98       filename - local filename of package
99
100    <Exceptions>
101       None.
102       
103    <Side Effects>
104       Transaction is appended to the end of the list.
105
106    <Returns>
107       None.
108    """
109    trans = {}
110    trans['op'] = INSTALL
111    trans['filename'] = filename
112    tl_add(tl, trans)
113
114 def tl_upgrade(tl, filename, conflict_list):
115    """
116    <Purpose>
117       Adds an UPGRADE operation to a transaction list.
118
119    <Arguments>
120       tl - transaction list
121       filename - local filename of package
122       conflict_list - list of package names that conflict with this pacakge
123
124    <Exceptions>
125       None.
126       
127    <Side Effects>
128       Transaction is appended to the end of the list.
129
130    <Returns>
131       None.
132    """
133    ravenlib.typecheck.simple(filename, "filename", str, "storktransaction.tl_add")
134    ravenlib.typecheck.simple(conflict_list, "conflict_list", list, "storktransaction.tl_add")
135    trans = {}
136    trans['op'] = UPGRADE
137    trans['filename'] = filename
138    trans['conflicts'] = conflict_list
139    tl_add(tl, trans)
140
141 def tl_remove(tl, packname):
142    """
143    <Purpose>
144       Adds a REMOVE operation to a transaction list.
145
146    <Arguments>
147       tl - transaction list
148       packname - name of installed package to remove
149
150    <Exceptions>
151       None.
152       
153    <Side Effects>
154       Transaction is appended to end of list.
155
156    <Returns>
157       None.
158    """
159    trans = {}
160    trans['op'] = REMOVE
161    trans['packname'] = packname
162    tl_add(tl, trans)
163
164 def tl_print(tl):
165    """
166    <Purpose>
167       Print the contents of a transaction list.
168
169    <Arguments>
170       tl - transaction list
171
172    <Exceptions>
173       None.
174       
175    <Side Effects>
176       None.
177
178    <Returns>
179       None.
180    """
181    ravenlib.typecheck.simple(tl, "tl", list, "storktransaction.tl_print")
182    
183    for trans in tl:
184       ravenlib.typecheck.simple(trans, "trans", dict, "storktransaction.tl_print")
185       operation = trans['op']
186       print_string = "   " + operation
187       if operation == INSTALL:
188          print_string += " " + trans['filename']
189       elif operation == REMOVE:
190          print_string += ' ' + trans['packname']
191       elif operation == UPGRADE:
192          print_string += ' ' + trans['filename']
193          if 'conflicts' in trans:
194             print_string += "     will replace: " + str(trans['conflicts'])
195       print print_string
196
197 def tl_clear_status(tl):
198    for trans in tl:
199       if ("status" in trans):
200           del trans["status"]
201       if ("status-reason" in trans):
202           del trans["status-reason"]
203       if ("status-verbose" in trans):
204           del trans["status-verbose"]
205
206
207
208 def tl_get_count(tl, kind):
209    count = 0
210    for trans in tl:
211       if (kind == None) or (trans['op'] == kind):
212          count = count + 1
213    return count
214           
215 def tl_get_filename_list(tl, kind=None, status=None):
216    filename_list = []
217    for trans in tl:
218       if (kind!=None) and (trans.get('op', None) != kind):
219          continue
220       if (status!=None) and (trans.get('status', None) != status):
221          continue
222       if 'filename' in trans:
223          filename_list.append(trans['filename'])
224    filename_list = ravenlib.listutil.uniq(filename_list)
225    return filename_list
226
227 def tl_find_filename(tl, filename):
228    for trans in tl:
229        if trans.get("filename", None) == filename:
230            return trans
231    return None
232
233 def tl_find_packname(tl, packname):
234    for trans in tl:
235        if trans.get("packname", None) == packname:
236            return trans
237    return None
238
239 def tl_get_packname_list(tl, kind):
240    packname_list = []
241    for trans in tl:
242       if (kind == None) or (trans['op'] == kind):
243          if 'packname' in trans:
244             packname_list.append(trans['packname'])
245    packname_list = ravenlib.listutil.uniq(packname_list)
246    return packname_list
247
248 def tl_get_conflict_list(tl, kind):
249    conflict_list = []
250    for trans in tl:
251       if (kind == None) or (trans['op'] == kind):
252          if 'conflicts' in trans:
253             conflict_list.extend(trans['conflicts'])
254    conflict_list = ravenlib.listutil.uniq(conflict_list)
255    return conflict_list
256
257 def trans_set_status(trans, status, reason=None, verbose_msg=None):
258    trans["status"] = status
259    trans["status-reason"] = reason
260    trans["status-verbose"] = verbose_msg
261
262 def tl_set_status_by_filename(tl, filename, status, reason=None, verbose_msg=None):
263    trans = tl_find_filename(tl, filename)
264    if trans:
265        trans_set_status(trans, status, reason, verbose_msg)
266
267 def tl_set_status_by_packname(tl, packname, status, reason=None, verbose_msg=None):
268    trans = tl_find_packname(tl, packname)
269    if trans:
270        trans_set_status(trans, status, reason, verbose_msg)