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

Source Code for Module conary.conaryclient.branch

  1  # 
  2  # Copyright (c) 2005-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  from conary.deps import deps 
 15  from conary.repository import changeset 
 16  from conary import errors 
 17  from conary import versions 
 18   
19 -class BranchError(errors.ClientError):
20 pass
21
22 -class ClientBranch:
23 BRANCH_SOURCE = 1 << 0 24 BRANCH_BINARY = 1 << 1 25 BRANCH_ALL = BRANCH_SOURCE | BRANCH_BINARY 26
27 - def createBranchChangeSet(self, newLabel, 28 troveList = [], branchType=BRANCH_ALL, 29 sigKeyId = None):
30 return self._createBranchOrShadow(newLabel, troveList, shadow = False, 31 branchType = branchType, 32 sigKeyId = sigKeyId)
33
34 - def createShadowChangeSet(self, newLabel, troveList = [], 35 branchType=BRANCH_ALL, 36 sigKeyId = None):
37 return self._createBranchOrShadow(newLabel, troveList, shadow = True, 38 branchType = branchType, 39 sigKeyId = sigKeyId)
40
41 - def _checkForLaterShadows(self, newLabel, troves):
42 # check to see if we've already shadowed any versions later than 43 # these versions to newLabel. 44 query = {} 45 for trove in troves: 46 versionDict = query.setdefault(trove.getName(), {}) 47 b = trove.getVersion().branch().createShadow(newLabel) 48 versionDict[b] = None 49 # get the latest version of the new branches 50 results = self.repos.getTroveLeavesByBranch(query) 51 52 if not results: 53 return [] 54 55 oldTroves = [] 56 for trove in troves: 57 versionDict = results.get(trove.getName(), {}) 58 b = trove.getVersion().branch().createShadow(newLabel) 59 versionList = [ x for x in versionDict if x.branch() == b and not x.isModifiedShadow() ] 60 if not versionList: 61 continue 62 latestVersion = max(versionList) 63 oldVersion = latestVersion.parentVersion() 64 # now get the upstream timeStamps associated with the already 65 # shadowed versions. 66 oldTroves.extend((trove.getName(), oldVersion, x) \ 67 for x in versionDict[latestVersion]) 68 69 shadowedTroves = self.repos.getTroves(oldTroves, withFiles=False) 70 71 shadowed = {} 72 for shadowedTrove in shadowedTroves: 73 (n,v,f) = shadowedTrove.getNameVersionFlavor() 74 shadowed[n, v.branch(), f] = v 75 76 laterShadows = [] 77 for trove in troves: 78 (n,v,f) = trove.getNameVersionFlavor() 79 shadowedVer = shadowed.get((n, v.branch(), f), None) 80 if not shadowedVer: 81 continue 82 if v < shadowedVer: 83 # the version we shadowed before had a later timestamp 84 # than the version we're shadowing now. 85 laterShadows.append((n, v, f, shadowedVer)) 86 return laterShadows
87
88 - def _createBranchOrShadow(self, newLabel, troveList, shadow, 89 branchType=BRANCH_ALL, sigKeyId = None):
90 cs = changeset.ChangeSet() 91 92 seen = set(troveList) 93 dupList = [] 94 needsCommit = False 95 96 newLabel = versions.Label(newLabel) 97 98 while troveList: 99 leavesByLabelOps = {} 100 101 troves = self.repos.getTroves(troveList) 102 troveList = set() 103 branchedTroves = {} 104 105 if shadow: 106 laterShadows = self._checkForLaterShadows(newLabel, troves) 107 # we disallow shadowing an earlier trove if a later 108 # later one has already been shadowed - it makes our 109 # cvc merge algorithm not work well. 110 if laterShadows: 111 msg = [] 112 for n, v, f, shadowedVer in laterShadows: 113 msg.append('''\ 114 Cannot shadow backwards - already shadowed 115 %s=%s[%s] 116 cannot shadow earlier trove 117 %s=%s[%s] 118 ''' % (n, shadowedVer, f, n, v, f)) 119 raise BranchError('\n\n'.join(msg)) 120 121 for trove in troves: 122 if trove.isRedirect(): 123 raise errors.ShadowRedirect(*trove.getNameVersionFlavor()) 124 125 # add contained troves to the todo-list 126 newTroves = [ x for x in 127 trove.iterTroveList(strongRefs=True, 128 weakRefs=True) if x not in seen ] 129 troveList.update(newTroves) 130 seen.update(newTroves) 131 132 troveName = trove.getName() 133 134 if troveName.endswith(':source'): 135 if not(branchType & self.BRANCH_SOURCE): 136 continue 137 138 elif branchType & self.BRANCH_SOURCE: 139 # name doesn't end in :source - if we want 140 # to shadow the listed troves' sources, do so now 141 142 # XXX this can go away once we don't care about 143 # pre-troveInfo troves 144 if not trove.getSourceName(): 145 from conary.lib import log 146 log.warning('%s has no source information' % troveName) 147 sourceName = troveName 148 else: 149 sourceName = trove.getSourceName() 150 151 key = (sourceName, 152 trove.getVersion().getSourceVersion(False), 153 deps.Flavor()) 154 if key not in seen: 155 troveList.add(key) 156 seen.add(key) 157 158 if not(branchType & self.BRANCH_BINARY): 159 continue 160 161 if shadow: 162 branchedVersion = trove.getVersion().createShadow(newLabel) 163 else: 164 branchedVersion = trove.getVersion().createBranch(newLabel, 165 withVerRel = 1) 166 167 branchedTrove = trove.copy() 168 branchedTrove.changeVersion(branchedVersion) 169 #this clears the digital signatures from the shadow 170 branchedTrove.troveInfo.sigs.reset() 171 # this flattens the old metadata and removes signatures 172 branchedTrove.copyMetadata(trove) 173 # FIXME we should add a new digital signature in cases 174 # where we can (aka user is at kb and can provide secret key 175 176 for ((name, version, flavor), byDefault, isStrong) \ 177 in trove.iterTroveListInfo(): 178 if shadow: 179 branchedVersion = version.createShadow(newLabel) 180 else: 181 branchedVersion = version.createBranch(newLabel, 182 withVerRel = 1) 183 branchedTrove.delTrove(name, version, flavor, 184 missingOkay = False, 185 weakRef=not isStrong) 186 branchedTrove.addTrove(name, branchedVersion, flavor, 187 byDefault=byDefault, 188 weakRef=not isStrong) 189 190 key = (trove.getName(), branchedTrove.getVersion(), 191 trove.getFlavor()) 192 193 if sigKeyId is not