Skip to content

Commit

Permalink
fix: fix crash on repeated export with long filenames
Browse files Browse the repository at this point in the history
fix #26
  • Loading branch information
vzhd1701 committed Aug 23, 2022
1 parent 9cbc19e commit 692a93a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
32 changes: 18 additions & 14 deletions evernote_backup/note_exporter_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _get(self, *paths: str, is_dir: bool, overwrite: bool) -> Path:

def _get_safe_path(target_dir: Path, new_name: str, overwrite: bool = False) -> Path:
file_name = _replace_bad_characters(new_name)
file_name = _trim_name(file_name)
file_name = _trim_name(Path(file_name).stem, Path(file_name).suffix)

if not overwrite:
file_name = _get_non_existant_name(file_name, target_dir)
Expand All @@ -76,19 +76,23 @@ def _replace_bad_characters(string: str) -> str:
def _get_non_existant_name(file_name: str, target_dir: Path) -> str:
i = 0
orig = Path(file_name)

while (target_dir / file_name).exists():
i += 1
file_name = f"{orig.stem} ({i}){orig.suffix}"
if len(file_name) > MAX_FILE_NAME_LEN:
max_len = MAX_FILE_NAME_LEN - len(f" ({i}){orig.suffix}")

trimmed_name = _trim_name(orig.stem, max_len)
file_name = f"{trimmed_name} ({i}){orig.suffix}"
suffix = f" ({i}){orig.suffix}"
file_name = f"{orig.stem}{suffix}"

if len(file_name.encode("utf-8")) > MAX_FILE_NAME_LEN:
max_len = MAX_FILE_NAME_LEN - len(suffix.encode("utf-8"))

trimmed_name = _trim_name(orig.stem, "", max_len)
file_name = f"{trimmed_name}{suffix}"

return file_name


def _trim_name(file_name: str, max_len: int = MAX_FILE_NAME_LEN) -> str:
def _trim_name(file_name: str, file_ext: str, max_len: int = MAX_FILE_NAME_LEN) -> str:
"""Trim file name to 255 characters while maintaining extension
255 characters is max file name length on linux and macOS
Windows has a filename limit of 260 bytes
Expand All @@ -100,19 +104,19 @@ def _trim_name(file_name: str, max_len: int = MAX_FILE_NAME_LEN) -> str:
Raises: ValueError if the file name is too long and cannot be trimmed
"""
if len(file_name.encode("utf-8")) <= max_len:
return file_name
orig_name = f"{file_name}{file_ext}"

orig = Path(file_name)
if len(orig_name.encode("utf-8")) <= max_len:
return orig_name

if orig.suffix:
max_len_name = max_len - len(orig.suffix.encode("utf-8"))
if file_ext:
max_len_name = max_len - len(file_ext.encode("utf-8"))
else:
max_len_name = max_len

trimmed_name = _trim_string(orig.stem, max_len_name)
trimmed_name = _trim_string(file_name, max_len_name)

result_name = f"{trimmed_name}{orig.suffix}"
result_name = f"{trimmed_name}{file_ext}"

if len(result_name.encode("utf-8")) > max_len:
raise ValueError(
Expand Down
24 changes: 23 additions & 1 deletion tests/test_note_exporter_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,36 @@ def test_safe_path_long_file_name_no_ext(tmp_path):
assert result_file_path == expected_file


def test_safe_path_long_file_name_existing_unicode(tmp_path):
"""Test that SafePath trims a long file name with no extension"""
test_dir = tmp_path / "test"

slightly_longer_than_supported = MAX_FILE_NAME_LEN * 2

long_file_name = ("😁" * slightly_longer_than_supported) + ".enex"

expected_file_name = ("😁" * 61) + " (1).enex"
expected_file = tmp_path / "test" / "test1" / expected_file_name

safe_path = SafePath(test_dir)
result_file_path = safe_path.get_file("test1", long_file_name)
result_file_path.touch()

result_file_path_repeat = safe_path.get_file("test1", long_file_name)
result_file_path_repeat.touch()

assert expected_file.is_file()
assert result_file_path_repeat == expected_file


def test_safe_path_long_file_name_no_ext_unicode(tmp_path):
"""Test that SafePath trims a long file name with no extension"""
test_dir = tmp_path / "test"

slightly_longer_than_supported = MAX_FILE_NAME_LEN * 2

long_file_name = "😁" * slightly_longer_than_supported
expected_file_name = "😁" * (MAX_FILE_NAME_LEN // len("😁".encode("utf-8")))
expected_file_name = "😁" * 63
expected_file = tmp_path / "test" / "test1" / expected_file_name

safe_path = SafePath(test_dir)
Expand Down

0 comments on commit 692a93a

Please sign in to comment.