509
510
raise NotImplementedError('fileid_involved_by_set is abstract')
512
def fileid_involved_between_revs(self, from_revid, to_revid):
513
""" This function returns the file_id(s) involved in the
514
changes between the from_revid revision and the to_revid
517
raise NotImplementedError('fileid_involved_between_revs is abstract')
519
def fileid_involved(self, last_revid=None):
520
""" This function returns the file_id(s) involved in the
521
changes up to the revision last_revid
522
If no parametr is passed, then all file_id[s] present in the
523
repository are returned
525
raise NotImplementedError('fileid_involved is abstract')
527
def fileid_involved_by_set(self, changes):
528
""" This function returns the file_id(s) involved in the
529
changes present in the set 'changes'
531
raise NotImplementedError('fileid_involved_by_set is abstract')
511
534
class BzrBranch(Branch):
512
535
"""A branch stored in the actual filesystem.
828
851
('pending-merges', ''),
829
852
('inventory', empty_inv),
830
853
('inventory.weave', empty_weave),
831
('ancestry.weave', empty_weave)
833
855
self._transport.mkdir_multi([cfn(d) for d in dirs], mode=self._dir_mode)
834
856
self.put_controlfiles(files)
1137
1159
revision_id, "sig")
1139
1161
def fileid_involved_between_revs(self, from_revid, to_revid):
1140
""" This function returns the file_id(s) involved in the
1141
changes between the from_revid revision and the to_revid
1162
"""Find file_id(s) which are involved in the changes between revisions.
1164
This determines the set of revisions which are involved, and then
1165
finds all file ids affected by those revisions.
1144
w = self._get_inventory_weave( )
1167
# TODO: jam 20060119 This code assumes that w.inclusions will
1168
# always be correct. But because of the presence of ghosts
1169
# it is possible to be wrong.
1170
# One specific example from Robert Collins:
1171
# Two branches, with revisions ABC, and AD
1172
# C is a ghost merge of D.
1173
# Inclusions doesn't recognize D as an ancestor.
1174
# If D is ever merged in the future, the weave
1175
# won't be fixed, because AD never saw revision C
1176
# to cause a conflict which would force a reweave.
1177
w = self._get_inventory_weave()
1145
1178
from_set = set(w.inclusions([w.lookup(from_revid)]))
1146
1179
to_set = set(w.inclusions([w.lookup(to_revid)]))
1147
1180
included = to_set.difference(from_set)
1148
changed = map(w.idx_to_name,included)
1181
changed = map(w.idx_to_name, included)
1149
1182
return self._fileid_involved_by_set(changed)
1151
1184
def fileid_involved(self, last_revid=None):
1152
""" This function returns the file_id(s) involved in the
1153
changes up to the revision last_revid
1154
If no parametr is passed, then all file_id[s] present in the
1155
repository are returned
1185
"""Find all file_ids modified in the ancestry of last_revid.
1187
:param last_revid: If None, last_revision() will be used.
1157
w = self._get_inventory_weave( )
1189
w = self._get_inventory_weave()
1158
1190
if not last_revid:
1159
1191
changed = set(w._names)
1163
1195
return self._fileid_involved_by_set(changed)
1165
1197
def fileid_involved_by_set(self, changes):
1166
""" This function returns the file_id(s) involved in the
1167
changese present in the set changes
1198
"""Find all file_ids modified by the set of revisions passed in.
1200
:param changes: A set() of revision ids
1169
w = self._get_inventory_weave( )
1202
# TODO: jam 20060119 This line does *nothing*, remove it.
1203
# or better yet, change _fileid_involved_by_set so
1204
# that it takes the inventory weave, rather than
1205
# pulling it out by itself.
1206
w = self._get_inventory_weave()
1170
1207
return self._fileid_involved_by_set(changes)
1172
1209
def _fileid_involved_by_set(self, changes):
1173
w = self._get_inventory_weave( )
1210
"""Find the set of file-ids affected by the set of revisions.
1212
:param changes: A set() of revision ids.
1213
:return: A set() of file ids.
1215
This peaks at the Weave, interpreting each line, looking to
1216
see if it mentions one of the revisions. And if so, includes
1217
the file id mentioned.
1218
This expects both the Weave format, and the serialization
1219
to have a single line per file/directory, and to have
1220
fileid="" and revision="" on that line.
1222
assert self._branch_format in (5, 6), \
1223
"fileid_involved only supported for branches which store inventory as xml"
1225
w = self._get_inventory_weave()
1175
1227
for line in w._weave:
1177
1229
# it is ugly, but it is due to the weave structure
1178
if not isinstance(line,basestring): continue
1230
if not isinstance(line, basestring): continue
1180
1232
start = line.find('file_id="')+9
1181
1233
if start < 9: continue
1182
end = line.find('"',start)
1234
end = line.find('"', start)
1184
file_id = line[start:end]
1236
file_id = xml.sax.saxutils.unescape(line[start:end])
1186
1238
# check if file_id is already present
1187
1239
if file_id in file_ids: continue
1189
1241
start = line.find('revision="')+10
1190
1242
if start < 10: continue
1191
end = line.find('"',start)
1243
end = line.find('"', start)
1193
revision_id = line[start:end]
1245
revision_id = xml.sax.saxutils.unescape(line[start:end])
1195
1247
if revision_id in changes:
1196
1248
file_ids.add(file_id)
1261
1313
filename = normpath(filename)
1262
1314
while filename != '':
1263
1315
head, tail = os.path.split(filename)
1264
## mutter('check %r for control file' % ((head, tail), ))
1316
## mutter('check %r for control file' % ((head, tail),))
1265
1317
if tail == bzrlib.BZRDIR:
1267
1319
if filename == head: