diff --git a/src/littlefs/__main__.py b/src/littlefs/__main__.py index f92b077..7119994 100644 --- a/src/littlefs/__main__.py +++ b/src/littlefs/__main__.py @@ -85,7 +85,7 @@ def create(parser: argparse.ArgumentParser, args: argparse.Namespace) -> int: source = Path(args.source).absolute() if source.is_dir(): - sources = _walk_all(source) + sources = list(_walk_all(source)) root = source else: sources = [source] @@ -108,15 +108,13 @@ def create(parser: argparse.ArgumentParser, args: argparse.Namespace) -> int: if args.verbose: print(f"Compacting... {fs.used_block_count} / {args.block_count}") compact_fs = _fs_from_args(args, block_count=fs.used_block_count) - for root, dirs, files in fs.walk("/"): - if not root.endswith("/"): - root += "/" - for _dir in dirs: - compact_fs.makedirs(root + _dir, exist_ok=True) - for file in files: - path = root + file - with fs.open(path, "rb") as src, compact_fs.open(path, "wb") as dest: - dest.write(src.read()) + for path in sources: + rel_path = path.relative_to(root) + if path.is_dir(): + compact_fs.mkdir(rel_path.as_posix()) + else: + with compact_fs.open(rel_path.as_posix(), "wb") as dest: + dest.write(path.read_bytes()) compact_fs.fs_grow(args.block_count) data = compact_fs.context.buffer if not args.no_pad: diff --git a/test/cli/test_create_and_extract.py b/test/cli/test_create_and_extract.py index f27c407..9be48ed 100644 --- a/test/cli/test_create_and_extract.py +++ b/test/cli/test_create_and_extract.py @@ -1,6 +1,8 @@ from pathlib import Path import filecmp +import pytest + from littlefs.__main__ import main @@ -50,3 +52,50 @@ def test_create_and_extract(tmp_path): # Verify file contents assert (extract_dir / "file1.txt").read_text() == "hello world" assert (extract_dir / "subdir" / "file2.txt").read_text() == "test content" + + +@pytest.mark.parametrize( + "num_files, file_size", + [ + (1, 10), + (5, 100), + (10, 200), + (15, 300), + (20, 400), + (30, 500), + (1, 10000), + (5, 5000), + ], +) +def test_create_compact_roundtrip(tmp_path, num_files, file_size): + """Test that --compact creates a valid image with all files preserved.""" + source_dir = tmp_path / "source" + source_dir.mkdir() + + # Create source files with deterministic content + for i in range(num_files): + (source_dir / f"file_{i}.txt").write_text(f"content_{i}_" + "x" * file_size) + + image_file = tmp_path / "test_compact.bin" + create_argv = [ + "littlefs", "create", str(source_dir), str(image_file), + "--block-size", "512", "--fs-size", "64KB", + "--compact", "--no-pad", + ] + + assert main(create_argv) == 0 + assert image_file.exists() + assert image_file.stat().st_size < 64 * 1024 + + # Extract and verify all files survived compaction + extract_dir = tmp_path / "extracted" + extract_argv = [ + "littlefs", "extract", str(image_file), str(extract_dir), + "--block-size", "512", + ] + assert main(extract_argv) == 0 + + for i in range(num_files): + extracted_file = extract_dir / f"file_{i}.txt" + assert extracted_file.exists(), f"file_{i}.txt missing from compact image" + assert extracted_file.read_text() == f"content_{i}_" + "x" * file_size