Skip to content

Commit 091e642

Browse files
committed
Add new flag --skip-hash-collection
1 parent 6aa302e commit 091e642

File tree

13 files changed

+73
-34
lines changed

13 files changed

+73
-34
lines changed

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pip install -r requirements.txt
1515

1616
# Run specific detectors for testing
1717
python3 -m dependency_resolver docker <container_name>
18-
python3 -m dependency_resolver host --skip-system-scope
18+
python3 -m dependency_resolver host --skip-system-scope --skip-hash-generation
1919

2020
# Execute linting and formatting
2121
pre-commit run --files $(git diff --name-only --diff-filter=ACMR HEAD)

dependency_resolver/__main__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def parse_arguments() -> argparse.Namespace:
3636
%(prog)s --venv-path ~/.virtualenvs/myproject # Use specific virtual environment for pip
3737
%(prog)s --debug # Enable debug output
3838
%(prog)s --skip-system-scope # Skip system scope package managers
39+
%(prog)s --skip-hash-collection # Skip hash collection for improved performance
3940
""",
4041
)
4142

@@ -78,6 +79,12 @@ def parse_arguments() -> argparse.Namespace:
7879
help="Format JSON output with indentation",
7980
)
8081

82+
parser.add_argument(
83+
"--skip-hash-collection",
84+
action="store_true",
85+
help="Skip hash collection for packages and project locations to improve performance",
86+
)
87+
8188
return parser.parse_args()
8289

8390

@@ -122,7 +129,10 @@ def main() -> None:
122129
try:
123130
executor = create_executor(args.environment_type, args.environment_identifier, debug=args.debug)
124131
orchestrator = Orchestrator(
125-
debug=args.debug, skip_system_scope=args.skip_system_scope, venv_path=args.venv_path
132+
debug=args.debug,
133+
skip_system_scope=args.skip_system_scope,
134+
venv_path=args.venv_path,
135+
skip_hash_collection=args.skip_hash_collection,
126136
)
127137
dependencies = orchestrator.resolve_dependencies(executor, args.working_dir, args.only_container_info)
128138
formatter = OutputFormatter(debug=args.debug)

dependency_resolver/core/interfaces.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
3232

3333
@abstractmethod
3434
def get_dependencies(
35-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
35+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
3636
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
3737
"""Extract dependencies with versions and hashes.
3838
39+
Args:
40+
executor: Environment executor for running commands
41+
working_dir: Working directory to use
42+
skip_hash_collection: Skip hash collection for improved performance
43+
3944
Returns:
4045
tuple: (packages, metadata)
4146
- packages: List of package dicts with name, version, type, and optional hash

dependency_resolver/core/orchestrator.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ def __init__(
1616
debug: bool = False,
1717
skip_system_scope: bool = False,
1818
venv_path: str | None = None,
19+
skip_hash_collection: bool = False,
1920
):
2021
self.debug = debug
2122
self.skip_system_scope = skip_system_scope
23+
self.skip_hash_collection = skip_hash_collection
2224

2325
# Create detector instances
2426
self.detectors: list[PackageManagerDetector] = [
@@ -69,15 +71,19 @@ def resolve_dependencies(
6971

7072
# Special handling for docker-info detector
7173
if detector_name == "docker-info":
72-
packages, metadata = detector.get_dependencies(executor, working_dir)
74+
packages, metadata = detector.get_dependencies(
75+
executor, working_dir, skip_hash_collection=self.skip_hash_collection
76+
)
7377
if metadata: # Only include if we got container info
7478
metadata["type"] = "container"
7579
result["source"] = metadata
7680
if self.debug:
7781
print(f"Found container info for {detector_name}")
7882
else:
7983
# Standard handling for package detectors
80-
packages, metadata = detector.get_dependencies(executor, working_dir)
84+
packages, metadata = detector.get_dependencies(
85+
executor, working_dir, skip_hash_collection=self.skip_hash_collection
86+
)
8187

8288
if detector.has_system_scope(executor, working_dir):
8389
# System scope packages

dependency_resolver/detectors/apk_detector.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,22 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
2525
return apk_exit_code == 0
2626

2727
def get_dependencies(
28-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
28+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
2929
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
3030
"""Extract system packages with versions and architecture using apk list.
3131
3232
Uses 'apk list --installed' for comprehensive package information including architecture.
3333
See docs/technical/detectors/apk_detector.md
3434
35+
Args:
36+
skip_hash_collection: Not applicable for apk (no hash collection implemented)
37+
3538
Returns:
3639
tuple: (packages, metadata)
3740
- packages: List of package dicts with name, version, type
3841
- metadata: Empty dict (system scope has no metadata)
3942
"""
43+
_ = skip_hash_collection # Not applicable for apk detector
4044
command = "apk list --installed"
4145
stdout, _, exit_code = executor.execute_command(command, working_dir)
4246

dependency_resolver/detectors/docker_info_detector.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
1414
return isinstance(executor, DockerExecutor)
1515

1616
def get_dependencies(
17-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
17+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
1818
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
1919
"""Extract Docker container metadata.
2020
2121
Note: This detector returns metadata rather than packages, but conforms to the interface.
2222
The orchestrator handles this specially.
2323
"""
2424
_ = working_dir # Unused parameter, required by interface
25+
_ = skip_hash_collection # Not applicable for docker metadata
2526
if not isinstance(executor, DockerExecutor):
2627
return [], {}
2728

dependency_resolver/detectors/dpkg_detector.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
3131
return dpkg_exit_code == 0
3232

3333
def get_dependencies(
34-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
34+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
3535
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
3636
"""Extract system packages with versions using dpkg-query.
3737
@@ -49,8 +49,8 @@ def get_dependencies(
4949
if exit_code != 0:
5050
return [], {}
5151

52-
# Collect all package hashes in a single batch operation
53-
batch_hashes = self._collect_all_package_hashes(executor)
52+
# Collect all package hashes in a single batch operation (unless skipped)
53+
batch_hashes = {} if skip_hash_collection else self._collect_all_package_hashes(executor)
5454

5555
packages = []
5656
for line in stdout.strip().split("\n"):
@@ -65,13 +65,15 @@ def get_dependencies(
6565

6666
package_data = {"name": package_name, "version": full_version, "type": PACKAGE_TYPE_DPKG}
6767

68-
# Use batch-collected hash or fallback to individual lookup
69-
package_hash = batch_hashes.get(package_name)
70-
if not package_hash:
71-
package_hash = self._get_package_hash(executor, package_name, architecture)
68+
# Skip hash collection if requested
69+
if not skip_hash_collection:
70+
# Use batch-collected hash or fallback to individual lookup
71+
package_hash = batch_hashes.get(package_name)
72+
if not package_hash:
73+
package_hash = self._get_package_hash(executor, package_name, architecture)
7274

73-
if package_hash:
74-
package_data["hash"] = package_hash
75+
if package_hash:
76+
package_data["hash"] = package_hash
7577

7678
packages.append(package_data)
7779

dependency_resolver/detectors/maven_detector.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
2525
return executor.path_exists(f"{search_dir}/pom.xml")
2626

2727
def get_dependencies(
28-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
28+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
2929
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
3030
"""Extract Maven dependencies with versions.
3131
@@ -51,8 +51,8 @@ def get_dependencies(
5151

5252
# Build metadata for project scope
5353
metadata = {"location": location}
54-
# Generate location-based hash if we have packages
55-
if packages:
54+
# Generate location-based hash if we have packages (unless skipped)
55+
if packages and not skip_hash_collection:
5656
metadata["hash"] = self._generate_location_hash(executor, location)
5757

5858
return packages, metadata

dependency_resolver/detectors/npm_detector.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
3838
return executor.path_exists(f"{search_dir}/package-lock.json")
3939

4040
def get_dependencies(
41-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
41+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
4242
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
4343
"""Extract npm dependencies with versions.
4444
@@ -77,8 +77,8 @@ def get_dependencies(
7777
else:
7878
# Build metadata for project scope
7979
metadata = {"location": location}
80-
# Generate location-based hash if we have packages
81-
if packages:
80+
# Generate location-based hash if we have packages (unless skipped)
81+
if packages and not skip_hash_collection:
8282
metadata["hash"] = self._generate_location_hash(executor, location)
8383
return packages, metadata
8484

dependency_resolver/detectors/pip_detector.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def is_usable(self, executor: EnvironmentExecutor, working_dir: Optional[str] =
2727
return exit_code == 0
2828

2929
def get_dependencies(
30-
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None
30+
self, executor: EnvironmentExecutor, working_dir: Optional[str] = None, skip_hash_collection: bool = False
3131
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
3232
"""Extract pip dependencies with versions.
3333
@@ -72,8 +72,8 @@ def get_dependencies(
7272
else:
7373
# Build metadata for project scope
7474
metadata = {"location": location}
75-
# Generate location-based hash if we have packages
76-
if packages:
75+
# Generate location-based hash if we have packages (unless skipped)
76+
if packages and not skip_hash_collection:
7777
metadata["hash"] = self._generate_location_hash(executor, location)
7878
return packages, metadata
7979

0 commit comments

Comments
 (0)