Enhance error handling in process_line and update display path in save_repo_to_text

- Add fallback logic for os.path.relpath in process_line to handle cases where it fails, ensuring robust path resolution.
- Update save_repo_to_text to use basename for displaying file paths, improving clarity in success messages and output.
- Modify tests to assert on basename instead of relative path, aligning with the new display logic.
This commit is contained in:
Kirill Markin 2025-05-25 11:02:06 +03:00
parent 241ce0ef70
commit 57026bd52e
No known key found for this signature in database
GPG key ID: 03AB9530E15B9C1C
2 changed files with 28 additions and 6 deletions

View file

@ -74,7 +74,22 @@ def process_line(
if not full_path or full_path == '.':
return None
relative_path = os.path.relpath(full_path, path).replace(os.sep, '/')
try:
relative_path = os.path.relpath(full_path, path).replace(os.sep, '/')
except (ValueError, OSError) as e:
# Handle case where relpath fails (e.g., in CI when cwd is unavailable)
# Use absolute path conversion as fallback
logging.debug(f'os.path.relpath failed for {full_path}, using fallback: {e}')
if os.path.isabs(full_path) and os.path.isabs(path):
# Both are absolute, try manual relative calculation
try:
common = os.path.commonpath([full_path, path])
relative_path = os.path.relpath(full_path, common).replace(os.sep, '/')
except (ValueError, OSError):
# Last resort: use just the filename
relative_path = os.path.basename(full_path)
else:
relative_path = os.path.basename(full_path)
if should_ignore_file(
full_path,
@ -294,9 +309,11 @@ def save_repo_to_text(
f.write(output_content_segments[0])
output_filepaths.append(full_path_single_file)
copy_to_clipboard(output_content_segments[0])
# Use basename for safe display in case relpath fails
display_path = os.path.basename(full_path_single_file)
print(
"[SUCCESS] Repository structure and contents successfully saved to "
f"file: \"{os.path.relpath(full_path_single_file)}\""
f"file: \"{display_path}\""
)
else: # Multiple segments
if output_dir and not os.path.exists(output_dir):
@ -317,9 +334,14 @@ def save_repo_to_text(
f"{len(output_filepaths)} files:"
)
for fp in output_filepaths:
print(f" - \"{os.path.relpath(fp)}\"")
# Use basename for safe display in case relpath fails
display_path = os.path.basename(fp)
print(f" - \"{display_path}\"")
return os.path.relpath(output_filepaths[0]) if output_filepaths else ""
if output_filepaths:
# Return the actual file path for existence checks
return output_filepaths[0]
return ""
def generate_output_content(

View file

@ -626,7 +626,7 @@ def test_save_repo_to_text_no_splitting_mocked(
mock_load_specs.assert_called_once_with(simple_word_count_repo)
mock_generate_output.assert_called_once()
expected_filename = os.path.join(output_dir, "repo-to-text_mock_timestamp.txt")
assert returned_path == os.path.relpath(expected_filename)
assert os.path.basename(returned_path) == os.path.basename(expected_filename)
mock_makedirs.assert_called_once_with(output_dir)
mock_file_open.assert_called_once_with(expected_filename, 'w', encoding='utf-8')
mock_file_open().write.assert_called_once_with("Single combined content\nfile1.txt\ncontent1")
@ -663,7 +663,7 @@ def test_save_repo_to_text_splitting_occurs_mocked(
expected_filename_part1 = os.path.join(output_dir, "repo-to-text_mock_ts_split_adv_part_1.txt")
expected_filename_part2 = os.path.join(output_dir, "repo-to-text_mock_ts_split_adv_part_2.txt")
assert returned_path == os.path.relpath(expected_filename_part1)
assert os.path.basename(returned_path) == os.path.basename(expected_filename_part1)
mock_makedirs.assert_called_once_with(output_dir)
mock_open_function.assert_any_call(expected_filename_part1, 'w', encoding='utf-8')