1
2
3
4
5
6
7
8
9
10
11
12
13 """
14 Implementation of "clone" + "promote" functionality.
15
16 Cloning creates a copy of a trove on a related branch, with the only link
17 back to the original branch being through the "clonedFrom" link.
18 """
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 import itertools
41 import os
42 import tempfile
43 import time
44
45 from conary import callbacks
46 from conary import errors, files
47 from conary import trove
48 from conary import versions
49 from conary.build.nextversion import nextVersions
50 from conary.conarycfg import selectSignatureKey
51 from conary.deps import deps
52 from conary.lib import log
53 from conary.repository import changeset, filecontents
54 from conary.repository import trovesource
55 from conary.repository import errors as neterrors
56
57 V_LOADED = 0
58 V_BREQ = 1
59 V_REFTRV = 2
60
61
62 DEFAULT_MESSAGE = 1
63
66 self.cloneJob = {}
67 self.preCloned = {}
68 self.options = options
69
70 - def add(self, troveTup):
71 self.cloneJob[troveTup] = None
72
74 self.cloneJob.pop(troveTup, False)
75 self.preCloned[troveTup] = True
76
77 - def target(self, troveTup, targetVersion):
78 self.cloneJob[troveTup] = targetVersion
79
82
84 return self.cloneJob.keys()
85
87 return self.preCloned.keys()
88
90 return not self.cloneJob
91
92
93 MAX_CLONE_FILES = 5000
94
95 CHANGESET_MULTIPLE = 3
96
98
99 - def createCloneChangeSet(self, targetBranch, troveList,
100 updateBuildInfo=True, message=DEFAULT_MESSAGE,
101 infoOnly=False, fullRecurse=False,
102 cloneSources=False, callback=None,
103 trackClone=True, excludeGroups=False):
104 targetMap = dict((x[1].branch(), targetBranch) for x in troveList)
105 return self.createTargetedCloneChangeSet(targetMap,
106 troveList,
107 fullRecurse=fullRecurse,
108 cloneSources=cloneSources,
109 trackClone=trackClone,
110 callback=callback,
111 message=message,
112 updateBuildInfo=updateBuildInfo,
113 infoOnly=infoOnly,
114 excludeGroups=excludeGroups)
115
116 - def createTargetedCloneChangeSet(self, targetMap, troveList,
117 updateBuildInfo=True, infoOnly=False,
118 callback=None, message=DEFAULT_MESSAGE,
119 trackClone=True, fullRecurse=True,
120 cloneOnlyByDefaultTroves=False,
121 cloneSources=True, excludeGroups=False):
122 cloneOptions = CloneOptions(fullRecurse=fullRecurse,
123 cloneSources=cloneSources,
124 trackClone=trackClone,
125 callback=callback,
126 message=message,
127 cloneOnlyByDefaultTroves=cloneOnlyByDefaultTroves,
128 updateBuildInfo=updateBuildInfo,
129 infoOnly=infoOnly,
130 bumpGroupVersions=True,
131 excludeGroups=excludeGroups)
132 chooser = CloneChooser(targetMap, troveList, cloneOptions)
133 return self._createCloneChangeSet(chooser, cloneOptions)
134
135 createSiblingCloneChangeSet = createTargetedCloneChangeSet
136
139
141 callback = cloneOptions.callback
142 troveCache = TroveCache(self.repos, callback)
143
144 cloneJob, cloneMap, leafMap = self._createCloneJob(cloneOptions,
145 chooser,
146 troveCache)
147 if cloneJob.isEmpty():
148 log.warning('Nothing to clone!')
149 return False, None
150
151 newTroveList = self._buildTroves(chooser, cloneMap, cloneJob,
152 leafMap, troveCache, callback)
153 if newTroveList is None:
154 return False, None
155
156 _logMe('new troves calculated')
157
158 if cloneOptions.infoOnly:
159
160 cs = changeset.ChangeSet()
161 for oldVersion, newTrove in newTroveList:
162 cs.newTrove(newTrove.diff(None, absolute = True)[0])
163 callback.done()
164 return True, cs
165
166 finalCs = self._buildChangeSet(troveCache, newTroveList, callback)
167
168 callback.prefix = ''
169 callback.done()
170 return True, finalCs
171
175
176
177
178
179
180
181
182
183
184
185
186 searchDict = {}
187 for (fromVersion, finalTrove) in finalTroveList:
188 if not _sameHost(fromVersion, finalTrove.getVersion()):
189 name, version, flavor = finalTrove.getNameVersionFlavor()
190 label = version.trailingLabel()
191 searchDict.setdefault(name, {})
192 searchDict[name].setdefault(label, [])
193 searchDict[name][label].append(flavor)
194
195 matches = self.repos.getTroveLeavesByLabel(searchDict)
196
197 oldTrovesNeeded = []
198 for (fromVersion, finalTrove) in finalTroveList:
199 name, version, flavor = finalTrove.getNameVersionFlavor()
200 if _sameHost(fromVersion, finalTrove.getVersion()):
201 oldTrovesNeeded.append((name, fromVersion, flavor))
202 else:
203 match = None
204 versionD = matches.get(name, {})
205 for matchVersion, flavorList in versionD.iteritems():
206 if (matchVersion.trailingLabel() ==
207 version.trailingLabel()
208 and flavor in flavorList):
209 match = matchVersion
210
211 if match is None:
212
213 oldTrovesNeeded.append(None)
214 else:
215 oldTrovesNeeded.append((name, match, flavor))
216
217 oldTroves = troveCache.getTroves(
218 [ x for x in oldTrovesNeeded if x is not None ], withFiles=True)
219
220
221
222
223
224
225
226
227
228
229
230
231
232 finalCs = changeset.ReadOnlyChangeSet()
233 cs = changeset.ChangeSet()
234 fileCount = 0
235 jobList = [