Skip to content

Commit

Permalink
Merge pull request #20 from KeplerOps/19-maintainability
Browse files Browse the repository at this point in the history
Reduce complexity and remove unnecessary variable
  • Loading branch information
Brad-Edwards authored Dec 27, 2024
2 parents 487ab5b + dcb2083 commit 664e846
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 30 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.2] - 2024-01-24

### Changed
- Refactored `build_directory_tree` into smaller, more focused functions
- Improved code organization following Clean Code principles
- Enhanced type hints and documentation

## [0.2.1] - 2024-12-27

### Changed
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[![Build](https://github.com/KeplerOps/codeorite/actions/workflows/build.yml/badge.svg)](https://github.com/KeplerOps/codeorite/actions/workflows/build.yml)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=KeplerOps_codeorite&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=KeplerOps_codeorite)

# Codeorite

A CLI tool to package repository code into a single text file, respecting .gitignore rules.
Expand Down
2 changes: 1 addition & 1 deletion codeorite/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ def main() -> NoReturn:
except KeyboardInterrupt:
logger.info("Operation cancelled by user")
sys.exit(130) # Standard exit code for SIGINT
except Exception as e:
except Exception:
logger.exception("Fatal error occurred")
sys.exit(1)

Expand Down
101 changes: 73 additions & 28 deletions codeorite/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,75 @@ def is_ignored_by_gitignore(file_path, spec, root_path):
return is_ignored


def build_directory_tree(root_dir, included_files):
def _is_path_included(path: Path, included_paths: set[Path]) -> bool:
"""Check if a path or any of its subdirectories are included.
Args:
path: Path to check
included_paths: Set of paths that are included
Returns:
bool: True if path or any subdirectory is included
"""
return path in included_paths or any(
str(p).startswith(str(path)) for p in included_paths
)


def _format_tree_line(current_path: Path, root_path: Path) -> str:
"""Format a single line in the directory tree.
Args:
current_path: Current directory path
root_path: Root directory path
Returns:
str: Formatted tree line with proper indentation
"""
try:
rel_path = current_path.relative_to(root_path)
level = len(rel_path.parts) if str(rel_path) != "." else 0
indent = " " * level
dir_name = current_path.name or root_path.name
return f"{indent}{dir_name}/"
except ValueError as e:
logger.warning("Could not determine relative path for %s: %s", current_path, e)
return ""


def _check_directory_inclusion(
current_path: Path, files: list[str], dirs: list[str], included_paths: set[Path]
) -> bool:
"""Check if a directory should be included in the tree.
Args:
current_path: Current directory path
files: List of files in the directory
dirs: List of subdirectories
included_paths: Set of included file paths
Returns:
bool: True if directory should be included
"""
# Check if any files in this directory are included
if any(
_is_path_included(Path(current_path, f).resolve(), included_paths)
for f in files
):
return True

# Check if any subdirectories contain included files
return any(
_is_path_included(Path(current_path, d).resolve(), included_paths) for d in dirs
)


def build_directory_tree(root_dir: str, included_files: list[str]) -> str:
"""Build a directory tree string that only includes folders containing included files.
This function creates a visual representation of the directory structure,
showing only directories that contain files that were selected for inclusion.
Args:
root_dir: Repository root directory
included_files: List of files to include
Expand All @@ -76,33 +142,12 @@ def build_directory_tree(root_dir, included_files):

for current_root, dirs, files in os.walk(root_dir):
current_path = Path(current_root).resolve()
sub_included = False

for f in files:
if Path(current_root, f).resolve() in included_paths:
sub_included = True
break

for d in dirs:
subdir_path = Path(current_root, d).resolve()
if any(str(p).startswith(str(subdir_path)) for p in included_paths):
sub_included = True
break

if sub_included:
try:
# Calculate relative path from root to current path
rel_path = current_path.relative_to(root_path)
level = len(rel_path.parts) if str(rel_path) != "." else 0
indent = " " * level
dir_name = current_path.name or root_path.name
tree_lines.append(f"{indent}{dir_name}/")
logger.debug("Added directory to tree: %s", dir_name)
except ValueError as e:
logger.warning(
"Could not determine relative path for %s: %s", current_path, e
)
continue

if _check_directory_inclusion(current_path, files, dirs, included_paths):
tree_line = _format_tree_line(current_path, root_path)
if tree_line:
tree_lines.append(tree_line)
logger.debug("Added directory to tree: %s", current_path.name)

return "\n".join(tree_lines)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "codeorite"
version = "0.2.1"
version = "0.2.2"
description = "A tool to package a repository into a single text file while respecting .gitignore."
authors = [
{name = "Brad Edwards", email = "[email protected]"}
Expand Down

0 comments on commit 664e846

Please sign in to comment.