1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import os
16
17 from conary import conarycfg
18 from conary import errors
19 from conary import state
20 from conary.deps import deps
21 from conary.lib import log, cfgtypes, api
22 from conary.repository import changeset
23 from conary.repository.filecontainer import BadContainer
24
25 @api.publicApi
27 """
28 Parse a TroveSpec string
29
30 @param specStr: the input string
31 @type specStr: string
32
33 @param allowEmptyName: if set, will accept an empty string and some other
34 variations.
35 @type allowEmptyName: bool
36
37 @rtype: list
38 @return: (name, version, flavor)
39
40 @raise TroveSpecError: Raised if the input string is not a valid TroveSpec
41 """
42 origSpecStr = specStr
43 if specStr.find('[') > 0 and specStr[-1] == ']':
44 specStr = specStr[:-1]
45 l = specStr.split('[')
46 if len(l) != 2:
47 raise TroveSpecError(origSpecStr, "bad flavor spec")
48 specStr, flavorSpec = l
49 flavor = deps.parseFlavor(flavorSpec)
50 if flavor is None:
51 raise TroveSpecError(origSpecStr, "bad flavor spec")
52 else:
53 flavor = None
54
55 if specStr.find("=") >= 0:
56 l = specStr.split("=")
57 if len(l) != 2:
58 raise TroveSpecError(origSpecStr, "Too many ='s")
59 name, versionSpec = l
60 else:
61 name = specStr
62 versionSpec = None
63 if not name and not allowEmptyName:
64 raise TroveSpecError(origSpecStr, 'Trove name is required')
65
66 return (name, versionSpec, flavor)
67
82
84
85
86
87
88
89 areAbsolute = not keepExisting
90
91 applyList = []
92
93 if type(updateList) is str:
94 updateList = ( updateList, )
95
96 for updateStr in updateList:
97 if os.path.exists(updateStr) and os.path.isfile(updateStr):
98 applyList.append(_getChangeSet(updateStr))
99 continue
100 else:
101 troveSpec = parseTroveSpec(updateStr)
102 if troveSpec[0][0] == '-':
103 applyList.append((troveSpec[0], troveSpec[1:],
104 (None, None), False))
105 elif troveSpec[0][0] == '+':
106 applyList.append((troveSpec[0], (None, None),
107 troveSpec[1:], areAbsolute))
108 elif updateByDefault:
109 applyList.append((troveSpec[0], (None, None),
110 troveSpec[1:], areAbsolute))
111 else:
112 applyList.append((troveSpec[0], troveSpec[1:],
113 (None, None), False))
114 log.debug("will look for %s", applyList[-1])
115
116
117 return set(applyList)
118
119
120 @api.publicApi
121 -def parseChangeList(changeSpecList, keepExisting=False, updateByDefault=True,
122 allowChangeSets=True):
123 """
124 Parse a change specification list, as presented on the command line.
125
126 Takes input specifying changeSpecs, such as C{foo=1.1--1.2},
127 and turns it into C{(name, (oldVersionSpec, oldFlavorSpec),
128 (newVersionSpec, newFlavorSpec), isAbsolute)} tuples.
129
130 @note:
131 If a filename is passed as a changeSpec, and the file does not contain
132 a valid conary changeset, a sys.exit() will be called.
133
134 @param changeSpecList: a changeSpec, such as C{foo=1.1--1.2}
135 @type changeSpecList: string
136
137 @param keepExisting: specifies whether an installed trove should be
138 kept in addition to an updated version.
139 @type keepExisting: bool
140
141 @param updateByDefault:
142 @type updateByDefault: bool
143
144 @param allowChangeSets: specifies whether file-based changesets are
145 allowed.
146 @type allowChangeSets: bool
147
148 @raise TroveSpecError: Raised if an invalid TroveSpec is passed within the
149 ChangeSpec list.
150
151 @rtype: list
152 @return: a list of changes to apply, of the form
153 (name, (oldVersion, oldFlavor), (newVersion, newFlavor), replaceExisting)
154 where either the old or new version/flavor (but not both) may be
155 (None, None)
156 """
157 applyList = []
158
159 if isinstance(changeSpecList, str):
160 changeSpecList = (changeSpecList,)
161
162
163 for changeSpec in changeSpecList:
164
165 isAbsolute = False
166
167 if (allowChangeSets and os.path.exists(changeSpec)
168 and os.path.isfile(changeSpec)):
169 applyList.append(_getChangeSet(changeSpec))
170 continue
171
172 l = changeSpec.split("--")
173
174 if len(l) == 1:
175 (troveName, versionStr, flavor) = parseTroveSpec(l[0], False)
176
177 if troveName[0] == '-':
178 applyList.append((troveName, (versionStr, flavor),
179 (None, None), False))
180 elif troveName[0] == '+' or updateByDefault:
181 applyList.append((troveName, (None, None),
182 (versionStr, flavor), not keepExisting))
183 else:
184 applyList.append((troveName, (versionStr, flavor),
185 (None, None), False))
186 elif len(l) != 2:
187 log.error("one -- expected in change spec '%s'",
188 changeSpec)
189 return
190 else:
191 oldSpec, newSpec = l
192 (troveName, oldVersion, oldFlavor) = parseTroveSpec(oldSpec)
193
194 if newSpec:
195 newSpec = troveName + "=" + newSpec
196 (troveName, newVersion, newFlavor) = parseTroveSpec(newSpec)
197 else:
198 newVersion, newFlavor = None, None
199
200 if (newVersion or (newFlavor is not None)) and \
201 not (oldVersion or (oldFlavor is not None)):
202
203 oldVersion, oldFlavor = None, None
204
205 applyList.append((troveName, (oldVersion, oldFlavor),
206 (newVersion, newFlavor), False))
207
208
209
210 finalList = []
211 for item in applyList:
212 if item not in finalList:
213 finalList.append(item)
214
215 return finalList
216
217 @api.publicApi
219 """
220 Construct a TroveSpec string from name + version + flavor
221
222 @param name: trove name
223 @type name: string
224
225 @param versionStr: trove version string
226 @type versionStr: string
227
228 @param flavor: trove flavor
229 @type flavor: L{deps.deps.Flavor}
230
231 @rtype: string
232 @return: a TroveSpec of the form name=version[flavor]
233 """
234
235 disp = [name]
236 if versionStr:
237 disp.extend(('=', versionStr))
238 if flavor is not None and not flavor.isEmpty():
239 disp.extend(('[', deps.formatFlavor(flavor), ']'))
240 return ''.join(disp)
241
242 -def askYn(prompt, default=None):
243 while True:
244 try:
245 resp = raw_input(prompt + ' ')
246 except EOFError:
247 return False
248
249 resp = resp.lower()
250 if resp in ('y', 'yes'):
251 return True
252 elif resp in ('n', 'no'):
253 return False
254 elif not resp:
255 return default
256 else:
257 print "Unknown response '%s'." % resp
258