Skip to content

Commit f96f039

Browse files
committed
Support recursive directory addition to payload
1 parent b5ba581 commit f96f039

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

src/bagit/__init__.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -550,13 +550,13 @@ def add_payload(self, src, dest=None, processes=1):
550550
"""
551551
Copy a file into the payload directory and rebuild manifests.
552552
"""
553-
if not os.path.isfile(src):
554-
raise ValueError("Payload source must be a file: %s" % src)
553+
if not os.path.isfile(src) and not os.path.isdir(src):
554+
raise ValueError("Payload source must be a file or directory: %s" % src)
555555

556556
if dest is None:
557557
dest = os.path.basename(src)
558558

559-
payload_dest = os.path.normpath(dest)
559+
dest = os.path.normpath(dest)
560560

561561
if os.path.isabs(dest) or dest.startswith("..") or os.path.expanduser(dest) != dest:
562562
raise ValueError("Payload destination is unsafe: %s" % dest)
@@ -567,12 +567,19 @@ def add_payload(self, src, dest=None, processes=1):
567567
raise ValueError("Payload destination is unsafe: %s" % dest)
568568

569569
dst = os.path.join(self.path, payload_dest)
570-
dst_dir = os.path.dirname(dst)
571570

572-
if not os.path.isdir(dst_dir):
573-
os.makedirs(dst_dir)
571+
if os.path.isfile(src):
572+
dst_dir = os.path.dirname(dst)
573+
if not os.path.isdir(dst_dir):
574+
os.makedirs(dst_dir)
574575

575-
shutil.copy2(src, dst)
576+
shutil.copy2(src, dst)
577+
578+
elif os.path.isdir(src):
579+
if os.path.exists(dst):
580+
raise ValueError("Payload destination already exists: %s" % dest)
581+
582+
shutil.copytree(src, dst)
576583

577584
self.update_payload(processes=processes)
578585

test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,49 @@ def test_remove_payload_directory_requires_recursive(self):
12091209
with self.assertRaises(ValueError):
12101210
bag.remove_payload("data/extra")
12111211

1212+
def test_add_payload_directory(self):
1213+
bag = bagit.make_bag(self.tmpdir)
1214+
1215+
src_dir = tempfile.mkdtemp()
1216+
try:
1217+
with open(j(src_dir, "one.txt"), "w") as f:
1218+
f.write("one")
1219+
1220+
os.mkdir(j(src_dir, "nested"))
1221+
1222+
with open(j(src_dir, "nested", "two.txt"), "w") as f:
1223+
f.write("two")
1224+
1225+
bag.add_payload(src_dir)
1226+
1227+
dest_dir = j(self.tmpdir, "data", os.path.basename(src_dir))
1228+
1229+
self.assertTrue(os.path.isdir(dest_dir))
1230+
self.assertTrue(os.path.isfile(j(dest_dir, "one.txt")))
1231+
self.assertTrue(os.path.isfile(j(dest_dir, "nested", "two.txt")))
1232+
1233+
bag = bagit.Bag(self.tmpdir)
1234+
self.assertTrue(bag.is_valid())
1235+
finally:
1236+
shutil.rmtree(src_dir)
1237+
1238+
def test_add_payload_directory_with_destination(self):
1239+
bag = bagit.make_bag(self.tmpdir)
1240+
1241+
src_dir = tempfile.mkdtemp()
1242+
try:
1243+
with open(j(src_dir, "one.txt"), "w") as f:
1244+
f.write("one")
1245+
1246+
bag.add_payload(src_dir, "imports/sip")
1247+
1248+
self.assertTrue(os.path.isdir(j(self.tmpdir, "data", "imports", "sip")))
1249+
self.assertTrue(os.path.isfile(j(self.tmpdir, "data", "imports", "sip", "one.txt")))
1250+
1251+
bag = bagit.Bag(self.tmpdir)
1252+
self.assertTrue(bag.is_valid())
1253+
finally:
1254+
shutil.rmtree(src_dir)
12121255

12131256

12141257
class TestFetch(SelfCleaningTestCase):

0 commit comments

Comments
 (0)