279
279
stored and retrieved.
282
def __init__(self, relpath, transport, file_mode=None, access_mode=None,
282
def __init__(self, relpath, transport, file_mode=None, access_mode=None,
283
283
factory=None, basis_knit=DEPRECATED_PARAMETER, delta=True,
284
create=False, create_parent_dir=False, delay_create=False,
285
286
"""Construct a knit at location specified by relpath.
287
288
:param create: If not True, only open an existing knit.
289
:param create_parent_dir: If True, create the parent directory if
290
creating the file fails. (This is used for stores with
291
hash-prefixes that may not exist yet)
292
:param delay_create: The calling code is aware that the knit won't
293
actually be created until the first data is stored.
289
295
if deprecated_passed(basis_knit):
290
296
warnings.warn("KnitVersionedFile.__(): The basis_knit parameter is"
301
307
self.delta = delta
303
309
self._index = _KnitIndex(transport, relpath + INDEX_SUFFIX,
304
access_mode, create=create, file_mode=file_mode)
310
access_mode, create=create, file_mode=file_mode,
311
create_parent_dir=create_parent_dir, delay_create=delay_create,
305
313
self._data = _KnitData(transport, relpath + DATA_SUFFIX,
306
access_mode, create=create and not len(self), file_mode=file_mode)
314
access_mode, create=create and not len(self), file_mode=file_mode,
315
create_parent_dir=create_parent_dir, delay_create=delay_create,
308
318
def __repr__(self):
309
319
return '%s(%s)' % (self.__class__.__name__,
948
958
class _KnitComponentFile(object):
949
959
"""One of the files used to implement a knit database"""
951
def __init__(self, transport, filename, mode, file_mode=None):
961
def __init__(self, transport, filename, mode, file_mode=None,
962
create_parent_dir=False, dir_mode=None):
952
963
self._transport = transport
953
964
self._filename = filename
954
965
self._mode = mode
955
self._file_mode=file_mode
957
def write_header(self):
958
if self._transport.put_bytes_non_atomic(self._filename, self.HEADER,
959
mode=self._file_mode):
960
raise KnitCorrupt(self._filename, 'misaligned after writing header')
966
self._file_mode = file_mode
967
self._dir_mode = dir_mode
968
self._create_parent_dir = create_parent_dir
969
self._need_to_create = False
962
971
def check_header(self, fp):
963
972
line = fp.readline()
1053
def __init__(self, transport, filename, mode, create=False, file_mode=None):
1054
_KnitComponentFile.__init__(self, transport, filename, mode, file_mode)
1062
def __init__(self, transport, filename, mode, create=False, file_mode=None,
1063
create_parent_dir=False, delay_create=False, dir_mode=None):
1064
_KnitComponentFile.__init__(self, transport, filename, mode,
1065
file_mode=file_mode,
1066
create_parent_dir=create_parent_dir,
1055
1068
self._cache = {}
1056
1069
# position in _history is the 'official' index for a revision
1057
1070
# but the values may have come from a newer entry.
1126
1139
except NoSuchFile, e:
1127
1140
if mode != 'w' or not create:
1143
self._need_to_create = True
1145
self._transport.put_bytes_non_atomic(self._filename,
1146
self.HEADER, mode=self._file_mode)
1131
1149
pb.update('read knit index', total, total)
1247
1265
assert isinstance(line, str), \
1248
1266
'content must be utf-8 encoded: %r' % (line,)
1249
1267
lines.append(line)
1250
self._transport.append_bytes(self._filename, ''.join(lines))
1268
if not self._need_to_create:
1269
self._transport.append_bytes(self._filename, ''.join(lines))
1272
sio.write(self.HEADER)
1273
sio.writelines(lines)
1275
self._transport.put_file_non_atomic(self._filename, sio,
1276
create_parent_dir=self._create_parent_dir,
1277
mode=self._file_mode,
1278
dir_mode=self._dir_mode)
1279
self._need_to_create = False
1251
1281
# cache after writing, so that a failed write leads to missing cache
1252
1282
# entries not extra ones. XXX TODO: RBC 20060502 in the event of a
1253
1283
# failure, reload the index or flush it or some such, to prevent
1298
1328
class _KnitData(_KnitComponentFile):
1299
1329
"""Contents of the knit data file"""
1301
HEADER = "# bzr knit data 8\n"
1303
def __init__(self, transport, filename, mode, create=False, file_mode=None):
1304
_KnitComponentFile.__init__(self, transport, filename, mode)
1331
def __init__(self, transport, filename, mode, create=False, file_mode=None,
1332
create_parent_dir=False, delay_create=False,
1334
_KnitComponentFile.__init__(self, transport, filename, mode,
1335
file_mode=file_mode,
1336
create_parent_dir=create_parent_dir,
1305
1338
self._checked = False
1306
1339
# TODO: jam 20060713 conceptually, this could spill to disk
1307
1340
# if the cached size gets larger than a certain amount
1310
1343
self._cache = {}
1311
1344
self._do_cache = False
1313
self._transport.put_bytes_non_atomic(self._filename, '',
1347
self._need_to_create = create
1349
self._transport.put_bytes_non_atomic(self._filename, '',
1350
mode=self._file_mode)
1316
1352
def enable_cache(self):
1317
1353
"""Enable caching of reads."""
1356
1392
:return: the offset in the data file raw_data was written.
1358
1394
assert isinstance(raw_data, str), 'data must be plain bytes'
1359
return self._transport.append_bytes(self._filename, raw_data)
1395
if not self._need_to_create:
1396
return self._transport.append_bytes(self._filename, raw_data)
1398
self._transport.put_bytes_non_atomic(self._filename, raw_data,
1399
create_parent_dir=self._create_parent_dir,
1400
mode=self._file_mode,
1401
dir_mode=self._dir_mode)
1402
self._need_to_create = False
1361
1405
def add_record(self, version_id, digest, lines):
1362
1406
"""Write new text record to disk. Returns the position in the
1363
1407
file where it was written."""
1364
1408
size, sio = self._record_to_data(version_id, digest, lines)
1365
1409
# write to disk
1366
start_pos = self._transport.append_file(self._filename, sio)
1410
if not self._need_to_create:
1411
start_pos = self._transport.append_file(self._filename, sio)
1413
self._transport.put_file_non_atomic(self._filename, sio,
1414
create_parent_dir=self._create_parent_dir,
1415
mode=self._file_mode,
1416
dir_mode=self._dir_mode)
1417
self._need_to_create = False
1367
1419
if self._do_cache:
1368
1420
self._cache[version_id] = sio.getvalue()
1369
1421
return start_pos, size