This commit is contained in:
2025-01-17 13:10:42 +01:00
commit 4536213c91
15115 changed files with 1442174 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
using UnityEditor;
namespace Unity.PlasticSCM.Editor.CollabMigration
{
static class CloudProjectId
{
internal static bool HasValue()
{
if (PlasticPlugin.IsUnitTesting)
return false;
return !string.IsNullOrEmpty(GetValue());
}
internal static string GetValue()
{
//disable Warning CS0618 'PlayerSettings.cloudProjectId' is obsolete: 'cloudProjectId is deprecated
#pragma warning disable 0618
return PlayerSettings.cloudProjectId;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5326c7fb2eb17ce419ae9e925c9f26fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,263 @@
using System;
using System.IO;
using UnityEditor;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using Codice.CM.WorkspaceServer;
using Codice.LogWrapper;
using Unity.PlasticSCM.Editor.AssetUtils;
using Unity.PlasticSCM.Editor.Hub;
using Unity.PlasticSCM.Editor.WebApi;
namespace Unity.PlasticSCM.Editor.CollabMigration
{
public static class MigrateCollabProject
{
internal static void Initialize()
{
if (SessionState.GetInt(
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
MIGRATED_NOT_CALCULATED) == MIGRATED_NOTHING_TO_DO)
return;
EditorApplication.update += RunOnceWhenAccessTokenAndProjectIdAreInitialized;
}
internal static void RunOnceWhenAccessTokenAndProjectIdAreInitialized()
{
if (string.IsNullOrEmpty(CloudProjectSettings.accessToken))
return;
if (!CloudProjectId.HasValue())
return;
if (!SessionState.GetBool(
ProcessCommand.IS_PROCESS_COMMAND_ALREADY_EXECUTED_KEY, false))
return;
EditorApplication.update -= RunOnceWhenAccessTokenAndProjectIdAreInitialized;
string projectPath = ProjectPath.FromApplicationDataPath(
ApplicationDataPath.Get());
string projectGuid = CloudProjectId.GetValue();
if (!ShouldProjectBeMigrated(projectPath, projectGuid))
{
SessionState.SetInt(
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
MIGRATED_NOTHING_TO_DO);
return;
}
Execute(
CloudProjectSettings.accessToken,
projectPath,
projectGuid);
}
static bool ShouldProjectBeMigrated(
string projectPath,
string projectGuid)
{
if (SessionState.GetBool(
ProcessCommand.IS_PLASTIC_COMMAND_KEY, false))
{
return false;
}
string collabPath = GetCollabSnapshotFile(
projectPath, projectGuid);
if (!File.Exists(collabPath))
{
return false;
}
if (FindWorkspace.HasWorkspace(ApplicationDataPath.Get()))
{
return false;
}
return true;
}
static void Execute(
string unityAccessToken,
string projectPath,
string projectGuid)
{
string headCommitSha = GetCollabHeadCommitSha(projectPath, projectGuid);
if (string.IsNullOrEmpty(headCommitSha))
return;
PlasticApp.InitializeIfNeeded();
LaunchMigrationIfProjectIsArchivedAndMigrated(
unityAccessToken,
projectPath,
projectGuid,
headCommitSha);
}
internal static void DeletePlasticDirectoryIfExists(string projectPath)
{
WorkspaceInfo wkInfo = new WorkspaceInfo("wk", projectPath);
string plasticDirectory = WorkspaceConfigFile.GetPlasticWkConfigPath(wkInfo);
if (!Directory.Exists(plasticDirectory))
return;
Directory.Delete(plasticDirectory, true);
}
static void LaunchMigrationIfProjectIsArchivedAndMigrated(
string unityAccessToken,
string projectPath,
string projectGuid,
string headCommitSha)
{
IsCollabProjectMigratedResponse isMigratedResponse = null;
ChangesetFromCollabCommitResponse changesetResponse = null;
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
isMigratedResponse = WebRestApiClient.PlasticScm.
IsCollabProjectMigrated(unityAccessToken, projectGuid);
if (isMigratedResponse.Error != null)
return;
if (!isMigratedResponse.IsMigrated)
return;
OrganizationCredentials credentials = new OrganizationCredentials();
credentials.User = isMigratedResponse.Credentials.Email;
credentials.Password = isMigratedResponse.Credentials.Token;
string webLoginAccessToken = WebRestApiClient.CloudServer.WebLogin(
isMigratedResponse.WebServerUri,
isMigratedResponse.PlasticCloudOrganizationName,
credentials);
changesetResponse = WebRestApiClient.CloudServer.
GetChangesetFromCollabCommit(
isMigratedResponse.WebServerUri,
isMigratedResponse.PlasticCloudOrganizationName,
webLoginAccessToken, projectGuid, headCommitSha);
},
/*afterOperationDelegate*/ delegate
{
if (waiter.Exception != null)
{
ExceptionsHandler.LogException(
"IsCollabProjectArchivedAndMigrated",
waiter.Exception);
return;
}
if (isMigratedResponse.Error != null)
{
mLog.ErrorFormat(
"Unable to get IsCollabProjectMigratedResponse: {0} [code {1}]",
isMigratedResponse.Error.Message,
isMigratedResponse.Error.ErrorCode);
return;
}
if (!isMigratedResponse.IsMigrated)
{
SessionState.SetInt(
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
MIGRATED_NOTHING_TO_DO);
return;
}
if (changesetResponse.Error != null)
{
mLog.ErrorFormat(
"Unable to get ChangesetFromCollabCommitResponse: {0} [code {1}]",
changesetResponse.Error.Message,
changesetResponse.Error.ErrorCode);
return;
}
DeletePlasticDirectoryIfExists(projectPath);
MigrationDialog.Show(
null,
unityAccessToken,
projectPath,
isMigratedResponse.Credentials.Email,
isMigratedResponse.PlasticCloudOrganizationName,
new RepId(
changesetResponse.RepId,
changesetResponse.RepModuleId),
changesetResponse.ChangesetId,
changesetResponse.BranchId,
AfterWorkspaceMigrated);
});
}
static void AfterWorkspaceMigrated()
{
SessionState.SetInt(
IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY,
MIGRATED_NOTHING_TO_DO);
CollabPlugin.Disable();
mLog.DebugFormat(
"Disabled Collab Plugin after the migration for Project: {0}",
ProjectPath.FromApplicationDataPath(ApplicationDataPath.Get()));
}
static string GetCollabHeadCommitSha(
string projectPath,
string projectGuid)
{
string collabPath = GetCollabSnapshotFile(
projectPath, projectGuid);
if (!File.Exists(collabPath))
return null;
string text = File.ReadAllText(collabPath);
string[] chunks = text.Split(
new string[] { "currRevisionID" },
StringSplitOptions.None);
string current = chunks[1].Substring(3, 40);
if (!current.Contains("none"))
return current;
chunks = text.Split(
new string[] { "headRevisionID" },
StringSplitOptions.None);
return chunks[1].Substring(3, 40);
}
static string GetCollabSnapshotFile(
string projectPath,
string projectGuid)
{
return projectPath + "/Library/Collab/CollabSnapshot_" + projectGuid + ".txt";
}
const string IS_PROJECT_MIGRATED_ALREADY_CALCULATED_KEY =
"PlasticSCM.MigrateCollabProject.IsAlreadyCalculated";
const int MIGRATED_NOT_CALCULATED = 0;
const int MIGRATED_NOTHING_TO_DO = 1;
static readonly ILog mLog = PlasticApp.GetLogger("MigrateCollabProject");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ace6856390aa30340afb8eaf8a0168f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,416 @@
using System;
using UnityEditor;
using UnityEngine;
using Codice.Client.BaseCommands;
using Codice.Client.BaseCommands.Sync;
using Codice.Client.Common.EventTracking;
using Codice.Client.Common.Threading;
using Codice.CM.Common;
using Codice.LogWrapper;
using CodiceApp.EventTracking;
using PlasticGui;
using PlasticGui.WorkspaceWindow;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Progress;
using Unity.PlasticSCM.Editor.WebApi;
using Unity.PlasticSCM.Editor.Configuration;
namespace Unity.PlasticSCM.Editor.CollabMigration
{
internal class MigrationDialog : PlasticDialog
{
protected override Rect DefaultRect
{
get
{
var baseRect = base.DefaultRect;
return new Rect(baseRect.x, baseRect.y, 710, 260);
}
}
protected override string GetTitle()
{
return "Upgrade your Collaborate project to Unity Version Control";
}
//TODO: localize the strings
protected override void OnModalGUI()
{
GUILayout.BeginHorizontal();
DoIconArea();
GUILayout.Space(20);
DoContentArea();
GUILayout.EndHorizontal();
DoButtonsArea();
mProgressControls.UpdateDeterminateProgress(this);
}
internal static bool Show(
EditorWindow parentWindow,
string unityAccessToken,
string projectPath,
string user,
string organizationName,
RepId repId,
long changesetId,
long branchId,
Action afterWorkspaceMigratedAction)
{
MigrationDialog dialog = Create(
unityAccessToken,
projectPath,
user,
organizationName,
repId,
changesetId,
branchId,
afterWorkspaceMigratedAction,
new ProgressControlsForMigration());
return dialog.RunModal(parentWindow) == ResponseType.Ok;
}
void DoIconArea()
{
GUILayout.BeginVertical();
GUILayout.Space(30);
Rect iconRect = GUILayoutUtility.GetRect(
GUIContent.none, EditorStyles.label,
GUILayout.Width(60), GUILayout.Height(60));
GUI.DrawTexture(
iconRect,
Images.GetPlasticIcon(),
ScaleMode.ScaleToFit);
GUILayout.EndVertical();
}
void DoContentArea()
{
GUILayout.BeginVertical();
Title("Upgrade your Collaborate project to Unity Version Control");
GUILayout.Space(20);
Paragraph("Your Unity project has been upgraded (from Collaborate) to Unity Version Control free" +
" of charge by your administrator. Your local workspace will now be converted to a" +
" Unity Version Control workspace in just a few minutes. Select ?Migrate? to start the conversion process.");
DrawProgressForMigration.For(
mProgressControls.ProgressData);
GUILayout.Space(40);
GUILayout.EndVertical();
}
//TODO: localize the strings
void DoButtonsArea()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (Application.platform == RuntimePlatform.WindowsEditor)
{
DoOkButton();
DoCloseButton();
return;
}
DoCloseButton();
DoOkButton();
}
}
void DoOkButton()
{
if (mIsMigrationCompleted)
{
DoOpenPlasticButton();
return;
}
DoMigrateButton();
}
void DoCloseButton()
{
GUI.enabled = !mProgressControls.ProgressData.IsOperationRunning;
if (NormalButton(PlasticLocalization.GetString(
PlasticLocalization.Name.CloseButton)))
{
if (mIsMigrationCompleted)
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
TrackFeatureUseEvent.Features.CloseDialogAfterWorkspaceMigration);
else
TrackFeatureUseEvent.For(
GetEventCloudOrganizationInfo(),
TrackFeatureUseEvent.Features.DoNotMigrateWorkspace);
CloseButtonAction();
}
GUI.enabled = true;
}
void DoOpenPlasticButton()
{
if (!NormalButton("Open Unity Version Control"))
return;
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
TrackFeatureUseEvent.Features.OpenPlasticAfterWorkspaceMigration);
((IPlasticDialogCloser)this).CloseDialog();
ShowWindow.Plastic();
}
EventCloudOrganizationInfo GetEventCloudOrganizationInfo()
{
return new EventCloudOrganizationInfo()
{
Name = mOrganizationName,
ServerType = EventCloudOrganizationInfo.GetServerType(true),
User = mUser
};
}
void DoMigrateButton()
{
GUI.enabled = !mProgressControls.ProgressData.IsOperationRunning;
if (NormalButton("Migrate"))
{
if (EditorUtility.DisplayDialog(
"Collab migration to Unity Version Control",
"Are you sure to start the migration process?",
PlasticLocalization.GetString(PlasticLocalization.Name.YesButton),
PlasticLocalization.GetString(PlasticLocalization.Name.NoButton)))
{
TrackFeatureUseEvent.For(
GetEventCloudOrganizationInfo(),
TrackFeatureUseEvent.Features.MigrateWorkspace);
LaunchMigration(
mUnityAccessToken, mProjectPath,
mOrganizationName, mRepId,
mChangesetId, mBranchId,
mAfterWorkspaceMigratedAction,
mProgressControls);
}
else
{
TrackFeatureUseEvent.For(
GetEventCloudOrganizationInfo(),
TrackFeatureUseEvent.Features.DoNotMigrateWorkspace);
}
}
GUI.enabled = true;
}
static void UpdateProgress(string wkPath,
CreateWorkspaceFromCollab.Progress progress,
ProgressControlsForMigration progressControls,
BuildProgressSpeedAndRemainingTime.ProgressData progressData)
{
string header = MigrationProgressRender.FixNotificationPath(
wkPath, progress.CurrentFile);
string message = MigrationProgressRender.GetProgressString(
progress,
progressData,
DateTime.Now,
0.05,
"Calculating...",
"Converted {0} of {1}bytes ({2} of 1 file){4}",
"Converted {0} of {1}bytes ({2} of {3} files {4})",
"remaining");
float percent = GetProgressBarPercent.ForTransfer(
progress.ProcessedSize, progress.TotalSize) / 100f;
progressControls.ShowProgress(header, message, percent);
}
void LaunchMigration(
string unityAccessToken,
string projectPath,
string organizationName,
RepId repId,
long changesetId,
long branchId,
Action afterWorkspaceMigratedAction,
ProgressControlsForMigration progressControls)
{
string serverName = string.Format(
"{0}@cloud", organizationName);
TokenExchangeResponse tokenExchangeResponse = null;
mWorkspaceInfo = null;
CreateWorkspaceFromCollab.Progress progress = new CreateWorkspaceFromCollab.Progress();
BuildProgressSpeedAndRemainingTime.ProgressData progressData =
new BuildProgressSpeedAndRemainingTime.ProgressData(DateTime.Now);
IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);
waiter.Execute(
/*threadOperationDelegate*/
delegate
{
tokenExchangeResponse = AutoConfig.PlasticCredentials(
unityAccessToken,
serverName);
if (tokenExchangeResponse.Error != null)
{
return;
}
RepositoryInfo repInfo = new BaseCommandsImpl().
GetRepositoryInfo(repId, serverName);
if (repInfo == null)
{
return;
}
repInfo.SetExplicitResolvedServer(serverName);
mWorkspaceInfo = CreateWorkspaceFromCollab.Create(
projectPath, repInfo.Name, repInfo,
changesetId, branchId,
progress);
},
/*afterOperationDelegate*/
delegate
{
progressControls.HideProgress();
if (waiter.Exception != null)
{
DisplayException(progressControls, waiter.Exception);
TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
return;
}
if (tokenExchangeResponse.Error != null)
{
mLog.ErrorFormat(
"Unable to get TokenExchangeResponse: {0} [code {1}]",
tokenExchangeResponse.Error.Message,
tokenExchangeResponse.Error.ErrorCode);
}
if (tokenExchangeResponse.Error != null ||
mWorkspaceInfo == null)
{
progressControls.ShowError(
"Failed to convert your workspace to Unity Version Control");
TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
return;
}
progressControls.ShowSuccess(
"Your workspace has been successfully converted to Unity Version Control");
mIsMigrationCompleted = true;
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedSuccess);
afterWorkspaceMigratedAction();
},
/*timerTickDelegate*/
delegate
{
UpdateProgress(projectPath, progress, progressControls, progressData);
});
}
void TrackWorkspaceMigrationFinishedFailureEvent(WorkspaceInfo wkInfo)
{
if (wkInfo == null)
{
TrackFeatureUseEvent.For(
GetEventCloudOrganizationInfo(),
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedFailure);
return;
}
TrackFeatureUseEvent.For(
PlasticGui.Plastic.API.GetRepositorySpec(wkInfo),
TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedFailure);
}
static void DisplayException(
ProgressControlsForMigration progressControls,
Exception ex)
{
ExceptionsHandler.LogException(
"MigrationDialog", ex);
progressControls.ShowError(
ExceptionsHandler.GetCorrectExceptionMessage(ex));
}
static MigrationDialog Create(
string unityAccessToken,
string projectPath,
string user,
string organizationName,
RepId repId,
long changesetId,
long branchId,
Action afterWorkspaceMigratedAction,
ProgressControlsForMigration progressControls)
{
var instance = CreateInstance<MigrationDialog>();
instance.IsResizable = false;
instance.mUnityAccessToken = unityAccessToken;
instance.mProjectPath = projectPath;
instance.mUser = user;
instance.mOrganizationName = organizationName;
instance.mRepId = repId;
instance.mChangesetId = changesetId;
instance.mBranchId = branchId;
instance.mAfterWorkspaceMigratedAction = afterWorkspaceMigratedAction;
instance.mProgressControls = progressControls;
instance.mEscapeKeyAction = instance.CloseButtonAction;
return instance;
}
bool mIsMigrationCompleted;
ProgressControlsForMigration mProgressControls;
Action mAfterWorkspaceMigratedAction;
long mChangesetId;
long mBranchId;
RepId mRepId;
string mOrganizationName;
string mUser;
string mProjectPath;
string mUnityAccessToken;
WorkspaceInfo mWorkspaceInfo;
static readonly ILog mLog = PlasticApp.GetLogger("MigrationDialog");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7a84120cb1bc4b48a18d18cb745730a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
using System;
using System.IO;
using Codice.Client.Commands;
using Codice.Client.Common;
using Codice.Client.BaseCommands;
using Codice.LogWrapper;
using PlasticGui;
using Codice.Client.BaseCommands.Sync;
namespace Unity.PlasticSCM.Editor.CollabMigration
{
internal class MigrationProgressRender
{
internal static string FixNotificationPath(string wkPath, string notification)
{
if (notification == null)
return string.Empty;
int position = notification.ToLower().IndexOf(wkPath.ToLower());
if (position < 0)
return notification;
return notification.Remove(position, wkPath.Length + 1);
}
internal static string GetProgressString(
CreateWorkspaceFromCollab.Progress status,
BuildProgressSpeedAndRemainingTime.ProgressData progressData,
DateTime now,
double smoothingFactor,
string updateProgressCalculatingMessage,
string updateProgressSingularMessage,
string updateProgressPluralMessage,
string remainingMessage)
{
if (status.CurrentStatus == CreateWorkspaceFromCollab.Progress.Status.Starting)
return updateProgressCalculatingMessage;
progressData.StartTimerIfNotStarted(now);
string updatedSize;
string totalSize;
GetFormattedSizes.ForTransfer(
status.ProcessedSize,
status.TotalSize,
out updatedSize,
out totalSize);
string details = string.Format(
status.TotalFiles == 1 ?
updateProgressSingularMessage :
updateProgressPluralMessage,
updatedSize,
totalSize,
status.ProcessedFiles,
status.TotalFiles,
BuildProgressSpeedAndRemainingTime.ForTransfer(
progressData,
now,
status.TotalSize,
status.ProcessedSize,
smoothingFactor,
remainingMessage));
return details;
}
static ILog mLog = PlasticApp.GetLogger("MigrationProgressRender");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b793dc79f36144740a175a3cba53845d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: