reposnap 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {reposnap-0.2.0 → reposnap-0.2.1}/.gitignore +1 -0
  2. {reposnap-0.2.0 → reposnap-0.2.1}/PKG-INFO +6 -6
  3. {reposnap-0.2.0 → reposnap-0.2.1}/README.md +5 -5
  4. {reposnap-0.2.0 → reposnap-0.2.1}/pyproject.toml +4 -1
  5. reposnap-0.2.1/src/reposnap/core/collector.py +30 -0
  6. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/core/file_system.py +5 -1
  7. reposnap-0.2.1/src/reposnap/core/git_repo.py +21 -0
  8. reposnap-0.2.1/src/reposnap/core/markdown_generator.py +122 -0
  9. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/interfaces/cli.py +9 -0
  10. reposnap-0.2.1/tests/reposnap/test_file_system.py +69 -0
  11. reposnap-0.2.1/tests/reposnap/test_markdown_generator.py +70 -0
  12. reposnap-0.2.1/tests/resources/another_existing_file.py +1 -0
  13. reposnap-0.2.1/tests/resources/existing_file.py +1 -0
  14. reposnap-0.2.0/src/reposnap/core/collector.py +0 -21
  15. reposnap-0.2.0/src/reposnap/core/git_repo.py +0 -14
  16. reposnap-0.2.0/src/reposnap/core/markdown_generator.py +0 -24
  17. reposnap-0.2.0/tests/reposnap/test_file_system.py +0 -28
  18. reposnap-0.2.0/tests/reposnap/test_markdown_generator.py +0 -15
  19. {reposnap-0.2.0 → reposnap-0.2.1}/.python-version +0 -0
  20. {reposnap-0.2.0 → reposnap-0.2.1}/LICENSE +0 -0
  21. {reposnap-0.2.0 → reposnap-0.2.1}/requirements-dev.lock +0 -0
  22. {reposnap-0.2.0 → reposnap-0.2.1}/requirements.lock +0 -0
  23. {reposnap-0.2.0 → reposnap-0.2.1}/src/collect.py +0 -0
  24. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/__init__.py +0 -0
  25. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/core/__init__.py +0 -0
  26. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/interfaces/__init__.py +0 -0
  27. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/utils/__init__.py +0 -0
  28. {reposnap-0.2.0 → reposnap-0.2.1}/src/reposnap/utils/path_utils.py +0 -0
  29. {reposnap-0.2.0 → reposnap-0.2.1}/tests/__init__.py +0 -0
  30. {reposnap-0.2.0 → reposnap-0.2.1}/tests/reposnap/__init__.py +0 -0
  31. {reposnap-0.2.0 → reposnap-0.2.1}/tests/reposnap/test_cli.py +0 -0
  32. {reposnap-0.2.0 → reposnap-0.2.1}/tests/reposnap/test_collector.py +0 -0
  33. {reposnap-0.2.0 → reposnap-0.2.1}/tests/reposnap/test_git_repo.py +0 -0
  34. {reposnap-0.2.0 → reposnap-0.2.1}/tests/reposnap/test_path_utils.py +0 -0
@@ -10,3 +10,4 @@ wheels/
10
10
  .venv
11
11
  .idea
12
12
  output.md
13
+ pytest.ini
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: reposnap
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Generate a Markdown file with all contents of your project
5
5
  Author: agoloborodko
6
6
  License-File: LICENSE
@@ -30,14 +30,14 @@ Description-Content-Type: text/markdown
30
30
  To use the `collect.py` script, run it with the following options:
31
31
 
32
32
  ```bash
33
- python -m collect <project_root> [-o OUTPUT] [-e EXCLUDE ...] [-x EXCLUDE_FILE] [--structure-only]
33
+ reposnap [-h] [-o OUTPUT] [--structure-only] [--debug] path
34
34
  ```
35
35
 
36
- - `<project_root>`: The root directory of the project to document.
37
- - `-o, --output`: The name of the output Markdown file. Defaults to `repo-content-<timestamp>.md`.
38
- - `-e, --exclude`: Patterns of files or directories to exclude (supports multiple patterns).
39
- - `-x, --exclude-file`: A file (e.g., `.gitignore`) containing patterns of files or directories to exclude.
36
+ - `path`: Path to the Git repository root folder
37
+ - `-h, --help`: show help message and exit
38
+ - `-o, --output`: The name of the output Markdown file. Defaults to `output.md`.
40
39
  - `--structure-only`: Generate a Markdown file that includes only the project structure, without file contents.
40
+ - `--debug`: Enable debug-level logging.
41
41
 
42
42
  ### Examples
43
43
 
@@ -18,14 +18,14 @@
18
18
  To use the `collect.py` script, run it with the following options:
19
19
 
20
20
  ```bash
21
- python -m collect <project_root> [-o OUTPUT] [-e EXCLUDE ...] [-x EXCLUDE_FILE] [--structure-only]
21
+ reposnap [-h] [-o OUTPUT] [--structure-only] [--debug] path
22
22
  ```
23
23
 
24
- - `<project_root>`: The root directory of the project to document.
25
- - `-o, --output`: The name of the output Markdown file. Defaults to `repo-content-<timestamp>.md`.
26
- - `-e, --exclude`: Patterns of files or directories to exclude (supports multiple patterns).
27
- - `-x, --exclude-file`: A file (e.g., `.gitignore`) containing patterns of files or directories to exclude.
24
+ - `path`: Path to the Git repository root folder
25
+ - `-h, --help`: show help message and exit
26
+ - `-o, --output`: The name of the output Markdown file. Defaults to `output.md`.
28
27
  - `--structure-only`: Generate a Markdown file that includes only the project structure, without file contents.
28
+ - `--debug`: Enable debug-level logging.
29
29
 
30
30
  ### Examples
31
31
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "reposnap"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Generate a Markdown file with all contents of your project"
5
5
  authors = [
6
6
  { name = "agoloborodko" }
@@ -28,3 +28,6 @@ allow-direct-references = true
28
28
 
29
29
  [tool.hatch.build.targets.wheel]
30
30
  packages = ["src/reposnap"]
31
+
32
+ [project.scripts]
33
+ reposnap = "collect:main"
@@ -0,0 +1,30 @@
1
+ # src/reposnap/core/collector.py
2
+
3
+ from .file_system import FileSystem
4
+ from .git_repo import GitRepo
5
+ from .markdown_generator import MarkdownGenerator
6
+ import pathspec
7
+ import logging
8
+ from pathlib import Path
9
+
10
+
11
+ class ProjectContentCollector:
12
+ def __init__(self, root_dir: str, output_file: str, structure_only: bool, gitignore_patterns: list):
13
+ self.root_dir = Path(root_dir).resolve()
14
+ self.output_file = Path(output_file).resolve()
15
+ self.structure_only = structure_only
16
+ self.spec = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, gitignore_patterns)
17
+ self.file_system = FileSystem(self.root_dir)
18
+ self.git_repo = GitRepo(self.root_dir)
19
+ self.markdown_generator = MarkdownGenerator(
20
+ root_dir=self.root_dir,
21
+ output_file=self.output_file,
22
+ structure_only=self.structure_only
23
+ )
24
+ self.logger = logging.getLogger(__name__)
25
+
26
+ def collect_and_generate(self):
27
+ self.logger.info("Starting project content collection.")
28
+ git_files = self.git_repo.get_git_files()
29
+ tree_structure = self.file_system.build_tree_structure(git_files)
30
+ self.markdown_generator.generate_markdown(tree_structure, git_files, self.spec)
@@ -1,5 +1,6 @@
1
1
  # src/reposnap/core/file_system.py
2
2
 
3
+ import logging
3
4
  from pathlib import Path
4
5
 
5
6
  class FileSystem:
@@ -8,12 +9,15 @@ class FileSystem:
8
9
 
9
10
  def build_tree_structure(self, files):
10
11
  tree = {}
12
+ logging.debug("\n>>> Processing Files for Tree Structure <<<")
11
13
  for file in files:
12
- file_path = Path(file).resolve()
14
+ file_path = (self.root_dir / file).resolve()
15
+ logging.debug(f"Processing file:\n File Path: {file_path}\n Root Dir: {self.root_dir}")
13
16
  relative_path = file_path.relative_to(self.root_dir).as_posix()
14
17
  parts = relative_path.split('/')
15
18
  current_level = tree
16
19
  for part in parts[:-1]:
17
20
  current_level = current_level.setdefault(part, {})
18
21
  current_level[parts[-1]] = relative_path
22
+ logging.debug(">>> End of Processing <<<\n")
19
23
  return tree
@@ -0,0 +1,21 @@
1
+ # src/reposnap/core/git_repo.py
2
+
3
+ import logging
4
+ from git import Repo, InvalidGitRepositoryError
5
+
6
+ class GitRepo:
7
+ def __init__(self, repo_path: str):
8
+ self.repo_path = repo_path
9
+
10
+ def get_git_files(self):
11
+ try:
12
+ repo = Repo(self.repo_path)
13
+ files = repo.git.ls_files().splitlines()
14
+ logging.debug(f"\n--- Retrieved Git Files from {repo.working_tree_dir} ---")
15
+ for file in files:
16
+ logging.debug(f" - {file}")
17
+ logging.debug("--- End of Git Files ---\n")
18
+ return files
19
+ except InvalidGitRepositoryError:
20
+ logging.debug(f"Invalid Git repository at: {self.repo_path}")
21
+ return []
@@ -0,0 +1,122 @@
1
+ # src/reposnap/core/markdown_generator.py
2
+
3
+ from pathlib import Path
4
+ from ..utils.path_utils import format_tree
5
+ import logging
6
+
7
+
8
+ class MarkdownGenerator:
9
+ def __init__(self, root_dir: Path, output_file: Path, structure_only: bool = False):
10
+ """
11
+ Initializes the MarkdownGenerator.
12
+
13
+ Args:
14
+ root_dir (Path): The root directory of the project.
15
+ output_file (Path): The path to the output Markdown file.
16
+ structure_only (bool): If True, only the directory structure is included without file contents.
17
+ """
18
+ self.root_dir = root_dir.resolve()
19
+ self.output_file = output_file.resolve()
20
+ self.structure_only = structure_only
21
+ self.logger = logging.getLogger(__name__)
22
+ self.logger.debug(f"Initialized MarkdownGenerator with root_dir={self.root_dir}, "
23
+ f"output_file={self.output_file}, structure_only={self.structure_only}")
24
+
25
+ def generate_markdown(self, tree_structure: dict, git_files: list, spec=None):
26
+ """
27
+ Generates the Markdown file based on the provided tree structure and git files.
28
+
29
+ Args:
30
+ tree_structure (dict): The hierarchical structure of the project files.
31
+ git_files (list): List of files tracked by Git.
32
+ spec (pathspec.PathSpec, optional): PathSpec object for file exclusion based on patterns.
33
+ """
34
+ self.logger.info("Starting Markdown generation.")
35
+ self._write_header(tree_structure)
36
+
37
+ if not self.structure_only:
38
+ self._write_file_contents(git_files, spec)
39
+
40
+ self.logger.info(f"Markdown file generated successfully at: {self.output_file}")
41
+
42
+ def _write_header(self, tree_structure: dict):
43
+ """
44
+ Writes the header and project structure to the Markdown file.
45
+
46
+ Args:
47
+ tree_structure (dict): The hierarchical structure of the project files.
48
+ """
49
+ self.logger.debug("Writing Markdown header and project structure.")
50
+ try:
51
+ with self.output_file.open('w', encoding='utf-8') as f:
52
+ f.write("# Project Structure\n\n")
53
+ f.write("```\n")
54
+ for line in format_tree(tree_structure):
55
+ f.write(line)
56
+ f.write("```\n\n")
57
+ self.logger.debug("Header and project structure written successfully.")
58
+ except IOError as e:
59
+ self.logger.error(f"Failed to write header to {self.output_file}: {e}")
60
+ raise
61
+
62
+ def _write_file_contents(self, git_files: list, spec):
63
+ """
64
+ Writes the contents of each file to the Markdown file, excluding those matching the spec.
65
+
66
+ Args:
67
+ git_files (list): List of files tracked by Git.
68
+ spec (pathspec.PathSpec, optional): PathSpec object for file exclusion based on patterns.
69
+ """
70
+ self.logger.debug("Writing file contents to Markdown.")
71
+ for file in git_files:
72
+ file_path = self._resolve_file_path(file)
73
+
74
+ if not file_path.exists():
75
+ self.logger.debug(f"File not found: {file_path}. Skipping.")
76
+ continue
77
+
78
+ relative_path = file_path.relative_to(self.root_dir).as_posix()
79
+ if spec and spec.match_file(relative_path):
80
+ self.logger.debug(f"File excluded by spec: {relative_path}. Skipping.")
81
+ continue
82
+
83
+ self.logger.debug(f"Processing file: {file_path}")
84
+ self._write_file_content(file_path, relative_path)
85
+
86
+ def _resolve_file_path(self, file: str) -> Path:
87
+ """
88
+ Resolves the absolute path of a file relative to the root directory.
89
+
90
+ Args:
91
+ file (str): The file path relative to the root directory.
92
+
93
+ Returns:
94
+ Path: The absolute path to the file.
95
+ """
96
+ resolved_path = self.root_dir / file
97
+ self.logger.debug(f"Resolved file path: {file} to {resolved_path}")
98
+ return resolved_path
99
+
100
+ def _write_file_content(self, file_path: Path, relative_path: str):
101
+ """
102
+ Writes the content of a single file to the Markdown file with syntax highlighting.
103
+
104
+ Args:
105
+ file_path (Path): The absolute path to the file.
106
+ relative_path (str): The file path relative to the root directory.
107
+ """
108
+ try:
109
+ print(f"Attempting to read file: {file_path}")
110
+ with file_path.open('r', encoding='utf-8') as f:
111
+ content = f.read()
112
+ self.logger.debug(f"Read content from {file_path}")
113
+
114
+ with self.output_file.open('a', encoding='utf-8') as f:
115
+ f.write(f"## {relative_path}\n\n")
116
+ f.write("```python\n" if file_path.suffix == '.py' else "```\n")
117
+ f.write(f"{content}\n```\n\n")
118
+ self.logger.debug(f"Wrote content of {relative_path} to Markdown.")
119
+ except IOError as e:
120
+ self.logger.error(f"Error reading or writing file {file_path}: {e}")
121
+ except Exception as e:
122
+ self.logger.error(f"Unexpected error processing file {file_path}: {e}")
@@ -1,21 +1,30 @@
1
1
  # src/reposnap/interfaces/cli.py
2
2
 
3
3
  import argparse
4
+ import logging
4
5
  from reposnap.core.collector import ProjectContentCollector
5
6
 
7
+
6
8
  def main():
7
9
  parser = argparse.ArgumentParser(description='Generate a Markdown representation of a Git repository.')
8
10
  parser.add_argument('path', help='Path to the Git repository.')
9
11
  parser.add_argument('-o', '--output', help='Output Markdown file', default='output.md')
10
12
  parser.add_argument('--structure-only', action='store_true',
11
13
  help='Only include the file structure without content.')
14
+ parser.add_argument('--debug', action='store_true', help='Enable debug-level logging.')
15
+
12
16
  args = parser.parse_args()
13
17
 
18
+ log_level = logging.DEBUG if args.debug else logging.INFO
19
+ logging.basicConfig(level=log_level, format='%(asctime)s - %(levelname)s - %(message)s')
20
+
14
21
  with open(f"{args.path}/.gitignore", 'r') as gitignore:
15
22
  patterns = gitignore.readlines()
23
+ logging.debug(f"Patterns from .gitignore in {args.path}: {patterns}")
16
24
 
17
25
  collector = ProjectContentCollector(args.path, args.output, args.structure_only, patterns)
18
26
  collector.collect_and_generate()
19
27
 
28
+
20
29
  if __name__ == "__main__":
21
30
  main()
@@ -0,0 +1,69 @@
1
+ # tests/reposnap/test_file_system.py
2
+
3
+ import pytest
4
+ from pathlib import Path
5
+ from reposnap.core.file_system import FileSystem
6
+
7
+
8
+ @pytest.fixture
9
+ def file_system(tmp_path):
10
+ # Initialize FileSystem with tmp_path as the root directory
11
+ return FileSystem(str(tmp_path))
12
+
13
+
14
+ def test_build_tree_structure(file_system, tmp_path):
15
+ # Ensure intermediate directories are created
16
+ (tmp_path / 'dir1').mkdir(parents=True, exist_ok=True)
17
+ (tmp_path / 'dir2').mkdir(parents=True, exist_ok=True)
18
+
19
+ # Write files into the created directories
20
+ (tmp_path / 'dir1' / 'file1.py').write_text('content')
21
+ (tmp_path / 'dir2' / 'file2.py').write_text('content')
22
+
23
+ # Build tree structure based on the files in tmp_path
24
+ tree_structure = file_system.build_tree_structure([
25
+ str(tmp_path / 'dir1' / 'file1.py'),
26
+ str(tmp_path / 'dir2' / 'file2.py')
27
+ ])
28
+ assert 'dir1' in tree_structure
29
+ assert 'file1.py' in tree_structure['dir1']
30
+ assert 'dir2' in tree_structure
31
+ assert 'file2.py' in tree_structure['dir2']
32
+
33
+
34
+ def test_relative_path_resolution(file_system, tmp_path):
35
+ # Create a mock .gitignore file in the root directory
36
+ gitignore_file = tmp_path / '.gitignore'
37
+ gitignore_file.write_text('*.pyc\n')
38
+
39
+ # Add a relative path to the git_files list
40
+ git_files = ['.gitignore']
41
+
42
+ # Mock the root_dir to simulate the environment
43
+ root_dir = tmp_path
44
+
45
+ # Simulate the file system processing
46
+ tree_structure = file_system.build_tree_structure(git_files)
47
+
48
+ # Check if .gitignore was correctly resolved relative to the root directory
49
+ expected_path = '.gitignore'
50
+ assert tree_structure['.gitignore'] == expected_path, \
51
+ f"Expected {expected_path}, but got {tree_structure['.gitignore']}"
52
+
53
+
54
+ def test_incorrect_path_resolution(file_system, tmp_path):
55
+ # Create a mock .gitignore file in a different directory (simulating reposnap)
56
+ wrong_dir = Path('/Users/andrey.goloborodko/PycharmProjects/reposnap')
57
+ wrong_gitignore_file = wrong_dir / '.gitignore'
58
+ wrong_gitignore_file.touch() # Create an empty .gitignore file
59
+
60
+ # Add a relative path to the git_files list
61
+ git_files = ['.gitignore']
62
+
63
+ # Simulate the file system processing and manually resolve .gitignore incorrectly
64
+ tree_structure = file_system.build_tree_structure(git_files)
65
+
66
+ # Check if .gitignore was incorrectly resolved to the wrong directory
67
+ incorrect_path = wrong_gitignore_file.resolve().as_posix()
68
+ assert tree_structure['.gitignore'] != incorrect_path, \
69
+ f"Expected path NOT to be {incorrect_path}, but it was resolved as such"
@@ -0,0 +1,70 @@
1
+ import pytest
2
+ from reposnap.core.markdown_generator import MarkdownGenerator
3
+ from unittest.mock import call
4
+ from pathlib import Path
5
+
6
+
7
+ @pytest.fixture
8
+ def resources_dir():
9
+ return Path(__file__).parent.parent / "resources"
10
+
11
+
12
+ @pytest.fixture
13
+ def markdown_generator_factory(resources_dir, tmp_path):
14
+ def _factory(structure_only=False):
15
+ # Use a temporary directory for the output file
16
+ output_file = tmp_path / "output.md"
17
+ return MarkdownGenerator(root_dir=resources_dir, output_file=output_file, structure_only=structure_only)
18
+
19
+ return _factory
20
+
21
+
22
+ @pytest.mark.parametrize("git_files,expected_calls", [
23
+ (
24
+ ['existing_file.py', 'missing_file.py', 'another_existing_file.py'],
25
+ [
26
+ "## existing_file.py\n\n",
27
+ "```python\n",
28
+ 'print("Hello, world!")\n',
29
+ '```\n\n',
30
+ "## another_existing_file.py\n\n",
31
+ "```python\n",
32
+ 'print("Another file")\n',
33
+ '```\n\n'
34
+ ]
35
+ ),
36
+ ])
37
+ def test_generate_markdown_with_missing_files(resources_dir, markdown_generator_factory, git_files, expected_calls):
38
+ markdown_generator = markdown_generator_factory(structure_only=False)
39
+
40
+ # Generate the markdown file and verify the output
41
+ markdown_generator.generate_markdown({}, git_files)
42
+ output_content = markdown_generator.output_file.read_text()
43
+
44
+ # Join expected calls into a single string
45
+ expected_content = ''.join(expected_calls)
46
+
47
+ assert expected_content in output_content
48
+
49
+
50
+ def test_generate_markdown_structure_only(markdown_generator_factory):
51
+ tree_structure = {'dir': {'file.py': 'file.py'}}
52
+
53
+ expected_calls = [
54
+ "# Project Structure\n\n",
55
+ "```\n",
56
+ "dir/\n",
57
+ " file.py\n",
58
+ "```\n\n"
59
+ ]
60
+
61
+ markdown_generator = markdown_generator_factory(structure_only=True)
62
+
63
+ # Generate the markdown file and verify the output
64
+ markdown_generator.generate_markdown(tree_structure, [])
65
+ output_content = markdown_generator.output_file.read_text()
66
+
67
+ # Join expected calls into a single string
68
+ expected_content = ''.join(expected_calls)
69
+
70
+ assert output_content == expected_content
@@ -0,0 +1 @@
1
+ print("Another file")
@@ -0,0 +1 @@
1
+ print("Hello, world!")
@@ -1,21 +0,0 @@
1
- # src/reposnap/core/collector.py
2
-
3
- from .file_system import FileSystem
4
- from .git_repo import GitRepo
5
- from .markdown_generator import MarkdownGenerator
6
- import pathspec
7
-
8
- class ProjectContentCollector:
9
- def __init__(self, root_dir: str, output_file: str, structure_only: bool, gitignore_patterns: list):
10
- self.root_dir = root_dir
11
- self.output_file = output_file
12
- self.structure_only = structure_only
13
- self.spec = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, gitignore_patterns)
14
- self.file_system = FileSystem(root_dir)
15
- self.git_repo = GitRepo(root_dir)
16
- self.markdown_generator = MarkdownGenerator()
17
-
18
- def collect_and_generate(self):
19
- git_files = self.git_repo.get_git_files()
20
- tree_structure = self.file_system.build_tree_structure(git_files)
21
- self.markdown_generator.generate_markdown(self.output_file, tree_structure, git_files, self.spec, self.structure_only)
@@ -1,14 +0,0 @@
1
- # src/reposnap/core/git_repo.py
2
-
3
- from git import Repo, InvalidGitRepositoryError
4
-
5
- class GitRepo:
6
- def __init__(self, repo_path: str):
7
- self.repo_path = repo_path
8
-
9
- def get_git_files(self):
10
- try:
11
- repo = Repo(self.repo_path)
12
- return repo.git.ls_files().splitlines()
13
- except InvalidGitRepositoryError:
14
- return []
@@ -1,24 +0,0 @@
1
- # src/reposnap/core/markdown_generator.py
2
-
3
- from pathlib import Path
4
- from ..utils.path_utils import format_tree
5
-
6
- class MarkdownGenerator:
7
- def generate_markdown(self, output_file, tree_structure, git_files, spec, structure_only=False):
8
- with open(output_file, 'w') as f:
9
- f.write("# Project Structure\n\n")
10
- f.write("```\n")
11
- for line in format_tree(tree_structure):
12
- f.write(line)
13
- f.write("```\n\n")
14
-
15
- if not structure_only:
16
- for file in git_files:
17
- relative_path = Path(file).relative_to(Path(output_file).parent).as_posix()
18
- if spec and not spec.match_file(relative_path):
19
- # Only read the file if spec is not None and does not match
20
- with open(Path(output_file).parent / file, 'r') as file_content:
21
- f.write(f"## {relative_path}\n\n")
22
- f.write(f"```\n{file_content.read()}\n```\n\n")
23
-
24
- print(f"Markdown file generated: {output_file}")
@@ -1,28 +0,0 @@
1
- # src/reposnap/tests/test_file_system.py
2
-
3
- import pytest
4
- from reposnap.core.file_system import FileSystem
5
-
6
- @pytest.fixture
7
- def file_system(tmp_path):
8
- # Initialize FileSystem with tmp_path as the root directory
9
- return FileSystem(str(tmp_path))
10
-
11
- def test_build_tree_structure(file_system, tmp_path):
12
- # Ensure intermediate directories are created
13
- (tmp_path / 'dir1').mkdir(parents=True, exist_ok=True)
14
- (tmp_path / 'dir2').mkdir(parents=True, exist_ok=True)
15
-
16
- # Write files into the created directories
17
- (tmp_path / 'dir1' / 'file1.py').write_text('content')
18
- (tmp_path / 'dir2' / 'file2.py').write_text('content')
19
-
20
- # Build tree structure based on the files in tmp_path
21
- tree_structure = file_system.build_tree_structure([
22
- str(tmp_path / 'dir1' / 'file1.py'),
23
- str(tmp_path / 'dir2' / 'file2.py')
24
- ])
25
- assert 'dir1' in tree_structure
26
- assert 'file1.py' in tree_structure['dir1']
27
- assert 'dir2' in tree_structure
28
- assert 'file2.py' in tree_structure['dir2']
@@ -1,15 +0,0 @@
1
- # src/reposnap/tests/test_markdown_generator.py
2
-
3
- import pytest # noqa
4
- from reposnap.core.markdown_generator import MarkdownGenerator
5
- from unittest.mock import mock_open, patch
6
-
7
- def test_generate_markdown():
8
- mock_open_func = mock_open()
9
- with patch('builtins.open', mock_open_func):
10
- markdown_generator = MarkdownGenerator()
11
- markdown_generator.generate_markdown('output.md', {'dir': {'file.py': 'file.py'}}, ['file.py'], None)
12
-
13
- mock_open_func.assert_called_once_with('output.md', 'w')
14
- handle = mock_open_func()
15
- handle.write.assert_called()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes