|
1 | 1 | import os
|
2 |
| -from typing import List |
| 2 | +import re |
| 3 | +from typing import List, Optional, Set |
3 | 4 |
|
4 | 5 | import click
|
5 | 6 |
|
| 7 | +from cycode.cli.consts import SCA_GRADLE_ALL_SUB_PROJECTS_FLAG |
6 | 8 | from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
|
7 | 9 | from cycode.cli.models import Document
|
| 10 | +from cycode.cli.utils.path_utils import get_path_from_context |
| 11 | +from cycode.cli.utils.shell_executor import shell |
8 | 12 |
|
9 | 13 | BUILD_GRADLE_FILE_NAME = 'build.gradle'
|
10 | 14 | BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
|
11 | 15 | BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'
|
| 16 | +BUILD_GRADLE_ALL_PROJECTS_TIMEOUT = 180 |
| 17 | +BUILD_GRADLE_ALL_PROJECTS_COMMAND = ['gradle', 'projects'] |
| 18 | +ALL_PROJECTS_REGEX = r"[+-]{3} Project '(.*?)'" |
12 | 19 |
|
13 | 20 |
|
14 | 21 | class RestoreGradleDependencies(BaseRestoreDependencies):
|
15 |
| - def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None: |
| 22 | + def __init__( |
| 23 | + self, context: click.Context, is_git_diff: bool, command_timeout: int, projects: Optional[Set[str]] = None |
| 24 | + ) -> None: |
16 | 25 | super().__init__(context, is_git_diff, command_timeout, create_output_file_manually=True)
|
| 26 | + if projects is None: |
| 27 | + projects = set() |
| 28 | + self.projects = self.get_all_projects() if self.is_gradle_sub_projects() else projects |
| 29 | + |
| 30 | + def is_gradle_sub_projects(self) -> bool: |
| 31 | + return self.context.obj.get(SCA_GRADLE_ALL_SUB_PROJECTS_FLAG) |
17 | 32 |
|
18 | 33 | def is_project(self, document: Document) -> bool:
|
19 | 34 | return document.path.endswith(BUILD_GRADLE_FILE_NAME) or document.path.endswith(BUILD_GRADLE_KTS_FILE_NAME)
|
20 | 35 |
|
21 | 36 | def get_commands(self, manifest_file_path: str) -> List[List[str]]:
|
22 |
| - return [['gradle', 'dependencies', '-b', manifest_file_path, '-q', '--console', 'plain']] |
| 37 | + return ( |
| 38 | + self.get_commands_for_sub_projects(manifest_file_path) |
| 39 | + if self.is_gradle_sub_projects() |
| 40 | + else [['gradle', 'dependencies', '-b', manifest_file_path, '-q', '--console', 'plain']] |
| 41 | + ) |
23 | 42 |
|
24 | 43 | def get_lock_file_name(self) -> str:
|
25 | 44 | return BUILD_GRADLE_DEP_TREE_FILE_NAME
|
26 | 45 |
|
27 | 46 | def verify_restore_file_already_exist(self, restore_file_path: str) -> bool:
|
28 | 47 | return os.path.isfile(restore_file_path)
|
| 48 | + |
| 49 | + def get_working_directory(self, document: Document) -> Optional[str]: |
| 50 | + return get_path_from_context(self.context) if self.is_gradle_sub_projects() else None |
| 51 | + |
| 52 | + def get_all_projects(self) -> Set[str]: |
| 53 | + projects_output = shell( |
| 54 | + command=BUILD_GRADLE_ALL_PROJECTS_COMMAND, |
| 55 | + timeout=BUILD_GRADLE_ALL_PROJECTS_TIMEOUT, |
| 56 | + working_directory=get_path_from_context(self.context), |
| 57 | + ) |
| 58 | + |
| 59 | + projects = re.findall(ALL_PROJECTS_REGEX, projects_output) |
| 60 | + |
| 61 | + return set(projects) |
| 62 | + |
| 63 | + def get_commands_for_sub_projects(self, manifest_file_path: str) -> List[List[str]]: |
| 64 | + project_name = os.path.basename(os.path.dirname(manifest_file_path)) |
| 65 | + project_name = f':{project_name}' |
| 66 | + return ( |
| 67 | + [['gradle', f'{project_name}:dependencies', '-q', '--console', 'plain']] |
| 68 | + if project_name in self.projects |
| 69 | + else [] |
| 70 | + ) |
0 commit comments