13
13
14
14
import traceback
15
15
from pathlib import Path
16
- from typing import List , Dict
16
+ from typing import List , Optional , Tuple
17
17
18
18
from lean .components .api .api_client import APIClient
19
19
from lean .components .config .project_config_manager import ProjectConfigManager
20
20
from lean .components .util .library_manager import LibraryManager
21
21
from lean .components .util .logger import Logger
22
22
from lean .components .util .platform_manager import PlatformManager
23
23
from lean .components .util .project_manager import ProjectManager
24
- from lean .models .api import QCProject , QCLeanEnvironment , QCLanguage
24
+ from lean .models .api import QCProject , QCLanguage
25
25
from lean .models .utils import LeanLibraryReference
26
26
27
27
@@ -52,38 +52,54 @@ def __init__(self,
52
52
self ._platform_manager = platform_manager
53
53
self ._last_file = None
54
54
55
- def pull_projects (self , projects_to_pull : List [QCProject ], all_cloud_projects : List [QCProject ]) -> None :
55
+ def _get_libraries (self , project : QCProject , seen_projects : List [int ] = None ) -> List [QCProject ]:
56
+ if seen_projects is None :
57
+ seen_projects = [project .projectId ]
58
+
59
+ libraries = []
60
+ for library_id in project .libraries :
61
+ if library_id in seen_projects :
62
+ continue
63
+ seen_projects .append (library_id )
64
+ library = self ._api_client .projects .get (library_id )
65
+ libraries .append (library )
66
+ libraries .extend (self ._get_libraries (library , seen_projects ))
67
+
68
+ return libraries
69
+
70
+ def pull_projects (self , projects_to_pull : List [QCProject ], all_cloud_projects : Optional [List [QCProject ]]) -> None :
56
71
"""Pulls the given projects from the cloud to the local drive.
57
72
58
73
This will also pull libraries referenced by the project.
59
74
60
75
:param projects_to_pull: the cloud projects that need to be pulled
61
76
:param all_cloud_projects: all the projects available in the cloud
62
77
"""
63
- projects_to_pull .extend (self ._project_manager .get_cloud_projects_libraries (all_cloud_projects ,
64
- projects_to_pull ))
78
+ if all_cloud_projects is not None :
79
+ projects_to_pull .extend (self ._project_manager .get_cloud_projects_libraries (all_cloud_projects ,
80
+ projects_to_pull ))
81
+ else :
82
+ for project in projects_to_pull :
83
+ projects_to_pull .extend (self ._get_libraries (project , [p .projectId for p in projects_to_pull ]))
84
+
65
85
projects_to_pull = sorted (projects_to_pull , key = lambda p : p .name )
66
- environments = self ._api_client .lean .environments ()
67
- projects_not_pulled = []
68
- project_paths = {}
86
+ projects_with_paths = []
69
87
70
88
for index , project in enumerate (projects_to_pull , start = 1 ):
71
89
try :
72
90
self ._logger .info (f"[{ index } /{ len (projects_to_pull )} ] Pulling '{ project .name } '" )
73
- project_paths [ project . projectId ] = self ._pull_project (project , environments )
91
+ projects_with_paths . append (( project , self ._pull_project (project )) )
74
92
except Exception as ex :
75
- projects_not_pulled .append (project )
76
93
self ._logger .debug (traceback .format_exc ().strip ())
77
94
if self ._last_file is not None :
78
95
self ._logger .warn (
79
96
f"Cannot pull '{ project .name } ' (id { project .projectId } , failed on { self ._last_file } ): { ex } " )
80
97
else :
81
98
self ._logger .warn (f"Cannot pull '{ project .name } ' (id { project .projectId } ): { ex } " )
82
99
83
- projects_to_update = [project for project in projects_to_pull if project not in projects_not_pulled ]
84
- self ._update_local_library_references (projects_to_update , project_paths )
100
+ self ._update_local_library_references (projects_with_paths )
85
101
86
- def _pull_project (self , project : QCProject , environments : List [ QCLeanEnvironment ] ) -> Path :
102
+ def _pull_project (self , project : QCProject ) -> Path :
87
103
"""Pulls a single project from the cloud to the local drive.
88
104
89
105
Raises an error with a descriptive message if the project cannot be pulled.
@@ -103,18 +119,13 @@ def _pull_project(self, project: QCProject, environments: List[QCLeanEnvironment
103
119
project_config .set ("parameters" , {parameter .key : parameter .value for parameter in project .parameters })
104
120
project_config .set ("description" , project .description )
105
121
project_config .set ("organization-id" , project .organizationId )
122
+ project_config .set ("python-venv" , project .leanEnvironment )
106
123
107
124
if not project .leanPinnedToMaster :
108
125
project_config .set ("lean-engine" , project .leanVersionId )
109
126
else :
110
127
project_config .delete ("lean-engine" )
111
128
112
- python_venv = next ((env .path for env in environments if env .id == project .leanEnvironment ), None )
113
- if python_venv is not None :
114
- project_config .set ("python-venv" , project .leanEnvironment )
115
- else :
116
- project_config .delete ("python-venv" )
117
-
118
129
return local_project_path
119
130
120
131
def _pull_files (self , project : QCProject , local_project_path : Path ) -> None :
@@ -255,22 +266,19 @@ def _remove_local_library_references_from_project(self,
255
266
Path .cwd () / library_reference .path ,
256
267
True )
257
268
258
- def _update_local_library_references (self , projects : List [QCProject ], paths : Dict [int , Path ]) -> None :
259
- for project in projects :
260
- cloud_libraries_paths = [paths [library_id ]
261
- for library_id in project .libraries
262
- for library in projects if library .projectId == library_id ]
263
-
264
- project_path = paths [project .projectId ]
269
+ def _update_local_library_references (self , projects : List [Tuple [QCProject , Path ]]) -> None :
270
+ for project , path in projects :
271
+ cloud_libraries_paths = [library_path for library , library_path in projects
272
+ if library .projectId in project .libraries ]
265
273
266
274
# Add cloud library references to local config
267
- self ._add_local_library_references_to_project (project_path , cloud_libraries_paths )
275
+ self ._add_local_library_references_to_project (path , cloud_libraries_paths )
268
276
269
277
# Remove library references locally if they were removed in the cloud
270
- self ._remove_local_library_references_from_project (project_path , cloud_libraries_paths )
278
+ self ._remove_local_library_references_from_project (path , cloud_libraries_paths )
271
279
272
280
# Restore the project to automatically enable local auto-complete
273
- self ._restore_project (project , project_path )
281
+ self ._restore_project (project , path )
274
282
275
283
def _restore_project (self , project : QCProject , project_dir : Path ) -> None :
276
284
if project .language != QCLanguage .CSharp :
0 commit comments