diff --git a/jrnl/plugins/text_exporter.py b/jrnl/plugins/text_exporter.py index cfd4a8ec..eeb934f9 100644 --- a/jrnl/plugins/text_exporter.py +++ b/jrnl/plugins/text_exporter.py @@ -1,6 +1,7 @@ # Copyright (C) 2012-2022 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html +import errno import os import re import unicodedata @@ -53,9 +54,24 @@ class TextExporter: def write_files(cls, journal, path): """Exports a journal into individual files for each entry.""" for entry in journal.entries: - full_path = os.path.join(path, cls.make_filename(entry)) - with open(full_path, "w", encoding="utf-8") as f: - f.write(cls.export_entry(entry)) + entry_is_written = False + while not entry_is_written: + full_path = os.path.join(path, cls.make_filename(entry)) + try: + with open(full_path, "w", encoding="utf-8") as f: + f.write(cls.export_entry(entry)) + entry_is_written = True + except OSError as oserr: + title_length = len(str(entry.title)) + if ( + oserr.errno == errno.ENAMETOOLONG + or oserr.errno == errno.ENOENT + or oserr.errno == errno.EINVAL + ) and title_length > 1: + shorter_file_length = title_length // 2 + entry.title = str(entry.title)[:shorter_file_length] + else: + raise print_msg( Message( MsgText.JournalExportedTo, diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index 9781ff51..d5714630 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -579,3 +579,21 @@ Feature: Custom formats | basic_encrypted.yaml | | basic_folder.yaml | | basic_dayone.yaml | + + Scenario: Export entries in markdown format with a title longer than max file name length. + Given we use the config "basic_onefile.yaml" + And we create a cache directory + When we run "jrnl 2022-07-31 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Laoreet id donec ultrices tincidunt arcu Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin Ut pharetra sit amet aliquam id diam maecenas Habitasse platea dictumst quisque sagittis Aliquam purus sit amet luctus venenatis lectus magna Aenean sed adipiscing diam donec adipiscing tristique risus nec feugiat Diam vel quam elementum pulvinar etiam non Odio ut enim blandit volutpat maecenas volutpat Lacus vestibulum sed arcu non odio euismod lacinia at quis. Pretium nibh ipsum consequat nisl." + When we run "jrnl 2022-07-31 Magna fermentum iaculis eu non diam phasellus Non pulvinar neque laoreet suspendisse interdum consectetur libero id Scelerisque felis imperdiet proin fermentum leo Eu ultrices vitae auctor eu augue ut lectus Bibendum arcu vitae elementum curabitur vitae nunc sed Tincidunt tortor aliquam nulla facilisi cras fermentum Malesuada nunc vel risus commodo viverra maecenas accumsan lacus vel Non sodales neque sodales ut Enim nulla aliquet porttitor lacus luctus accumsan Volutpat blandit aliquam etiam erat velit scelerisque in dictum non Egestas fringilla phasellus faucibus scelerisque At risus viverra adipiscing at in tellus integer feugiat scelerisque Eget velit aliquet sagittis id consectetur purus ut Imperdiet nulla malesuada pellentesque elit eget gravida cum sociis Lacus vestibulum sed arcu non odio euismod lacinia at Elit pellentesque habitant morbi tristique Vestibulum lorem sed risus ultricies Integer eget aliquet nibh praesent tristique magna sit amet purus Quisque id diam vel quam elementum pulvinar etiam non quam Nisi scelerisque eu ultrices vitae auctor eu augue. Malesuada fames ac turpis egestas integer eget aliquet." + When we run "jrnl --format markdown --file {cache_dir}" + Then the cache directory should contain 5 files + And we should get no error + + Scenario: Export entries in text format with a title longer than max file name length. + Given we use the config "basic_onefile.yaml" + And we create a cache directory + When we run "jrnl 2022-07-31 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Laoreet id donec ultrices tincidunt arcu Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin Ut pharetra sit amet aliquam id diam maecenas Habitasse platea dictumst quisque sagittis Aliquam purus sit amet luctus venenatis lectus magna Aenean sed adipiscing diam donec adipiscing tristique risus nec feugiat Diam vel quam elementum pulvinar etiam non Odio ut enim blandit volutpat maecenas volutpat Lacus vestibulum sed arcu non odio euismod lacinia at quis. Pretium nibh ipsum consequat nisl." + When we run "jrnl 2022-07-31 Magna fermentum iaculis eu non diam phasellus Non pulvinar neque laoreet suspendisse interdum consectetur libero id Scelerisque felis imperdiet proin fermentum leo Eu ultrices vitae auctor eu augue ut lectus Bibendum arcu vitae elementum curabitur vitae nunc sed Tincidunt tortor aliquam nulla facilisi cras fermentum Malesuada nunc vel risus commodo viverra maecenas accumsan lacus vel Non sodales neque sodales ut Enim nulla aliquet porttitor lacus luctus accumsan Volutpat blandit aliquam etiam erat velit scelerisque in dictum non Egestas fringilla phasellus faucibus scelerisque At risus viverra adipiscing at in tellus integer feugiat scelerisque Eget velit aliquet sagittis id consectetur purus ut Imperdiet nulla malesuada pellentesque elit eget gravida cum sociis Lacus vestibulum sed arcu non odio euismod lacinia at Elit pellentesque habitant morbi tristique Vestibulum lorem sed risus ultricies Integer eget aliquet nibh praesent tristique magna sit amet purus Quisque id diam vel quam elementum pulvinar etiam non quam Nisi scelerisque eu ultrices vitae auctor eu augue. Malesuada fames ac turpis egestas integer eget aliquet." + When we run "jrnl --format text --file {cache_dir}" + Then the cache directory should contain 5 files + And we should get no error diff --git a/tests/lib/helpers.py b/tests/lib/helpers.py index 39a24f71..e3a4d70d 100644 --- a/tests/lib/helpers.py +++ b/tests/lib/helpers.py @@ -17,6 +17,21 @@ def does_directory_contain_files(file_list, directory_path): return True +def does_directory_contain_n_files(directory_path, number): + count = 0 + if not os.path.isdir(directory_path): + return False + + files = [ + f + for f in os.listdir(directory_path) + if os.path.isfile(os.path.join(directory_path, f)) + ] + count = len(files) + + return int(number) == count + + def parse_should_or_should_not(should_or_should_not): if should_or_should_not == "should": return True diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index 4efde7a5..51b145d1 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -13,6 +13,7 @@ from ruamel.yaml import YAML from jrnl.config import scope_config from tests.lib.helpers import assert_equal_tags_ignoring_order from tests.lib.helpers import does_directory_contain_files +from tests.lib.helpers import does_directory_contain_n_files from tests.lib.helpers import get_nested_val from tests.lib.helpers import parse_should_or_should_not @@ -201,6 +202,11 @@ def assert_dir_contains_files(file_list, cache_dir): assert does_directory_contain_files(file_list, cache_dir["path"]) +@then(parse("the cache directory should contain {number} files")) +def assert_dir_contains_n_files(cache_dir, number): + assert does_directory_contain_n_files(cache_dir["path"], number) + + @then(parse("the journal directory should contain\n{file_list}")) def journal_directory_should_contain(config_on_disk, file_list): scoped_config = scope_config(config_on_disk, "default")