A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5using UnityEngine;
6
7using Codice.Client.Common;
8using Codice.Client.Common.Threading;
9using Codice.Client.Common.WebApi;
10using Codice.CM.Common;
11using PlasticGui;
12using PlasticGui.Configuration.CloudEdition;
13using PlasticGui.WorkspaceWindow.Home.Repositories;
14using PlasticGui.WorkspaceWindow.Home.Workspaces;
15using Unity.PlasticSCM.Editor.AssetUtils.Processor;
16using Unity.PlasticSCM.Editor.UI.Progress;
17
18namespace Unity.PlasticSCM.Editor.Views.CreateWorkspace
19{
20 internal class CreateWorkspaceView :
21 IPlasticDialogCloser,
22 IWorkspacesRefreshableView
23 {
24 internal interface ICreateWorkspaceListener
25 {
26 void OnWorkspaceCreated(WorkspaceInfo wkInfo, bool isGluonMode);
27 }
28
29 internal CreateWorkspaceView(
30 PlasticWindow parentWindow,
31 ICreateWorkspaceListener listener,
32 IPlasticAPI plasticApi,
33 IPlasticWebRestApi plasticWebRestApi,
34 string workspacePath)
35 {
36 mParentWindow = parentWindow;
37 mCreateWorkspaceListener = listener;
38 mWorkspacePath = workspacePath;
39 mPlasticWebRestApi = plasticWebRestApi;
40
41 mProgressControls = new ProgressControlsForViews();
42 mWorkspaceOperations = new WorkspaceOperations(this, mProgressControls, null);
43 mCreateWorkspaceState = CreateWorkspaceViewState.BuildForProjectDefaults();
44
45 Initialize(plasticApi, plasticWebRestApi);
46 }
47
48 internal void Update()
49 {
50 mProgressControls.UpdateProgress(mParentWindow);
51 }
52
53 internal void OnGUI()
54 {
55 if (Event.current.type == EventType.Layout)
56 {
57 mProgressControls.ProgressData.CopyInto(
58 mCreateWorkspaceState.ProgressData);
59 }
60
61 string repository = mCreateWorkspaceState.Repository;
62
63 DrawCreateWorkspace.ForState(
64 SelectRepository,
65 CreateRepository,
66 ValidateAndCreateWorkspace,
67 mParentWindow,
68 mPlasticWebRestApi,
69 mDefaultServer,
70 ref mCreateWorkspaceState);
71
72 if (repository == mCreateWorkspaceState.Repository)
73 return;
74
75 SynchronizeRepositoryAndWorkspace();
76 }
77
78 void Initialize(IPlasticAPI plasticApi, IPlasticWebRestApi plasticWebRestApi)
79 {
80 ((IProgressControls) mProgressControls).ShowProgress(string.Empty);
81
82 WorkspaceInfo[] allWorkspaces = null;
83 IList allRepositories = null;
84 string repositoryProject = null;
85
86 string localProjectFolder = Application.productName;
87
88 IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
89 waiter.Execute(
90 /*threadOperationDelegate*/ delegate
91 {
92 mDefaultServer = GetDefaultServer.ToCreateWorkspace(plasticWebRestApi);
93
94 allWorkspaces = plasticApi.GetAllWorkspacesArray();
95 allRepositories = plasticApi.GetAllRepositories(mDefaultServer, true);
96
97 if (OrganizationsInformation.IsUnityOrganization(mDefaultServer))
98 {
99 List<string> serverProjects = OrganizationsInformation.GetOrganizationProjects(mDefaultServer);
100
101 if (serverProjects.Count == 0)
102 {
103 return;
104 }
105
106 // If any of the organization projects match in name with the local project, we select it.
107 // Otherwise, we return the first project in alphabetic order
108 repositoryProject = serverProjects.Contains(localProjectFolder)
109 ? localProjectFolder
110 : serverProjects.First();
111 }
112 },
113 /*afterOperationDelegate*/ delegate
114 {
115 ((IProgressControls) mProgressControls).HideProgress();
116
117 if (waiter.Exception != null)
118 {
119 DisplayException(mProgressControls, waiter.Exception);
120 return;
121 }
122
123 string serverSpecPart = string.Format("@{0}", ResolveServer.ToDisplayString(mDefaultServer));
124
125 mCreateWorkspaceState.Repository = ValidRepositoryName.Get(
126 string.Format("{0}{1}", mCreateWorkspaceState.Repository, serverSpecPart),
127 allRepositories);
128
129 if (repositoryProject != null)
130 {
131 mCreateWorkspaceState.Repository = string.Format("{0}/{1}", repositoryProject, mCreateWorkspaceState.Repository);
132 }
133
134 string proposedWorkspaceName = mCreateWorkspaceState.Repository.Replace(serverSpecPart, string.Empty);
135
136 mCreateWorkspaceState.WorkspaceName = CreateWorkspaceDialogUserAssistant.GetNonExistingWkNameForName(
137 proposedWorkspaceName, allWorkspaces);
138
139 mDialogUserAssistant = CreateWorkspaceDialogUserAssistant.ForWkPathAndName(
140 mWorkspacePath,
141 allWorkspaces);
142
143 SynchronizeRepositoryAndWorkspace();
144 });
145 }
146
147 void SynchronizeRepositoryAndWorkspace()
148 {
149 if (mDialogUserAssistant == null)
150 {
151 return;
152 }
153
154 mDialogUserAssistant.RepositoryChanged(
155 mCreateWorkspaceState.Repository,
156 mCreateWorkspaceState.WorkspaceName,
157 mWorkspacePath);
158
159 mCreateWorkspaceState.WorkspaceName = mDialogUserAssistant.GetProposedWorkspaceName();
160 }
161
162 void SelectRepository(string repository)
163 {
164 mCreateWorkspaceState.Repository = repository;
165 SynchronizeRepositoryAndWorkspace();
166 }
167
168 void CreateRepository(RepositoryCreationData data)
169 {
170 if (!data.Result)
171 return;
172
173 ((IProgressControls)mProgressControls).ShowProgress(
174 PlasticLocalization.GetString(
175 PlasticLocalization.Name.CreatingRepository,
176 data.RepName));
177
178 RepositoryInfo createdRepository = null;
179
180 IThreadWaiter waiter = ThreadWaiter.GetWaiter();
181 waiter.Execute(
182 /*threadOperationDelegate*/ delegate
183 {
184 createdRepository = PlasticGui.Plastic.API.CreateRepository(
185 data.ServerName, data.RepName);
186 },
187 /*afterOperationDelegate*/ delegate
188 {
189 ((IProgressControls)mProgressControls).HideProgress();
190
191 if (waiter.Exception != null)
192 {
193 DisplayException(mProgressControls, waiter.Exception);
194 return;
195 }
196
197 if (createdRepository == null)
198 return;
199
200 mCreateWorkspaceState.Repository = createdRepository.GetRepSpec().ToDisplayString();
201
202 SynchronizeRepositoryAndWorkspace();
203 });
204 }
205
206 void ValidateAndCreateWorkspace(CreateWorkspaceViewState state)
207 {
208 // We need a conversion here because the actual repSpec is used during the AsyncValidation
209 // to call UpdateLastUsedRepositoryPreference. Also, it is the one to be used during wk creation
210 RepositorySpec repSpec = OrganizationsInformation.TryResolveRepositorySpecFromInput(state.Repository);
211
212 if (repSpec == null)
213 {
214 ((IProgressControls) mProgressControls).ShowError(
215 PlasticLocalization.Name.UnresolvedRepository.GetString(state.Repository));
216
217 return;
218 }
219
220 mWkCreationData = BuildCreationDataFromState(state, mWorkspacePath, repSpec);
221
222 // AsyncValidation calls IPlasticDialogCloser.CloseDialog() when the validation is ok
223 WorkspaceCreationValidation.AsyncValidation(mWkCreationData, this, mProgressControls);
224 }
225
226 void IPlasticDialogCloser.CloseDialog()
227 {
228 ((IProgressControls) mProgressControls).ShowProgress(string.Empty);
229
230 IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
231 waiter.Execute(
232 /*threadOperationDelegate*/ delegate
233 {
234 RepositorySpec repSpec = new SpecGenerator().GenRepositorySpec(
235 false, mWkCreationData.Repository, CmConnection.Get().UnityOrgResolver);
236
237 bool repositoryExist = PlasticGui.Plastic.API.CheckRepositoryExists(
238 repSpec.Server, repSpec.Name);
239
240 if (!repositoryExist)
241 PlasticGui.Plastic.API.CreateRepository(repSpec.Server, repSpec.Name);
242 },
243 /*afterOperationDelegate*/ delegate
244 {
245 ((IProgressControls)mProgressControls).HideProgress();
246
247 if (waiter.Exception != null)
248 {
249 DisplayException(mProgressControls, waiter.Exception);
250 return;
251 }
252
253 mWkCreationData.Result = true;
254 mWorkspaceOperations.CreateWorkspace(mWkCreationData);
255
256 // the operation calls IWorkspacesRefreshableView.RefreshAndSelect
257 // when the workspace is created
258 });
259 }
260
261 void IWorkspacesRefreshableView.RefreshAndSelect(WorkspaceInfo wkInfo)
262 {
263 UnityCloudProjectLinkMonitor.CheckCloudProjectAlignmentAsync(wkInfo);
264
265 PerformInitialCheckin.IfRepositoryIsEmpty(
266 wkInfo,
267 mWkCreationData.Repository,
268 mWkCreationData.IsGluonWorkspace,
269 PlasticGui.Plastic.API,
270 mProgressControls,
271 mCreateWorkspaceListener,
272 mParentWindow);
273 }
274
275 static WorkspaceCreationData BuildCreationDataFromState(
276 CreateWorkspaceViewState state,
277 string workspacePath,
278 RepositorySpec repSpec)
279 {
280 return new WorkspaceCreationData(
281 state.WorkspaceName,
282 workspacePath,
283 repSpec.ToString(),
284 state.WorkspaceMode == CreateWorkspaceViewState.WorkspaceModes.Gluon,
285 false);
286 }
287
288 static void DisplayException(
289 IProgressControls progressControls,
290 Exception ex)
291 {
292 ExceptionsHandler.LogException(
293 "CreateWorkspaceView", ex);
294
295 progressControls.ShowError(
296 ExceptionsHandler.GetCorrectExceptionMessage(ex));
297 }
298
299 class GetDefaultServer
300 {
301 internal static string ToCreateWorkspace(IPlasticWebRestApi plasticWebRestApi)
302 {
303 string clientConfServer = PlasticGui.Plastic.ConfigAPI.GetClientConfServer();
304
305 if (!EditionToken.IsCloudEdition())
306 return clientConfServer;
307
308 string cloudServer = PlasticGuiConfig.Get().
309 Configuration.DefaultCloudServer;
310
311 if (!string.IsNullOrEmpty(cloudServer))
312 return cloudServer;
313
314 CloudEditionCreds.Data config =
315 CloudEditionCreds.GetFromClientConf();
316
317 cloudServer = GetFirstCloudServer.
318 GetCloudServer(plasticWebRestApi, config.Email, config.Password);
319
320 if (string.IsNullOrEmpty(cloudServer))
321 return clientConfServer;
322
323 SaveCloudServer.ToPlasticGuiConfig(cloudServer);
324
325 return cloudServer;
326 }
327 }
328
329 WorkspaceCreationData mWkCreationData;
330 CreateWorkspaceViewState mCreateWorkspaceState;
331
332 CreateWorkspaceDialogUserAssistant mDialogUserAssistant;
333
334 string mDefaultServer;
335
336 readonly WorkspaceOperations mWorkspaceOperations;
337 readonly ProgressControlsForViews mProgressControls;
338 readonly string mWorkspacePath;
339 readonly ICreateWorkspaceListener mCreateWorkspaceListener;
340 readonly PlasticWindow mParentWindow;
341 readonly IPlasticWebRestApi mPlasticWebRestApi;
342 }
343}