Package conary :: Package conaryclient :: Module cmdline
[hide private]
[frames] | no frames]

Source Code for Module conary.conaryclient.cmdline

  1  # 
  2  # Copyright (c) 2004-2008 rPath, Inc. 
  3  # 
  4  # This program is distributed under the terms of the Common Public License, 
  5  # version 1.0. A copy of this license should have been distributed with this 
  6  # source file in a file called LICENSE. If it is not present, the license 
  7  # is always available at http://www.rpath.com/permanent/licenses/CPL-1.0. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, but 
 10  # without any warranty; without even the implied warranty of merchantability 
 11  # or fitness for a particular purpose. See the Common Public License for 
 12  # full details. 
 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 
26 -def parseTroveSpec(specStr, allowEmptyName = True):
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
68 -def _getChangeSet(path):
69 try: 70 cs = changeset.ChangeSetFromFile(path) 71 except BadContainer, msg: 72 # ensure that it is obvious that a file is being referenced 73 if path[0] not in './': 74 path = './' + path 75 log.error("'%s' is not a valid conary changeset: %s" % 76 (path, msg)) 77 # XXX sys.exit is gross 78 import sys 79 sys.exit(1) 80 log.debug("found changeset file %s" % path) 81 return cs
82
83 -def parseUpdateList(updateList, keepExisting, updateByDefault=True):
84 # If keepExisting is true, we want our specifications to be relative 85 # to nothing. If it's false, they should be absolute as updateChangeSet 86 # interperts absolute jobs as ones which should be rooted (if there is 87 # anything available to root them to). 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 # dedup 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 # foo=--1.2 203 oldVersion, oldFlavor = None, None 204 205 applyList.append((troveName, (oldVersion, oldFlavor), 206 (newVersion, newFlavor), False)) 207 208 # dedup, but keep ordering - this is a little slower but can be handy 209 # for lining up input -> output (if input is deduped) 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
218 -def toTroveSpec(name, versionStr, flavor):
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
259 -class TroveSpecError(errors.ParseError):
260 - def __init__(self, spec, error):
261 self.spec = spec 262 errors.ParseError.