xmipp3-installer 1.0.0__py3-none-any.whl

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 (70) hide show
  1. xmipp3_installer/__init__.py +1 -0
  2. xmipp3_installer/__main__.py +6 -0
  3. xmipp3_installer/api_client/api_client.py +50 -0
  4. xmipp3_installer/api_client/assembler/installation_info_assembler.py +181 -0
  5. xmipp3_installer/application/__init__.py +1 -0
  6. xmipp3_installer/application/cli/__init__.py +1 -0
  7. xmipp3_installer/application/cli/arguments/__init__.py +8 -0
  8. xmipp3_installer/application/cli/arguments/modes.py +130 -0
  9. xmipp3_installer/application/cli/arguments/params.py +76 -0
  10. xmipp3_installer/application/cli/cli.py +271 -0
  11. xmipp3_installer/application/cli/parsers/base_help_formatter.py +244 -0
  12. xmipp3_installer/application/cli/parsers/error_handler_parser.py +68 -0
  13. xmipp3_installer/application/cli/parsers/format.py +35 -0
  14. xmipp3_installer/application/cli/parsers/general_help_formatter.py +92 -0
  15. xmipp3_installer/application/cli/parsers/mode_help_formatter.py +115 -0
  16. xmipp3_installer/application/logger/__init__.py +0 -0
  17. xmipp3_installer/application/logger/errors.py +28 -0
  18. xmipp3_installer/application/logger/logger.py +230 -0
  19. xmipp3_installer/application/logger/predefined_messages.py +66 -0
  20. xmipp3_installer/application/user_interactions.py +16 -0
  21. xmipp3_installer/installer/__init__.py +1 -0
  22. xmipp3_installer/installer/constants/__init__.py +17 -0
  23. xmipp3_installer/installer/constants/paths.py +32 -0
  24. xmipp3_installer/installer/handlers/__init__.py +1 -0
  25. xmipp3_installer/installer/handlers/cmake/__init__.py +1 -0
  26. xmipp3_installer/installer/handlers/cmake/cmake_constants.py +27 -0
  27. xmipp3_installer/installer/handlers/cmake/cmake_handler.py +69 -0
  28. xmipp3_installer/installer/handlers/conda_handler.py +13 -0
  29. xmipp3_installer/installer/handlers/generic_package_handler.py +18 -0
  30. xmipp3_installer/installer/handlers/git_handler.py +185 -0
  31. xmipp3_installer/installer/handlers/shell_handler.py +114 -0
  32. xmipp3_installer/installer/handlers/versions_manager.py +98 -0
  33. xmipp3_installer/installer/installer_service.py +66 -0
  34. xmipp3_installer/installer/modes/__init__.py +1 -0
  35. xmipp3_installer/installer/modes/mode_all_executor.py +63 -0
  36. xmipp3_installer/installer/modes/mode_clean/__init__.py +1 -0
  37. xmipp3_installer/installer/modes/mode_clean/mode_clean_all_executor.py +44 -0
  38. xmipp3_installer/installer/modes/mode_clean/mode_clean_bin_executor.py +94 -0
  39. xmipp3_installer/installer/modes/mode_clean/mode_clean_executor.py +45 -0
  40. xmipp3_installer/installer/modes/mode_cmake/__init__.py +1 -0
  41. xmipp3_installer/installer/modes/mode_cmake/mode_cmake_executor.py +55 -0
  42. xmipp3_installer/installer/modes/mode_cmake/mode_compile_and_install_executor.py +49 -0
  43. xmipp3_installer/installer/modes/mode_cmake/mode_config_build_executor.py +64 -0
  44. xmipp3_installer/installer/modes/mode_config_executor.py +46 -0
  45. xmipp3_installer/installer/modes/mode_executor.py +43 -0
  46. xmipp3_installer/installer/modes/mode_get_sources_executor.py +132 -0
  47. xmipp3_installer/installer/modes/mode_git_executor.py +41 -0
  48. xmipp3_installer/installer/modes/mode_selector.py +25 -0
  49. xmipp3_installer/installer/modes/mode_sync/mode_add_model_executor.py +104 -0
  50. xmipp3_installer/installer/modes/mode_sync/mode_get_models_executor.py +51 -0
  51. xmipp3_installer/installer/modes/mode_sync/mode_sync_executor.py +48 -0
  52. xmipp3_installer/installer/modes/mode_sync/mode_test_executor.py +91 -0
  53. xmipp3_installer/installer/modes/mode_version_executor.py +164 -0
  54. xmipp3_installer/installer/orquestrator.py +37 -0
  55. xmipp3_installer/installer/urls.py +8 -0
  56. xmipp3_installer/repository/__init__.py +1 -0
  57. xmipp3_installer/repository/config.py +241 -0
  58. xmipp3_installer/repository/config_vars/__init__.py +0 -0
  59. xmipp3_installer/repository/config_vars/config_values_adapter.py +107 -0
  60. xmipp3_installer/repository/config_vars/default_values.py +36 -0
  61. xmipp3_installer/repository/config_vars/variables.py +48 -0
  62. xmipp3_installer/repository/invalid_config_line.py +15 -0
  63. xmipp3_installer/shared/file_operations.py +18 -0
  64. xmipp3_installer/shared/singleton.py +25 -0
  65. xmipp3_installer-1.0.0.dist-info/LICENSE +674 -0
  66. xmipp3_installer-1.0.0.dist-info/METADATA +729 -0
  67. xmipp3_installer-1.0.0.dist-info/RECORD +70 -0
  68. xmipp3_installer-1.0.0.dist-info/WHEEL +5 -0
  69. xmipp3_installer-1.0.0.dist-info/entry_points.txt +2 -0
  70. xmipp3_installer-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,94 @@
1
+ import glob
2
+ import os
3
+ import pathlib
4
+ from typing import List
5
+
6
+ from xmipp3_installer.application.logger.logger import logger
7
+ from xmipp3_installer.installer import constants
8
+ from xmipp3_installer.installer.constants import paths
9
+ from xmipp3_installer.installer.modes.mode_clean import mode_clean_executor
10
+
11
+ class ModeCleanBinExecutor(mode_clean_executor.ModeCleanExecutor):
12
+ def _get_paths_to_delete(self) -> List[str]:
13
+ """
14
+ ### Returns a list of all the paths to be deleted.
15
+
16
+ #### Returns:
17
+ - (list(str)): List containing all the paths to delete.
18
+ """
19
+ dblite_files = glob.glob(
20
+ "**/*.dblite",
21
+ recursive=True
22
+ )
23
+ return [
24
+ *dblite_files,
25
+ *ModeCleanBinExecutor.__get_compilation_files(),
26
+ *ModeCleanBinExecutor.__get_empty_dirs(),
27
+ *ModeCleanBinExecutor.__get_pycache_dirs(),
28
+ paths.BUILD_PATH
29
+ ]
30
+
31
+ def _get_confirmation_keyword(self) -> str:
32
+ """
33
+ ### Returns the keyword needed to be introduced by the user to confirm an operation.
34
+
35
+ #### Returns:
36
+ - (str): Confirmation keyword.
37
+ """
38
+ return "y"
39
+
40
+ def _get_confirmation_message(self) -> str:
41
+ """
42
+ ### Returns message to be printed when asking for user confirmation.
43
+
44
+ #### Returns:
45
+ - (str): Confirmation message.
46
+ """
47
+ return '\n'.join([
48
+ logger.yellow(f"WARNING: This will DELETE from {paths.SOURCES_PATH} all *.so, *.os and *.o files. Also the *.pyc and *.dblite files"),
49
+ logger.yellow(f"If you are sure you want to do this, type '{self._get_confirmation_keyword()}' (case sensitive):")
50
+ ])
51
+
52
+ @staticmethod
53
+ def __get_compilation_files():
54
+ """
55
+ ### Returns a list of all the compilation-related files.
56
+
57
+ #### Returns:
58
+ - (list(str)): List containing all the paths to compilation-related files.
59
+ """
60
+ compilation_files = []
61
+ for root, _, files in os.walk(paths.SOURCES_PATH):
62
+ for pattern in ['*.so', '*.os', '*.o']:
63
+ for filename in glob.fnmatch.filter(files, pattern):
64
+ compilation_files.append(os.path.join(root, filename))
65
+ return compilation_files
66
+
67
+ @staticmethod
68
+ def __get_empty_dirs() -> List[str]:
69
+ """
70
+ ### Returns a list with all the empty directories inside the programs folder.
71
+
72
+ #### Returns:
73
+ - (list(str)): List containing the paths to all the empty directories.
74
+ """
75
+ empty_dirs = []
76
+ for root, dirs, files in os.walk(os.path.join(
77
+ paths.SOURCES_PATH, constants.XMIPP, "applications", "programs"
78
+ )):
79
+ if not len(dirs) and not len(files):
80
+ empty_dirs.append(root)
81
+ return empty_dirs
82
+
83
+ @staticmethod
84
+ def __get_pycache_dirs() -> List[str]:
85
+ """
86
+ ### Returns a list of all the __pycache__ directories.
87
+
88
+ #### Returns:
89
+ - (list(str)): List containing all the paths to __pycache__ directories.
90
+ """
91
+ return [
92
+ str(path) for path in pathlib.Path().rglob('__pycache__')
93
+ ]
94
+
@@ -0,0 +1,45 @@
1
+ from abc import abstractmethod
2
+ from typing import Tuple, List
3
+
4
+ from xmipp3_installer.application import user_interactions
5
+ from xmipp3_installer.application.logger import errors
6
+ from xmipp3_installer.application.logger import predefined_messages
7
+ from xmipp3_installer.application.logger.logger import logger
8
+ from xmipp3_installer.installer.modes import mode_executor
9
+ from xmipp3_installer.shared import file_operations
10
+
11
+ class ModeCleanExecutor(mode_executor.ModeExecutor):
12
+ def run(self) -> Tuple[int, str]:
13
+ """
14
+ ### Deletes the compiled binaries.
15
+
16
+ #### Returns:
17
+ - (tuple(int, str)): Tuple containing the error status and an error message if there was an error.
18
+ """
19
+ if not self.__get_confirmation():
20
+ return errors.INTERRUPTED_ERROR, ""
21
+ file_operations.delete_paths(self._get_paths_to_delete())
22
+ logger(predefined_messages.get_done_message())
23
+ return 0, ""
24
+
25
+ def __get_confirmation(self) -> bool:
26
+ """
27
+ ### Asks the user for confirmation.
28
+
29
+ #### Returns:
30
+ - (bool): True if the user confirms, False otherwise.
31
+ """
32
+ logger(self._get_confirmation_message())
33
+ return user_interactions.get_user_confirmation(self._get_confirmation_keyword())
34
+
35
+ @abstractmethod
36
+ def _get_paths_to_delete(self) -> List[str]:
37
+ """Get paths to delete method to be implemented by the inheriting classes."""
38
+
39
+ @abstractmethod
40
+ def _get_confirmation_message(self) -> str:
41
+ """Get confirmation message method to be implemented by the inheriting classes."""
42
+
43
+ @abstractmethod
44
+ def _get_confirmation_keyword(self) -> str:
45
+ """Get confirmation keyword method to be implemented by the inheriting classes."""
@@ -0,0 +1 @@
1
+ """### Contains the executors for the CMake modes."""
@@ -0,0 +1,55 @@
1
+ import shutil
2
+ from abc import abstractmethod
3
+ from typing import Dict, Tuple, Optional
4
+
5
+ from xmipp3_installer.application.cli.arguments import params
6
+ from xmipp3_installer.application.logger import errors
7
+ from xmipp3_installer.installer.modes import mode_executor
8
+ from xmipp3_installer.repository.config_vars import variables
9
+
10
+ class ModeCMakeExecutor(mode_executor.ModeExecutor):
11
+ def __init__(self, context: Dict):
12
+ """
13
+ ### Constructor.
14
+
15
+ #### Params:
16
+ - context (dict): Dictionary containing the installation context variables.
17
+ """
18
+ super().__init__(context)
19
+ self.substitute = not context[params.PARAM_KEEP_OUTPUT]
20
+ self.cmake = context[variables.CMAKE]
21
+ self.build_type = context[variables.BUILD_TYPE]
22
+
23
+ def run(self) -> Tuple[int, str]:
24
+ """
25
+ ### Runs the CMake config with the appropiate params.
26
+
27
+ #### Returns:
28
+ - (tuple(int, str)): Tuple containing the error status and an error message if there was an error.
29
+ """
30
+ cmake = self.__get_cmake_executable()
31
+ if not cmake:
32
+ return errors.CMAKE_ERROR, "CMake installation not found."
33
+ return self._run_cmake_mode(cmake)
34
+
35
+ def _set_executor_config(self):
36
+ """
37
+ ### Sets the specific executor params for this mode.
38
+ """
39
+ super()._set_executor_config()
40
+ self.logs_to_file = True
41
+ self.prints_with_substitution = True
42
+
43
+ def __get_cmake_executable(self) -> Optional[str]:
44
+ """
45
+ ### Returns the path to the CMake executable to be used.
46
+
47
+ #### Returns:
48
+ - (str | None): Path to the CMake executable. None if it was not found.
49
+ """
50
+ return self.cmake or shutil.which("cmake")
51
+
52
+ @abstractmethod
53
+ def _run_cmake_mode(self, cmake: str) -> Tuple[int, str]:
54
+ """Run CMake mode method to be implemented by inheriting classes."""
55
+
@@ -0,0 +1,49 @@
1
+ from typing import Tuple, Dict
2
+
3
+ from xmipp3_installer.application.cli.arguments import params
4
+ from xmipp3_installer.application.logger import predefined_messages, errors
5
+ from xmipp3_installer.application.logger.logger import logger
6
+ from xmipp3_installer.installer.constants import paths
7
+ from xmipp3_installer.installer.handlers import shell_handler
8
+ from xmipp3_installer.installer.modes.mode_cmake import mode_cmake_executor
9
+
10
+ class ModeCompileAndInstallExecutor(mode_cmake_executor.ModeCMakeExecutor):
11
+ def __init__(self, context: Dict):
12
+ """
13
+ ### Constructor.
14
+
15
+ #### Params:
16
+ - context (dict): Dictionary containing the installation context variables.
17
+ """
18
+ super().__init__(context)
19
+ self.jobs = context[params.PARAM_JOBS]
20
+
21
+ def _set_executor_config(self):
22
+ """
23
+ ### Sets the specific executor params for this mode.
24
+ """
25
+ super()._set_executor_config()
26
+ self.prints_banner_on_exit = True
27
+
28
+ def _run_cmake_mode(self, cmake: str) -> Tuple[int, str]:
29
+ """
30
+ ### Runs the CMake compilation & installation with the appropiate params.
31
+
32
+ #### Params:
33
+ - cmake (str): Path to CMake executable.
34
+
35
+ #### Returns:
36
+ - (tuple(int, str)): Tuple containing the error status and an error message if there was an error.
37
+ """
38
+ logger(predefined_messages.get_section_message("Compiling with CMake"))
39
+ cmd = f"{cmake} --build {paths.BUILD_PATH} --config {self.build_type} -j {self.jobs}"
40
+ if shell_handler.run_shell_command_in_streaming(cmd, show_output=True, substitute=self.substitute):
41
+ return errors.CMAKE_COMPILE_ERROR, ""
42
+
43
+ installation_section_message = predefined_messages.get_section_message("Installing with CMake")
44
+ logger(f"\n{installation_section_message}")
45
+ cmd = f"{cmake} --install {paths.BUILD_PATH} --config {self.build_type}"
46
+ if shell_handler.run_shell_command_in_streaming(cmd, show_output=True, substitute=self.substitute):
47
+ return errors.CMAKE_INSTALL_ERROR, ""
48
+ return 0, ""
49
+
@@ -0,0 +1,64 @@
1
+ from typing import Tuple, List, Optional, Union
2
+
3
+ from xmipp3_installer.application.logger import predefined_messages, errors
4
+ from xmipp3_installer.application.logger.logger import logger
5
+ from xmipp3_installer.installer.constants import paths
6
+ from xmipp3_installer.installer.handlers import shell_handler
7
+ from xmipp3_installer.installer.modes.mode_cmake import mode_cmake_executor
8
+ from xmipp3_installer.repository.config_vars import variables
9
+
10
+ class ModeConfigBuildExecutor(mode_cmake_executor.ModeCMakeExecutor):
11
+ def _run_cmake_mode(self, cmake: str) -> Tuple[int, str]:
12
+ """
13
+ ### Runs the CMake config with the appropiate params.
14
+
15
+ #### Params:
16
+ - cmake (str): Path to CMake executable.
17
+
18
+ #### Returns:
19
+ - (tuple(int, str)): Tuple containing the error status and an error message if there was an error.
20
+ """
21
+ logger(predefined_messages.get_section_message("Configuring with CMake"))
22
+ cmd = f"{cmake} -S . -B {paths.BUILD_PATH} -DCMAKE_BUILD_TYPE={self.build_type} {self.__get_cmake_vars()}"
23
+ if shell_handler.run_shell_command_in_streaming(cmd, show_output=True, substitute=self.substitute):
24
+ return errors.CMAKE_CONFIGURE_ERROR, ""
25
+ return 0, ""
26
+
27
+ def __get_cmake_vars(self) -> str:
28
+ """
29
+ ### Returns the CMake variables required for the configuration step.
30
+
31
+ #### Returns:
32
+ - (str): String containing all required CMake variables
33
+ """
34
+ return " ".join([
35
+ f"-D{variable_key}={self.context[variable_key]}" for variable_key
36
+ in self.__get_config_vars() if not self.__is_empty(self.context[variable_key])
37
+ ])
38
+
39
+ def __get_config_vars(self) -> List[str]:
40
+ """
41
+ ### Returns all non-internal config variable keys.
42
+
43
+ #### Returns:
44
+ - (list(str)): A list containing all non-internal config variable keys.
45
+ """
46
+ all_config_var_keys = [
47
+ config_var for variable_section in variables.CONFIG_VARIABLES.values()
48
+ for config_var in variable_section
49
+ ]
50
+ non_internal_keys = list(set(all_config_var_keys) - set(variables.INTERNAL_LOGIC_VARS))
51
+ non_internal_keys.sort() # To keep order consistency
52
+ return non_internal_keys
53
+
54
+ def __is_empty(self, value: Optional[Union[bool, str]]) -> bool:
55
+ """
56
+ ### Checks if the given config value is empty.
57
+
58
+ #### Params:
59
+ - value (bool | str | None): Value to be checked.
60
+
61
+ #### Returns:
62
+ - (bool): True if it is empty, False otherwise.
63
+ """
64
+ return value is None or value == ""
@@ -0,0 +1,46 @@
1
+ import os
2
+ from typing import Dict, Tuple
3
+
4
+ from xmipp3_installer.application.logger import errors
5
+ from xmipp3_installer.application.logger import predefined_messages
6
+ from xmipp3_installer.application.logger.logger import logger
7
+ from xmipp3_installer.application.cli.arguments import params
8
+ from xmipp3_installer.installer.constants import paths
9
+ from xmipp3_installer.installer.modes import mode_executor
10
+ from xmipp3_installer.repository import config
11
+
12
+ class ModeConfigExecutor(mode_executor.ModeExecutor):
13
+ def __init__(self, context: Dict):
14
+ """
15
+ ### Constructor.
16
+
17
+ #### Params:
18
+ - context (dict): Dictionary containing the installation context variables.
19
+ """
20
+ super().__init__(context)
21
+ self.overwrite = context.pop(params.PARAM_OVERWRITE)
22
+ self.config_values = {}
23
+
24
+ def run(self) -> Tuple[int, str]:
25
+ """
26
+ ### Reads the config file and writes to it formatting properly with the appropiate values.
27
+
28
+ #### Returns:
29
+ - (tuple(int, str)): Tuple containing the error status and an error message if there was an error.
30
+ """
31
+ logger(predefined_messages.get_section_message("Managing config file"))
32
+ action_message = (
33
+ "Generating config file from scratch with default values..."
34
+ if self.overwrite or not os.path.exists(paths.CONFIG_FILE) else
35
+ "Reading config file..."
36
+ )
37
+ logger(action_message)
38
+ try:
39
+ file_handler = config.ConfigurationFileHandler()
40
+ file_handler.write_config(overwrite=self.overwrite)
41
+ except PermissionError as permission_error:
42
+ return errors.IO_ERROR, str(permission_error)
43
+ self.config_values = file_handler.values
44
+ logger(predefined_messages.get_done_message())
45
+ return 0, ""
46
+
@@ -0,0 +1,43 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, Tuple
3
+
4
+ from xmipp3_installer.application.logger.logger import logger
5
+ from xmipp3_installer.installer.constants import paths
6
+
7
+ class ModeExecutor(ABC):
8
+ """
9
+ ### Base executor interface for installer modes.
10
+ """
11
+ def __init__(self, context: Dict):
12
+ """
13
+ ### Constructor.
14
+
15
+ #### Params:
16
+ - context (dict): Dictionary containing the installation context variables.
17
+ """
18
+ super().__init__()
19
+ self.context = context
20
+ self._set_executor_config()
21
+ self.__configure_logger()
22
+
23
+ def _set_executor_config(self):
24
+ """
25
+ ### Sets the specific executor params for this mode.
26
+ """
27
+ self.logs_to_file = False
28
+ self.prints_with_substitution = False
29
+ self.prints_banner_on_exit = False
30
+ self.sends_installation_info = False
31
+
32
+ def __configure_logger(self):
33
+ """
34
+ ### Configures the logger according to the specified config.
35
+ """
36
+ if self.logs_to_file:
37
+ logger.start_log_file(paths.LOG_FILE)
38
+ if self.prints_with_substitution:
39
+ logger.set_allow_substitution(True)
40
+
41
+ @abstractmethod
42
+ def run(self) -> Tuple[int, str]:
43
+ """Run method to be implemented by inheriting classes."""
@@ -0,0 +1,132 @@
1
+ import os
2
+ from typing import Dict, Tuple, Optional
3
+
4
+ from xmipp3_installer.application.cli.arguments import params
5
+ from xmipp3_installer.application.logger import predefined_messages, errors
6
+ from xmipp3_installer.application.logger.logger import logger
7
+ from xmipp3_installer.installer import constants, urls
8
+ from xmipp3_installer.installer.constants import paths
9
+ from xmipp3_installer.installer.modes import mode_executor
10
+ from xmipp3_installer.installer.handlers import git_handler, versions_manager, shell_handler
11
+
12
+ class ModeGetSourcesExecutor(mode_executor.ModeExecutor):
13
+ def __init__(self, context: Dict):
14
+ """
15
+ ### Constructor.
16
+
17
+ #### Params:
18
+ - context (dict): Dictionary containing the installation context variables.
19
+ - substitute (bool): Optional. If True, printed text will be substituted with the next message.
20
+ """
21
+ super().__init__(context)
22
+ self.substitute = not context[params.PARAM_KEEP_OUTPUT]
23
+ self.target_branch = context.pop(params.PARAM_BRANCH)
24
+ versions: versions_manager.VersionsManager = context[constants.VERSIONS_CONTEXT_KEY]
25
+ self.xmipp_tag_name = versions.xmipp_version_name
26
+ self.source_versions: Dict = versions.sources_versions
27
+
28
+ def run(self) -> Tuple[int, str]:
29
+ """
30
+ ### Executes the given git command into all xmipp source repositories.
31
+
32
+ #### Returns:
33
+ - (tuple(int, str)): Tuple containing the return code and an error message if there was an error.
34
+ """
35
+ logger(predefined_messages.get_section_message("Getting Xmipp sources"))
36
+ for source in constants.XMIPP_SOURCES:
37
+ ret_code, output = self.__get_source(source)
38
+ if ret_code:
39
+ return errors.SOURCE_CLONE_ERROR, output
40
+ return 0, ""
41
+
42
+ def _set_executor_config(self):
43
+ """
44
+ ### Sets the specific executor params for this mode.
45
+ """
46
+ super()._set_executor_config()
47
+ self.prints_with_substitution = True
48
+
49
+ def __select_ref_to_clone(self, source_name: str, source_repo: str) -> str:
50
+ """
51
+ ### Selects the reference to clone from the source.
52
+
53
+ #### Params:
54
+ - source_name (str): Name of the source to clone.
55
+ - source_repo (str): URL of the source's repository.
56
+
57
+ #### Returns:
58
+ - (str): The reference name to clone.
59
+ """
60
+ current_branch = git_handler.get_current_branch()
61
+ tag_name = None
62
+ if (
63
+ not current_branch or
64
+ current_branch == constants.MASTER_BRANCHNAME or
65
+ current_branch == self.xmipp_tag_name
66
+ ):
67
+ tag_name = self.source_versions.get(source_name)
68
+ return git_handler.get_clonable_branch(source_repo, self.target_branch, tag_name)
69
+
70
+ def __run_source_command(self, source_name: str, source_repo: str, target_branch: Optional[str]) -> Tuple[int, str]:
71
+ """
72
+ ### Executes git clone/checkout commands for a source repository.
73
+
74
+ If the source already exists locally:
75
+ - If target_branch is specified, checks out that branch.
76
+ - If no target_branch, returns success without changes.
77
+
78
+ If the source doesn't exist:
79
+ - Clones the repository with the specified branch.
80
+ - If no branch specified, clones with default branch.
81
+
82
+ #### Params:
83
+ - source_name (str): Name of the source repository.
84
+ - source_repo (str): URL of the git repository to clone from.
85
+ - target_branch (str | None): Branch or tag to checkout/clone.
86
+
87
+ #### Returns:
88
+ - (tuple(int, str)): Tuple containing the return code and the text output produced by the command.
89
+ """
90
+ source_path = paths.get_source_path(source_name)
91
+ if os.path.exists(source_path):
92
+ if not target_branch:
93
+ return 0, ""
94
+ return shell_handler.run_shell_command(
95
+ f"git checkout {target_branch}",
96
+ cwd=source_path
97
+ )
98
+
99
+ branch_str = (
100
+ f"{params.PARAMS[params.PARAM_BRANCH][params.LONG_VERSION]} {target_branch}"
101
+ if target_branch else ""
102
+ )
103
+ return shell_handler.run_shell_command(f"git clone{branch_str} {source_repo}.git", cwd=paths.SOURCES_PATH)
104
+
105
+ def __get_source(self, source_name: str) -> Tuple[int, str]:
106
+ """
107
+ ### Gets the given source.
108
+
109
+ It is cloned if it does not already exist locally.
110
+
111
+ #### Params:
112
+ - source_name (str): Name of the source to clone.
113
+
114
+ #### Returns:
115
+ - (tuple(int, str)): Tuple containing the return code and the text output produced by the command.
116
+ """
117
+ repo_url = f"{urls.I2PC_REPOSITORY_URL}{source_name}"
118
+ logger(f"Cloning {source_name}...", substitute=self.substitute)
119
+ logger(predefined_messages.get_working_message(), substitute=self.substitute)
120
+
121
+ clone_branch = self.__select_ref_to_clone(source_name, repo_url)
122
+ if self.target_branch and not clone_branch:
123
+ warning_message = logger.yellow("\n".join([
124
+ f"Warning: branch \'{self.target_branch}\' does not exist for repository with url {repo_url}.",
125
+ "Falling back to repository's default branch."
126
+ ]))
127
+ logger(warning_message, substitute=self.substitute)
128
+
129
+ ret_code, output = self.__run_source_command(source_name, repo_url, clone_branch)
130
+ if not ret_code:
131
+ logger(predefined_messages.get_done_message(), substitute=self.substitute)
132
+ return ret_code, output
@@ -0,0 +1,41 @@
1
+ from typing import Dict, Tuple
2
+
3
+ from xmipp3_installer.application.cli.arguments import params
4
+ from xmipp3_installer.application.logger.logger import logger
5
+ from xmipp3_installer.installer import constants
6
+ from xmipp3_installer.installer.constants import paths
7
+ from xmipp3_installer.installer.modes import mode_executor
8
+ from xmipp3_installer.installer.handlers import git_handler
9
+
10
+ class ModeGitExecutor(mode_executor.ModeExecutor):
11
+ def __init__(self, context: Dict):
12
+ """
13
+ ### Constructor.
14
+
15
+ #### Params:
16
+ - context (dict): Dictionary containing the installation context variables.
17
+ """
18
+ super().__init__(context)
19
+ command_param_list = context.pop(params.PARAM_GIT_COMMAND)
20
+ self.command = ' '.join(command_param_list)
21
+
22
+ def run(self) -> Tuple[int, str]:
23
+ """
24
+ ### Executes the given git command into all xmipp source repositories.
25
+
26
+ #### Returns:
27
+ - (tuple(int, str)): Tuple containing the return code and an error message if there was an error.
28
+ """
29
+ logger(f"Running command 'git {self.command}' for all xmipp sources...")
30
+
31
+ for source in [constants.XMIPP, *constants.XMIPP_SOURCES]:
32
+ logger("\n" + logger.blue(
33
+ f"Running command for {source} in path {paths.get_source_path(source)}..."
34
+ ))
35
+ ret_code, output = git_handler.execute_git_command_for_source(
36
+ self.command, source
37
+ )
38
+ if ret_code:
39
+ return ret_code, output
40
+
41
+ return 0, ""
@@ -0,0 +1,25 @@
1
+ from xmipp3_installer.application.cli.arguments import modes
2
+ from xmipp3_installer.installer.modes import (
3
+ mode_config_executor, mode_version_executor, mode_git_executor,
4
+ mode_get_sources_executor, mode_all_executor
5
+ )
6
+ from xmipp3_installer.installer.modes.mode_clean import mode_clean_all_executor, mode_clean_bin_executor
7
+ from xmipp3_installer.installer.modes.mode_sync import (
8
+ mode_add_model_executor, mode_get_models_executor, mode_test_executor
9
+ )
10
+ from xmipp3_installer.installer.modes.mode_cmake import mode_config_build_executor, mode_compile_and_install_executor
11
+
12
+ MODE_EXECUTORS = {
13
+ modes.MODE_ADD_MODEL: mode_add_model_executor.ModeAddModelExecutor,
14
+ modes.MODE_ALL: mode_all_executor.ModeAllExecutor,
15
+ modes.MODE_CLEAN_ALL: mode_clean_all_executor.ModeCleanAllExecutor,
16
+ modes.MODE_CLEAN_BIN: mode_clean_bin_executor.ModeCleanBinExecutor,
17
+ modes.MODE_COMPILE_AND_INSTALL: mode_compile_and_install_executor.ModeCompileAndInstallExecutor,
18
+ modes.MODE_CONFIG_BUILD: mode_config_build_executor.ModeConfigBuildExecutor,
19
+ modes.MODE_CONFIG: mode_config_executor.ModeConfigExecutor,
20
+ modes.MODE_GET_MODELS: mode_get_models_executor.ModeGetModelsExecutor,
21
+ modes.MODE_GET_SOURCES: mode_get_sources_executor.ModeGetSourcesExecutor,
22
+ modes.MODE_GIT: mode_git_executor.ModeGitExecutor,
23
+ modes.MODE_TEST: mode_test_executor.ModeTestExecutor,
24
+ modes.MODE_VERSION: mode_version_executor.ModeVersionExecutor
25
+ }