Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/littlefs/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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:
Expand Down
49 changes: 49 additions & 0 deletions test/cli/test_create_and_extract.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from pathlib import Path
import filecmp

import pytest

from littlefs.__main__ import main


Expand Down Expand Up @@ -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
Loading