145
160
control = bzrdir.BzrDir.open(base)
146
161
return control.open_repository()
163
def push_stores(self, to, revision=NULL_REVISION):
164
"""FIXME: document and find a consistent name with other classes."""
165
if (not isinstance(self._format, RepositoryFormat4) or
166
self._format != to._format):
167
from bzrlib.fetch import RepoFetcher
168
mutter("Using fetch logic to push between %s(%s) and %s(%s)",
169
self, self._format, to, to._format)
170
RepoFetcher(to_repository=to, from_repository=self,
171
last_revision=revision)
174
# format 4 to format 4 logic only.
175
store_pairs = ((self.text_store, to.text_store),
176
(self.inventory_store, to.inventory_store),
177
(self.revision_store, to.revision_store))
179
for from_store, to_store in store_pairs:
180
copy_all(from_store, to_store)
181
except UnlistableStore:
182
raise UnlistableBranch(from_store)
148
184
def unlock(self):
149
185
self.control_files.unlock()
188
def clone(self, a_bzrdir):
189
"""Clone this repository into a_bzrdir using the current format.
191
Currently no check is made that the format of this repository and
192
the bzrdir format are compatible. FIXME RBC 20060201.
194
result = self._format.initialize(a_bzrdir)
152
199
def copy(self, destination):
153
200
destination.lock_write()
212
259
self.revision_store.add(StringIO(gpg_strategy.sign(plaintext)),
213
260
revision_id, "sig")
262
def fileid_involved_between_revs(self, from_revid, to_revid):
263
"""Find file_id(s) which are involved in the changes between revisions.
265
This determines the set of revisions which are involved, and then
266
finds all file ids affected by those revisions.
268
# TODO: jam 20060119 This code assumes that w.inclusions will
269
# always be correct. But because of the presence of ghosts
270
# it is possible to be wrong.
271
# One specific example from Robert Collins:
272
# Two branches, with revisions ABC, and AD
273
# C is a ghost merge of D.
274
# Inclusions doesn't recognize D as an ancestor.
275
# If D is ever merged in the future, the weave
276
# won't be fixed, because AD never saw revision C
277
# to cause a conflict which would force a reweave.
278
w = self.get_inventory_weave()
279
from_set = set(w.inclusions([w.lookup(from_revid)]))
280
to_set = set(w.inclusions([w.lookup(to_revid)]))
281
included = to_set.difference(from_set)
282
changed = map(w.idx_to_name, included)
283
return self._fileid_involved_by_set(changed)
285
def fileid_involved(self, last_revid=None):
286
"""Find all file_ids modified in the ancestry of last_revid.
288
:param last_revid: If None, last_revision() will be used.
290
w = self.get_inventory_weave()
292
changed = set(w._names)
294
included = w.inclusions([w.lookup(last_revid)])
295
changed = map(w.idx_to_name, included)
296
return self._fileid_involved_by_set(changed)
298
def fileid_involved_by_set(self, changes):
299
"""Find all file_ids modified by the set of revisions passed in.
301
:param changes: A set() of revision ids
303
# TODO: jam 20060119 This line does *nothing*, remove it.
304
# or better yet, change _fileid_involved_by_set so
305
# that it takes the inventory weave, rather than
306
# pulling it out by itself.
307
return self._fileid_involved_by_set(changes)
309
def _fileid_involved_by_set(self, changes):
310
"""Find the set of file-ids affected by the set of revisions.
312
:param changes: A set() of revision ids.
313
:return: A set() of file ids.
315
This peaks at the Weave, interpreting each line, looking to
316
see if it mentions one of the revisions. And if so, includes
317
the file id mentioned.
318
This expects both the Weave format, and the serialization
319
to have a single line per file/directory, and to have
320
fileid="" and revision="" on that line.
322
assert (isinstance(self._format, RepositoryFormat5) or
323
isinstance(self._format, RepositoryFormat6)), \
324
"fileid_involved only supported for branches which store inventory as xml"
326
w = self.get_inventory_weave()
328
for line in w._weave:
330
# it is ugly, but it is due to the weave structure
331
if not isinstance(line, basestring): continue
333
start = line.find('file_id="')+9
334
if start < 9: continue
335
end = line.find('"', start)
337
file_id = xml.sax.saxutils.unescape(line[start:end])
339
# check if file_id is already present
340
if file_id in file_ids: continue
342
start = line.find('revision="')+10
343
if start < 10: continue
344
end = line.find('"', start)
346
revision_id = xml.sax.saxutils.unescape(line[start:end])
348
if revision_id in changes:
349
file_ids.add(file_id)
216
353
def get_inventory_weave(self):
217
354
return self.control_weaves.get_weave('inventory',