reposnap 0.6.2__tar.gz → 0.6.3__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.
- {reposnap-0.6.2 → reposnap-0.6.3}/.gitignore +3 -0
- reposnap-0.6.3/.vscode/launch.json +13 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/PKG-INFO +1 -1
- {reposnap-0.6.2 → reposnap-0.6.3}/pyproject.toml +1 -1
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/controllers/project_controller.py +47 -57
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/models/file_tree.py +2 -1
- reposnap-0.6.3/tests/reposnap/test_collected_tree.py +133 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_project_controller.py +22 -24
- {reposnap-0.6.2 → reposnap-0.6.3}/.python-version +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/LICENSE +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/README.md +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/requirements-dev.lock +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/requirements.lock +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/controllers/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/core/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/core/file_system.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/core/git_repo.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/core/markdown_generator.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/interfaces/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/interfaces/cli.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/interfaces/gui.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/models/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/utils/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/src/reposnap/utils/path_utils.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/__init__.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_cli.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_file_system.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_file_tree.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_git_repo.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_gui.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_markdown_generator.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/reposnap/test_path_utils.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/resources/another_existing_file.py +0 -0
- {reposnap-0.6.2 → reposnap-0.6.3}/tests/resources/existing_file.py +0 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"version": "0.2.0",
|
3
|
+
"configurations": [
|
4
|
+
{
|
5
|
+
"name": "Python Debugger: Run reposnap",
|
6
|
+
"type": "debugpy",
|
7
|
+
"request": "launch",
|
8
|
+
"module": "reposnap.interfaces.cli",
|
9
|
+
"console": "integratedTerminal",
|
10
|
+
"args": ["src/reposnap/controllers", "src/reposnap/interfaces", "README.md", "tests/reposnap"]
|
11
|
+
}
|
12
|
+
]
|
13
|
+
}
|
@@ -1,9 +1,6 @@
|
|
1
|
-
# src/reposnap/controllers/project_controller.py
|
2
|
-
|
3
1
|
import logging
|
4
2
|
from pathlib import Path
|
5
3
|
from reposnap.core.file_system import FileSystem
|
6
|
-
from reposnap.core.markdown_generator import MarkdownGenerator
|
7
4
|
from reposnap.models.file_tree import FileTree
|
8
5
|
import pathspec
|
9
6
|
from typing import List, Optional
|
@@ -11,35 +8,33 @@ from typing import List, Optional
|
|
11
8
|
class ProjectController:
|
12
9
|
def __init__(self, args: Optional[object] = None):
|
13
10
|
self.logger = logging.getLogger(__name__)
|
11
|
+
# Always determine repository root using Git (or cwd)
|
12
|
+
self.root_dir = self._get_repo_root().resolve()
|
14
13
|
if args:
|
15
|
-
# Support both new 'paths' (multiple paths) and legacy 'path'
|
16
|
-
if hasattr(args, 'paths'):
|
17
|
-
input_paths = [Path(p) for p in args.paths]
|
18
|
-
else:
|
19
|
-
input_paths = [Path(args.path)]
|
20
14
|
self.args = args
|
21
|
-
#
|
22
|
-
|
23
|
-
# Convert provided paths to be relative to the repository root.
|
15
|
+
# Treat positional arguments as literal file/directory names.
|
16
|
+
input_paths = [Path(p) for p in (args.paths if hasattr(args, 'paths') else [args.path])]
|
24
17
|
self.input_paths = []
|
25
18
|
for p in input_paths:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
19
|
+
candidate = (self.root_dir / p).resolve()
|
20
|
+
if candidate.exists():
|
21
|
+
try:
|
22
|
+
rel = candidate.relative_to(self.root_dir)
|
23
|
+
if rel != Path('.'):
|
24
|
+
self.input_paths.append(rel)
|
25
|
+
except ValueError:
|
26
|
+
self.logger.warning(f"Path {p} is not under repository root {self.root_dir}. Ignoring.")
|
27
|
+
else:
|
28
|
+
self.logger.warning(f"Path {p} does not exist relative to repository root {self.root_dir}.")
|
33
29
|
self.output_file: Path = Path(args.output).resolve() if args.output else self.root_dir / 'output.md'
|
34
30
|
self.structure_only: bool = args.structure_only if hasattr(args, 'structure_only') else False
|
35
31
|
self.include_patterns: List[str] = args.include if hasattr(args, 'include') else []
|
36
32
|
self.exclude_patterns: List[str] = args.exclude if hasattr(args, 'exclude') else []
|
37
33
|
else:
|
38
|
-
self.
|
34
|
+
self.args = None
|
39
35
|
self.input_paths = []
|
40
|
-
self.output_file =
|
36
|
+
self.output_file = self.root_dir / 'output.md'
|
41
37
|
self.structure_only = False
|
42
|
-
self.args = None
|
43
38
|
self.include_patterns = []
|
44
39
|
self.exclude_patterns = []
|
45
40
|
self.file_tree: Optional[FileTree] = None
|
@@ -49,25 +44,9 @@ class ProjectController:
|
|
49
44
|
|
50
45
|
def _get_repo_root(self) -> Path:
|
51
46
|
"""
|
52
|
-
Determine the repository root
|
53
|
-
use the
|
54
|
-
git repository working tree directory (or current directory if not a git repo).
|
47
|
+
Determine the repository root using Git if available,
|
48
|
+
otherwise use the current directory.
|
55
49
|
"""
|
56
|
-
if self.args is not None:
|
57
|
-
candidate_paths = []
|
58
|
-
if hasattr(self.args, 'paths'):
|
59
|
-
for p in self.args.paths:
|
60
|
-
candidate = Path(p).resolve()
|
61
|
-
if candidate.exists():
|
62
|
-
candidate_paths.append(candidate)
|
63
|
-
elif hasattr(self.args, 'path'):
|
64
|
-
candidate = Path(self.args.path).resolve()
|
65
|
-
if candidate.exists():
|
66
|
-
candidate_paths.append(candidate)
|
67
|
-
if candidate_paths:
|
68
|
-
from os.path import commonpath
|
69
|
-
common = Path(commonpath([str(p) for p in candidate_paths]))
|
70
|
-
return common
|
71
50
|
from git import Repo, InvalidGitRepositoryError
|
72
51
|
try:
|
73
52
|
repo = Repo(Path.cwd(), search_parent_directories=True)
|
@@ -104,25 +83,33 @@ class ProjectController:
|
|
104
83
|
return files
|
105
84
|
|
106
85
|
def collect_file_tree(self) -> None:
|
107
|
-
self.logger.info("Collecting files
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
#
|
86
|
+
self.logger.info("Collecting files from Git tracked files if available.")
|
87
|
+
try:
|
88
|
+
from reposnap.core.git_repo import GitRepo
|
89
|
+
git_repo = GitRepo(self.root_dir)
|
90
|
+
all_files = git_repo.get_git_files()
|
91
|
+
self.logger.debug(f"Git tracked files: {all_files}")
|
92
|
+
except Exception as e:
|
93
|
+
self.logger.warning(f"Error obtaining Git tracked files: {e}.")
|
94
|
+
all_files = []
|
95
|
+
# If Git returns an empty list but files exist on disk, fall back to filesystem scan.
|
96
|
+
if not all_files:
|
97
|
+
file_list = [p for p in self.root_dir.rglob("*") if p.is_file()]
|
98
|
+
if file_list:
|
99
|
+
self.logger.info("Git tracked files empty, using filesystem scan fallback.")
|
100
|
+
all_files = []
|
101
|
+
for path in file_list:
|
102
|
+
try:
|
103
|
+
rel = path.relative_to(self.root_dir)
|
104
|
+
all_files.append(rel)
|
105
|
+
except ValueError:
|
106
|
+
continue
|
117
107
|
all_files = self._apply_include_exclude(all_files)
|
118
|
-
self.logger.debug(f"All files after include/exclude
|
108
|
+
self.logger.debug(f"All files after applying include/exclude: {all_files}")
|
119
109
|
if self.input_paths:
|
120
110
|
trees = []
|
121
111
|
for input_path in self.input_paths:
|
122
|
-
subset = [
|
123
|
-
f for f in all_files
|
124
|
-
if f == input_path or f.parts[:len(input_path.parts)] == input_path.parts
|
125
|
-
]
|
112
|
+
subset = [f for f in all_files if f == input_path or list(f.parts[:len(input_path.parts)]) == list(input_path.parts)]
|
126
113
|
self.logger.debug(f"Files for input path '{input_path}': {subset}")
|
127
114
|
if subset:
|
128
115
|
tree = FileSystem(self.root_dir).build_tree_structure(subset)
|
@@ -164,6 +151,7 @@ class ProjectController:
|
|
164
151
|
|
165
152
|
def generate_output(self) -> None:
|
166
153
|
self.logger.info("Starting Markdown generation.")
|
154
|
+
from reposnap.core.markdown_generator import MarkdownGenerator
|
167
155
|
markdown_generator = MarkdownGenerator(
|
168
156
|
root_dir=self.root_dir,
|
169
157
|
output_file=self.output_file,
|
@@ -175,6 +163,7 @@ class ProjectController:
|
|
175
163
|
def generate_output_from_selected(self, selected_files: set) -> None:
|
176
164
|
self.logger.info("Generating Markdown from selected files.")
|
177
165
|
pruned_tree = self.file_tree.prune_tree(selected_files)
|
166
|
+
from reposnap.core.markdown_generator import MarkdownGenerator
|
178
167
|
markdown_generator = MarkdownGenerator(
|
179
168
|
root_dir=self.root_dir,
|
180
169
|
output_file=self.output_file,
|
@@ -194,14 +183,15 @@ class ProjectController:
|
|
194
183
|
gitignore_path = self.root_dir / '.gitignore'
|
195
184
|
if not gitignore_path.exists():
|
196
185
|
for parent in self.root_dir.parents:
|
197
|
-
|
198
|
-
if
|
186
|
+
candidate = parent / '.gitignore'
|
187
|
+
if candidate.exists():
|
188
|
+
gitignore_path = candidate
|
199
189
|
break
|
200
190
|
else:
|
201
191
|
gitignore_path = None
|
202
192
|
if gitignore_path and gitignore_path.exists():
|
203
193
|
with gitignore_path.open('r') as gitignore:
|
204
|
-
patterns = gitignore.
|
194
|
+
patterns = [line.strip() for line in gitignore if line.strip() and not line.strip().startswith('#')]
|
205
195
|
self.logger.debug(f"Loaded .gitignore patterns from {gitignore_path.parent}: {patterns}")
|
206
196
|
return patterns
|
207
197
|
else:
|
@@ -48,7 +48,8 @@ class FileTree:
|
|
48
48
|
if filtered_value:
|
49
49
|
filtered_subtree[key] = filtered_value
|
50
50
|
else:
|
51
|
-
if
|
51
|
+
# Exclude the file if either the full path OR its basename matches a .gitignore pattern.
|
52
|
+
if not spec.match_file(current_path) and not spec.match_file(Path(current_path).name):
|
52
53
|
filtered_subtree[key] = value
|
53
54
|
return filtered_subtree
|
54
55
|
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# tests/reposnap/test_collected_tree.py
|
2
|
+
|
3
|
+
import os
|
4
|
+
import tempfile
|
5
|
+
from pathlib import Path
|
6
|
+
import pytest
|
7
|
+
from reposnap.controllers.project_controller import ProjectController
|
8
|
+
from unittest.mock import patch
|
9
|
+
|
10
|
+
def create_directory_structure(base_dir: str, structure: dict):
|
11
|
+
"""
|
12
|
+
Recursively creates directories and files based on the provided structure.
|
13
|
+
"""
|
14
|
+
for name, content in structure.items():
|
15
|
+
path = os.path.join(base_dir, name)
|
16
|
+
if isinstance(content, dict):
|
17
|
+
os.makedirs(path, exist_ok=True)
|
18
|
+
create_directory_structure(path, content)
|
19
|
+
else:
|
20
|
+
with open(path, 'w') as f:
|
21
|
+
f.write(content)
|
22
|
+
|
23
|
+
def traverse_tree(tree: dict, path=''):
|
24
|
+
files = []
|
25
|
+
for name, node in tree.items():
|
26
|
+
current_path = os.path.join(path, name)
|
27
|
+
if isinstance(node, dict):
|
28
|
+
files.extend(traverse_tree(node, current_path))
|
29
|
+
else:
|
30
|
+
files.append(current_path)
|
31
|
+
return files
|
32
|
+
|
33
|
+
def test_collect_tree_all_files():
|
34
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
35
|
+
structure = {
|
36
|
+
'src': {
|
37
|
+
'module': {
|
38
|
+
'a.py': 'print("a")',
|
39
|
+
'b.txt': 'text',
|
40
|
+
}
|
41
|
+
},
|
42
|
+
'tests': {
|
43
|
+
'test_a.py': 'print("test")'
|
44
|
+
},
|
45
|
+
'README.md': '# Readme'
|
46
|
+
}
|
47
|
+
create_directory_structure(temp_dir, structure)
|
48
|
+
args = type('Args', (object,), {
|
49
|
+
'path': temp_dir,
|
50
|
+
'output': os.path.join(temp_dir, 'output.md'),
|
51
|
+
'structure_only': True,
|
52
|
+
'debug': False,
|
53
|
+
'include': [],
|
54
|
+
'exclude': []
|
55
|
+
})
|
56
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
57
|
+
controller = ProjectController(args)
|
58
|
+
controller.collect_file_tree()
|
59
|
+
collected = traverse_tree(controller.file_tree.structure)
|
60
|
+
expected = [
|
61
|
+
'README.md',
|
62
|
+
os.path.join('src', 'module', 'a.py'),
|
63
|
+
os.path.join('src', 'module', 'b.txt'),
|
64
|
+
os.path.join('tests', 'test_a.py')
|
65
|
+
]
|
66
|
+
assert sorted(collected) == sorted(expected)
|
67
|
+
|
68
|
+
def test_collect_tree_literal_path():
|
69
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
70
|
+
structure = {
|
71
|
+
'src': {
|
72
|
+
'module': {
|
73
|
+
'a.py': 'print("a")',
|
74
|
+
'b.txt': 'text',
|
75
|
+
}
|
76
|
+
},
|
77
|
+
'tests': {
|
78
|
+
'test_a.py': 'print("test")'
|
79
|
+
},
|
80
|
+
'README.md': '# Readme'
|
81
|
+
}
|
82
|
+
create_directory_structure(temp_dir, structure)
|
83
|
+
# Request only the 'src' directory.
|
84
|
+
args = type('Args', (object,), {
|
85
|
+
'paths': ['src'],
|
86
|
+
'output': os.path.join(temp_dir, 'output.md'),
|
87
|
+
'structure_only': True,
|
88
|
+
'debug': False,
|
89
|
+
'include': [],
|
90
|
+
'exclude': []
|
91
|
+
})
|
92
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
93
|
+
controller = ProjectController(args)
|
94
|
+
controller.collect_file_tree()
|
95
|
+
collected = traverse_tree(controller.file_tree.structure)
|
96
|
+
expected = [
|
97
|
+
os.path.join('src', 'module', 'a.py'),
|
98
|
+
os.path.join('src', 'module', 'b.txt')
|
99
|
+
]
|
100
|
+
assert sorted(collected) == sorted(expected)
|
101
|
+
|
102
|
+
def test_collect_tree_multiple_paths():
|
103
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
104
|
+
structure = {
|
105
|
+
'src': {
|
106
|
+
'module': {
|
107
|
+
'a.py': 'print("a")',
|
108
|
+
}
|
109
|
+
},
|
110
|
+
'tests': {
|
111
|
+
'test_a.py': 'print("test")'
|
112
|
+
},
|
113
|
+
'README.md': '# Readme'
|
114
|
+
}
|
115
|
+
create_directory_structure(temp_dir, structure)
|
116
|
+
# Request multiple literal paths.
|
117
|
+
args = type('Args', (object,), {
|
118
|
+
'paths': ['README.md', 'tests'],
|
119
|
+
'output': os.path.join(temp_dir, 'output.md'),
|
120
|
+
'structure_only': True,
|
121
|
+
'debug': False,
|
122
|
+
'include': [],
|
123
|
+
'exclude': []
|
124
|
+
})
|
125
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
126
|
+
controller = ProjectController(args)
|
127
|
+
controller.collect_file_tree()
|
128
|
+
collected = traverse_tree(controller.file_tree.structure)
|
129
|
+
expected = [
|
130
|
+
'README.md',
|
131
|
+
os.path.join('tests', 'test_a.py')
|
132
|
+
]
|
133
|
+
assert sorted(collected) == sorted(expected)
|
@@ -49,9 +49,10 @@ def test_project_controller_includes_py_files():
|
|
49
49
|
'structure_only': False,
|
50
50
|
'debug': False
|
51
51
|
})
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
# Force repository root to be our temporary directory.
|
53
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
54
|
+
controller = ProjectController(args)
|
55
|
+
controller.run()
|
55
56
|
|
56
57
|
with open(args.output, 'r') as f:
|
57
58
|
output_content = f.read()
|
@@ -64,7 +65,6 @@ def test_project_controller_includes_py_files():
|
|
64
65
|
|
65
66
|
|
66
67
|
def test_project_controller_run():
|
67
|
-
# This test patches only MarkdownGenerator to verify that generate_markdown is called.
|
68
68
|
with tempfile.TemporaryDirectory() as temp_dir:
|
69
69
|
structure = {
|
70
70
|
'file1.txt': 'content',
|
@@ -79,14 +79,17 @@ def test_project_controller_run():
|
|
79
79
|
'include': [],
|
80
80
|
'exclude': []
|
81
81
|
})
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
# Patch _get_repo_root to force temp_dir as repo root.
|
83
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
84
|
+
# Patch the MarkdownGenerator in its actual module.
|
85
|
+
with patch('reposnap.core.markdown_generator.MarkdownGenerator') as MockMarkdownGenerator:
|
86
|
+
mock_instance = MagicMock()
|
87
|
+
MockMarkdownGenerator.return_value = mock_instance
|
85
88
|
|
86
|
-
|
87
|
-
|
89
|
+
controller = ProjectController(args)
|
90
|
+
controller.run()
|
88
91
|
|
89
|
-
|
92
|
+
mock_instance.generate_markdown.assert_called_once()
|
90
93
|
|
91
94
|
|
92
95
|
def test_include_pattern():
|
@@ -115,8 +118,9 @@ def test_include_pattern():
|
|
115
118
|
'include': ['*.py'],
|
116
119
|
'exclude': []
|
117
120
|
})
|
118
|
-
|
119
|
-
|
121
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
122
|
+
controller = ProjectController(args)
|
123
|
+
controller.collect_file_tree()
|
120
124
|
|
121
125
|
# Traverse the merged tree and collect file paths.
|
122
126
|
included_files = []
|
@@ -165,11 +169,10 @@ def test_exclude_pattern():
|
|
165
169
|
'include': [],
|
166
170
|
'exclude': ['*.md', '*.txt']
|
167
171
|
})
|
168
|
-
|
169
|
-
|
170
|
-
|
172
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
173
|
+
controller = ProjectController(args)
|
174
|
+
controller.collect_file_tree()
|
171
175
|
included_files = []
|
172
|
-
|
173
176
|
def traverse(tree, path=''):
|
174
177
|
for name, node in tree.items():
|
175
178
|
current_path = os.path.join(path, name)
|
@@ -177,9 +180,7 @@ def test_exclude_pattern():
|
|
177
180
|
traverse(node, current_path)
|
178
181
|
else:
|
179
182
|
included_files.append(current_path)
|
180
|
-
|
181
183
|
traverse(controller.file_tree.structure)
|
182
|
-
|
183
184
|
expected_files = [
|
184
185
|
os.path.join('src', 'module', 'file1.py'),
|
185
186
|
os.path.join('src', 'module', 'submodule', 'file3.py'),
|
@@ -187,7 +188,6 @@ def test_exclude_pattern():
|
|
187
188
|
]
|
188
189
|
assert sorted(included_files) == sorted(expected_files)
|
189
190
|
|
190
|
-
|
191
191
|
def test_include_and_exclude_patterns():
|
192
192
|
with tempfile.TemporaryDirectory() as temp_dir:
|
193
193
|
structure = {
|
@@ -217,11 +217,10 @@ def test_include_and_exclude_patterns():
|
|
217
217
|
'include': ['*foo*'],
|
218
218
|
'exclude': ['*submodule*']
|
219
219
|
})
|
220
|
-
|
221
|
-
|
222
|
-
|
220
|
+
with patch('reposnap.controllers.project_controller.ProjectController._get_repo_root', return_value=Path(temp_dir)):
|
221
|
+
controller = ProjectController(args)
|
222
|
+
controller.collect_file_tree()
|
223
223
|
collected = []
|
224
|
-
|
225
224
|
def traverse(tree, path=''):
|
226
225
|
for name, node in tree.items():
|
227
226
|
current_path = os.path.join(path, name)
|
@@ -230,7 +229,6 @@ def test_include_and_exclude_patterns():
|
|
230
229
|
traverse(node, current_path)
|
231
230
|
else:
|
232
231
|
collected.append(current_path)
|
233
|
-
|
234
232
|
traverse(controller.file_tree.structure)
|
235
233
|
expected = [
|
236
234
|
os.path.join('src'),
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|