Skip to content

Commit 0b74673

Browse files
committed
save only regenerates manifests when told to; this guards against recreating manifests for invalid bags
1 parent 51c2851 commit 0b74673

File tree

2 files changed

+52
-32
lines changed

2 files changed

+52
-32
lines changed

bagit.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -256,42 +256,53 @@ def payload_entries(self):
256256
return dict((key, value) for (key, value) in self.entries.iteritems() \
257257
if key.startswith("data" + os.sep))
258258

259-
def save(self, processes=1):
259+
def save(self, processes=1, manifests=False):
260260
"""
261-
If the contents of the payload directory have changed, this will update
262-
the bag for the new or removed files. Any changes made to bag metadata
263-
will also be saved and tag manifests will be updated.
261+
save will persist any changes that have been made to the bag
262+
metadata (self.info).
263+
264+
If you have modified the payload of the bag (added, modified,
265+
removed files in the data directory) and want to regenerate manifests
266+
set the manifests parameter to True. The default is False since you
267+
wouldn't want a save to accidentally create a new manifest for
268+
a corrupted bag.
269+
270+
If you want to control the number of processes that are used when
271+
recalculating checksums use the processes parameter.
264272
"""
265273
# Error checking
266274
if not self.path:
267275
raise BagError("Bag does not have a path.")
268-
unbaggable = _can_bag(self.path)
269-
if unbaggable:
270-
logging.error("no write permissions for the following directories and files: \n%s", unbaggable)
271-
raise BagError("Not all files/folders can be moved.")
272-
unreadable_dirs, unreadable_files = _can_read(self.path)
273-
if unreadable_dirs or unreadable_files:
274-
if unreadable_dirs:
275-
logging.error("The following directories do not have read permissions: \n%s", unreadable_dirs)
276-
if unreadable_files:
277-
logging.error("The following files do not have read permissions: \n%s", unreadable_files)
278-
raise BagError("Read permissions are required to calculate file fixities.")
279276

280277
# Change working directory to bag directory so helper functions work
281278
old_dir = os.path.abspath(os.path.curdir)
282279
os.chdir(self.path)
283280

284281
# Generate new manifest files
285-
oxum = None
286-
self.algs = list(set(self.algs)) # Dedupe
287-
for alg in self.algs:
288-
logging.info('updating manifest-%s.txt', alg)
289-
oxum = _make_manifest('manifest-%s.txt' % alg, 'data', processes, alg)
282+
if manifests:
283+
unbaggable = _can_bag(self.path)
284+
if unbaggable:
285+
logging.error("no write permissions for the following directories and files: \n%s", unbaggable)
286+
raise BagError("Not all files/folders can be moved.")
287+
unreadable_dirs, unreadable_files = _can_read(self.path)
288+
if unreadable_dirs or unreadable_files:
289+
if unreadable_dirs:
290+
logging.error("The following directories do not have read permissions: \n%s", unreadable_dirs)
291+
if unreadable_files:
292+
logging.error("The following files do not have read permissions: \n%s", unreadable_files)
293+
raise BagError("Read permissions are required to calculate file fixities.")
294+
295+
oxum = None
296+
self.algs = list(set(self.algs)) # Dedupe
297+
for alg in self.algs:
298+
logging.info('updating manifest-%s.txt', alg)
299+
oxum = _make_manifest('manifest-%s.txt' % alg, 'data', processes, alg)
300+
301+
# Update Payload-Oxum
302+
logging.info('updating %s', self.tag_file_name)
303+
if oxum:
304+
self.info['Payload-Oxum'] = oxum
290305

291-
# Update Payload-Oxum
292-
logging.info('updating %s', self.tag_file_name)
293-
if oxum:
294-
self.info['Payload-Oxum'] = oxum
295306
_make_tag_file(self.tag_file_name, self.info)
296307

297308
# Update tag-manifest for changes to manifest & bag-info files

test.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,19 +432,17 @@ def test_payload_permissions(self):
432432
self.assertTrue(perms != new_perms)
433433
os.chmod(self.tmpdir, new_perms)
434434
bag = bagit.make_bag(self.tmpdir)
435-
payload_dir = os.path.join(self.tmpdir, 'data')
435+
payload_dir = j(self.tmpdir, 'data')
436436
self.assertEqual(os.stat(payload_dir).st_mode, new_perms)
437437

438-
def test_save(self):
438+
def test_save_manifests(self):
439439
bag = bagit.make_bag(self.tmpdir)
440440
self.assertTrue(bag.is_valid())
441-
bag.save()
441+
bag.save(manifests=True)
442442
self.assertTrue(bag.is_valid())
443-
f = j(self.tmpdir, "data", "NEWFILE")
444-
with open(f, 'w') as fp:
445-
fp.write("NEWFILE")
443+
open(j(self.tmpdir, "data", "newfile"), 'w').write('newfile')
446444
self.assertRaises(bagit.BagValidationError, bag.validate, bag, fast=False)
447-
bag.save()
445+
bag.save(manifests=True)
448446
self.assertTrue(bag.is_valid())
449447

450448
def test_save_baginfo(self):
@@ -454,14 +452,25 @@ def test_save_baginfo(self):
454452
bag.save()
455453
bag = bagit.Bag(self.tmpdir)
456454
self.assertEqual(bag.info["foo"], "bar")
455+
self.assertTrue(bag.is_valid())
457456

458457
bag.info['x'] = ["a", "b", "c"]
459458
bag.save()
460459
b = bagit.Bag(self.tmpdir)
461460
self.assertEqual(b.info["x"], ["a", "b", "c"])
462-
463461
self.assertTrue(bag.is_valid())
464462

463+
def test_save_only_baginfo(self):
464+
bag = bagit.make_bag(self.tmpdir)
465+
open(j(self.tmpdir, 'data', 'newfile'), 'w').write('newfile')
466+
bag.info["foo"] = "bar"
467+
bag.save()
468+
469+
bag = bagit.Bag(self.tmpdir)
470+
self.assertEqual(bag.info["foo"], "bar")
471+
self.assertFalse(bag.is_valid())
472+
473+
465474
def test_make_bag_with_newline(self):
466475
bag = bagit.make_bag(self.tmpdir, {"test": "foo\nbar"})
467476
self.assertEqual(bag.info["test"], "foobar")

0 commit comments

Comments
 (0)