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