public override void Add(IEnumerable <string> assetPaths, bool includeMeta, bool wait = false)
        {
            if (!assetPaths.Any())
            {
                return;
            }

            foreach (var path in assetPaths)
            {
                if (!WiseSVNIntegration.CheckAndAddParentFolderIfNeeded(path, true))
                {
                    return;
                }
            }

            // Don't give versioned metas, as tortoiseSVN doesn't like it.
            var metas = assetPaths
                        .Select(path => path + ".meta")
                        .Where(path => WiseSVNIntegration.GetStatus(path).Status == VCFileStatus.Unversioned)
            ;

            var pathsArg = AssetPathsToContextPaths(includeMeta ? assetPaths.Concat(metas) : assetPaths, false);

            var result = ShellUtils.ExecuteCommand(ClientCommand, $"/command:add /path:\"{pathsArg}\"", wait);

            if (!string.IsNullOrEmpty(result.Error))
            {
                Debug.LogError($"SVN Error: {result.Error}");
            }
        }
Exemplo n.º 2
0
        public void ForceLock(IEnumerable <SVNStatusData> lockedByOtherEntries)
        {
            var shouldLog   = SVNPreferencesManager.Instance.PersonalPrefs.TraceLogs.HasFlag(SVNTraceLogs.SVNOperations);
            var lockMessage = SVNPreferencesManager.Instance.ProjectPrefs.AutoLockMessage;

            var targetsFileToUse = FileUtil.GetUniqueTempPathInProject();               // Not thread safe - call in main thread only.

            EnqueueOperation(op => WiseSVNIntegration.LockFiles(lockedByOtherEntries.Select(sd => sd.Path), true, lockMessage, "", targetsFileToUse))
            .Completed += (op) => {
                if (op.Result != LockOperationResult.Success)
                {
                    Debug.LogError($"Auto-locking by force failed with result {op.Result} for assets:\n{string.Join("\n", lockedByOtherEntries.Select(sd => sd.Path))}.");
                    EditorUtility.DisplayDialog("SVN Auto-Locking", "Stealing lock failed. Check the logs for more info.", "I will!");
                }
                else if (shouldLog)
                {
                    Debug.Log($"Auto-locked assets by force:\n{string.Join("\n", lockedByOtherEntries.Select(sd => sd.Path))}");
                }
            };

            if (m_PendingOperations.Count > 0 && m_HasPendingOperations == false)
            {
                m_HasPendingOperations = true;
                m_PendingOperations.Peek().Start();
            }
        }
        private static bool DiffAsset(string assetPath)
        {
            var statusData = WiseSVNIntegration.GetStatus(assetPath);

            var isModified = statusData.Status != VCFileStatus.Normal &&
                             statusData.Status != VCFileStatus.Unversioned &&
                             statusData.Status != VCFileStatus.Conflicted
            ;

            isModified |= statusData.PropertiesStatus == VCPropertiesStatus.Modified;

            if (isModified)
            {
                m_Integration?.DiffChanges(assetPath, false);
                return(true);
            }

            if (statusData.Status == VCFileStatus.Conflicted || statusData.PropertiesStatus == VCPropertiesStatus.Conflicted)
            {
                m_Integration?.Resolve(assetPath, false);
                return(true);
            }

            return(false);
        }
Exemplo n.º 4
0
        public override void Initialize(bool freshlyCreated)
        {
            var lastModifiedDate = File.Exists(PROJECT_PREFERENCES_PATH)
                                ? File.GetLastWriteTime(PROJECT_PREFERENCES_PATH).Ticks
                                : 0
            ;

            if (freshlyCreated || m_ProjectPrefsLastModifiedTime != lastModifiedDate)
            {
                LoadPreferences();
            }

            if (freshlyCreated || m_RetryTextures)
            {
                LoadTextures();

                m_RetryTextures = false;

                // If WiseSVN was just added to the project, Unity won't manage to load the textures the first time. Try again next frame.
                if (FileStatusIcons[(int)VCFileStatus.Added].image == null)
                {
                    // We're using a flag as assembly reload may happen and update callback will be lost.
                    m_RetryTextures = true;

                    EditorApplication.CallbackFunction reloadTextures = null;
                    reloadTextures = () => {
                        LoadTextures();
                        m_RetryTextures           = false;
                        EditorApplication.update -= reloadTextures;
                    };

                    EditorApplication.update += reloadTextures;
                }

                Debug.Log($"Loaded WiseSVN Preferences. WiseSVN is turned {(PersonalPrefs.EnableCoreIntegration ? "on" : "off")}.");

                if (PersonalPrefs.EnableCoreIntegration)
                {
                    var svnError = WiseSVNIntegration.CheckForSVNErrors();

                    // svn: warning: W155007: '...' is not a working copy!
                    // This can be returned when project is not a valid svn checkout. (Probably)
                    if (svnError.Contains("W155007"))
                    {
                        Debug.LogError("This project is NOT under version control (not a proper SVN checkout).");

                        // System.ComponentModel.Win32Exception (0x80004005): ApplicationName='...', CommandLine='...', Native error= The system cannot find the file specified.
                        // Could not find the command executable. The user hasn't installed their CLI (Command Line Interface) so we're missing an "svn.exe" in the PATH environment.
                        // This is allowed only if there isn't ProjectPreference specified CLI path.
                    }
                    else if (svnError.Contains("0x80004005"))
                    {
                        Debug.LogError("SVN CLI (Command Line Interface) not found. You need to install it in order for the SVN integration to work properly.");

                        // Any other error.
                    }
                    else if (!string.IsNullOrEmpty(svnError))
                    {
                        Debug.LogError($"SVN command line interface returned this error:\n{svnError}");
                    }
                }
            }

            SVNContextMenusManager.SetupContextType(PersonalPrefs.ContextMenusClient);
        }
Exemplo n.º 5
0
        private void OnGUI()
        {
            var outputStyle = new GUIStyle(EditorStyles.textArea);

            outputStyle.wordWrap = false;

            var textSize = outputStyle.CalcSize(new GUIContent(m_CombinedOutput));

            m_OutputScroll = EditorGUILayout.BeginScrollView(m_OutputScroll);
            EditorGUILayout.LabelField(m_CombinedOutput, outputStyle, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true), GUILayout.MinWidth(textSize.x), GUILayout.MinHeight(textSize.y));
            EditorGUILayout.EndScrollView();

            EditorGUILayout.BeginHorizontal();
            {
                bool isWorking = m_SVNOperation == null || m_SVNOperation.HasFinished;

                EditorGUI.BeginDisabledGroup(isWorking);

                if (GUILayout.Button("Abort"))
                {
                    m_SVNOperation.Abort(false);
                    m_CombinedOutput += "Aborting...\n";
                    m_StateLabel      = "Aborting...";
                }

                if (GUILayout.Button("Kill"))
                {
                    m_SVNOperation.Abort(true);
                    m_CombinedOutput += "Killing...\n";
                    m_StateLabel      = "Killing...";
                }

                EditorGUI.EndDisabledGroup();

                GUILayout.FlexibleSpace();

                EditorGUILayout.LabelField(m_StateLabel);

                GUILayout.FlexibleSpace();

                if (GUILayout.Button("Clear"))
                {
                    m_CombinedOutput = "";
                }

                EditorGUI.BeginDisabledGroup(!isWorking);

                if (GUILayout.Button("Get Status"))
                {
                    m_SVNOperation = WiseSVNIntegration.GetStatusesAsync(".", recursive: true, offline: false);

                    m_SVNOperation.AnyOutput += (line) => { m_CombinedOutput += line + "\n"; };

                    m_SVNOperation.Completed += (op) => {
                        m_StateLabel      = op.AbortRequested ? "Aborted!" : "Completed!";
                        m_CombinedOutput += m_StateLabel + "\n\n";
                        m_SVNOperation    = null;
                    };

                    m_StateLabel = "Working...";
                }

                EditorGUI.EndDisabledGroup();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
            {
                GUILayout.FlexibleSpace();

                GUILayout.Label("External SVN Client:");

                if (GUILayout.Button("Commit", GUILayout.ExpandWidth(false)))
                {
                    SVNContextMenusManager.CommitAll();
                }

                if (GUILayout.Button("Update", GUILayout.ExpandWidth(false)))
                {
                    SVNContextMenusManager.UpdateAll();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
        }
Exemplo n.º 6
0
        private void OnStatusDatabaseChanged()
        {
            if (!IsActive)
            {
                return;
            }

            var statusDatabaseData = SVNStatusesDatabase.Instance.GetAllKnownStatusData(false, true, true)
                                     .Where(sd => !Directory.Exists(sd.Path))
                                     .ToList()
            ;

            var newEntries = new List <SVNStatusData>();

            foreach (var statusData in statusDatabaseData)
            {
                if (AddOrUpdateKnowsStatusData(statusData))
                {
                    newEntries.Add(statusData);
                }
            }

            m_KnownData.RemoveAll(known => !statusDatabaseData.Any(unknown => known.Path == unknown.Path));

            var shouldLock           = new List <SVNStatusData>(newEntries.Count);
            var lockedByOtherEntries = new List <SVNStatusData>(newEntries.Count);
            var shouldUnlock         = new List <SVNStatusData>();

            // Check for new assets to lock.
            foreach (var statusData in newEntries)
            {
                // NOTE: Deleted status never occurs as it is not provided by the SVNStatusesDatabase. :(
                if (statusData.Status != VCFileStatus.Modified && statusData.Status != VCFileStatus.Deleted && statusData.Status != VCFileStatus.Replaced)
                {
                    continue;
                }

                if (statusData.LockStatus == VCLockStatus.LockedHere)
                {
                    continue;
                }

                var  assetPath = statusData.Path;
                bool isMeta    = false;
                if (statusData.Path.EndsWith(".meta", StringComparison.OrdinalIgnoreCase))
                {
                    assetPath = statusData.Path.Substring(0, statusData.Path.LastIndexOf(".meta"));
                    isMeta    = true;
                }
                assetPath = assetPath.Replace("\\", "/");

                var autoLockingParam = m_ProjectPrefs.AutoLockingParameters
                                       .FirstOrDefault(al => assetPath.StartsWith(al.TargetFolder, StringComparison.OrdinalIgnoreCase));

                if (string.IsNullOrEmpty(autoLockingParam.TargetFolder))
                {
                    continue;
                }

                if (isMeta && !autoLockingParam.IncludeTargetMetas)
                {
                    continue;
                }

                if (SVNPreferencesManager.ShouldExclude(autoLockingParam.Exclude, assetPath))
                {
                    continue;
                }

                bool matched = IsAssetOfType(assetPath, autoLockingParam.TargetTypes, statusData.Status == VCFileStatus.Deleted);
                if (!matched && !autoLockingParam.TargetTypes.HasFlag(AssetType.OtherTypes))
                {
                    continue;
                }

                if (statusData.LockStatus == VCLockStatus.NoLock)
                {
                    shouldLock.Add(statusData);
                    continue;
                }

                lockedByOtherEntries.Add(statusData);
            }

            // Check for old assets to unlock.
            foreach (var statusData in statusDatabaseData)
            {
                if (statusData.Status != VCFileStatus.Normal)
                {
                    continue;
                }

                var assetPath = statusData.Path;
                if (statusData.Path.EndsWith(".meta", StringComparison.OrdinalIgnoreCase))
                {
                    assetPath = statusData.Path.Substring(0, statusData.Path.LastIndexOf(".meta"));
                }
                assetPath = assetPath.Replace("\\", "/");

                var autoLockingParam = m_ProjectPrefs.AutoLockingParameters
                                       .FirstOrDefault(al => assetPath.StartsWith(al.TargetFolder, StringComparison.OrdinalIgnoreCase));

                if (string.IsNullOrEmpty(autoLockingParam.TargetFolder))
                {
                    continue;
                }

                if (SVNPreferencesManager.ShouldExclude(autoLockingParam.Exclude, assetPath))
                {
                    continue;
                }

                bool matched = IsAssetOfType(assetPath, autoLockingParam.TargetTypes, false);
                if (!matched && !autoLockingParam.TargetTypes.HasFlag(AssetType.OtherTypes))
                {
                    continue;
                }

                if (statusData.LockStatus != VCLockStatus.NoLock && statusData.LockStatus != VCLockStatus.LockedOther)
                {
                    shouldUnlock.Add(statusData);
                }
            }


            var shouldLog   = SVNPreferencesManager.Instance.PersonalPrefs.TraceLogs.HasFlag(SVNTraceLogs.SVNOperations);
            var lockMessage = SVNPreferencesManager.Instance.ProjectPrefs.AutoLockMessage;

            if (shouldLock.Count > 0)
            {
                var targetsFileToUse = FileUtil.GetUniqueTempPathInProject();                   // Not thread safe - call in main thread only.
                EnqueueOperation(op => WiseSVNIntegration.LockFiles(shouldLock.Select(sd => sd.Path), false, lockMessage, "", targetsFileToUse))
                .Completed += (op) => {
                    if (op.Result != LockOperationResult.Success)
                    {
                        Debug.LogError($"Auto-locking failed with result {op.Result} for assets:\n{string.Join("\n", shouldLock.Select(sd => sd.Path))}");
                    }
                    else if (shouldLog)
                    {
                        Debug.Log($"Auto-locked assets:\n{string.Join("\n", shouldLock.Select(sd => sd.Path))}");
                    }
                };
            }

            if (shouldUnlock.Count > 0)
            {
                var targetsFileToUse = FileUtil.GetUniqueTempPathInProject();                   // Not thread safe - call in main thread only.
                EnqueueOperation(op => WiseSVNIntegration.UnlockFiles(shouldUnlock.Select(sd => sd.Path), false, targetsFileToUse))
                .Completed += (op) => {
                    // If lock was stolen or broken, there is no good way to release it without causing error.
                    // In that case the lock will be cleared from the local cache, so ignore the error.
                    if (op.Result != LockOperationResult.Success && op.Result != LockOperationResult.LockedByOther)
                    {
                        Debug.LogError($"Auto-unlocking failed with result {op.Result} for assets:\n{string.Join("\n", shouldUnlock.Select(sd => sd.Path))}");
                    }
                    else if (shouldLog)
                    {
                        Debug.Log($"Auto-unlocked assets:\n{string.Join("\n", shouldUnlock.Select(sd => sd.Path))}");
                    }
                };
            }

            if (lockedByOtherEntries.Count > 0)
            {
                SVNAutoLockingForceWindow.PromptForceLock(lockedByOtherEntries);
            }

            if (m_PendingOperations.Count > 0 && m_HasPendingOperations == false)
            {
                m_HasPendingOperations = true;
                m_PendingOperations.Peek().Start();
            }
        }
Exemplo n.º 7
0
        private void GatherProjectsIn(BranchScanParameters scanParams, List <BranchProject> results)
        {
            var listEntries       = new List <string>();
            var normalizedEntries = new List <string>();

            HashSet <string> branchSignatureEntries = new HashSet <string>(scanParams.BranchSignatureRootEntries);

            var lastBranch = new BranchProject()
            {
                BranchName         = "Unknown",
                BranchURL          = scanParams.EntryPointURL,
                BranchRelativePath = string.Empty,
                UnityProjectURL    = string.Empty,
            };

            Queue <string> urls = new Queue <string>();

            urls.Enqueue(scanParams.EntryPointURL);

            while (urls.Count > 0)
            {
                var url = urls.Dequeue();

                LastProcessedEntry = url.Length == scanParams.EntryPointURL.Length
                                        ? scanParams.EntryPointURL
                                        : url.Remove(0, scanParams.EntryPointURL.Length + 1);

                listEntries.Clear();
                var opResult = WiseSVNIntegration.ListURL(url, false, listEntries);

                if (opResult != ListOperationResult.Success)
                {
                    if (opResult == ListOperationResult.NotFound)
                    {
                        Debug.LogError($"{GetType().Name} failed to find url: \"{url}\".");
                    }

                    m_LastError = opResult;
                    results.Clear();
                    return;
                }

                // Folders have '/' at the end but the user shouldn't define them this way.
                normalizedEntries.Clear();
                normalizedEntries.Capacity = Mathf.Max(listEntries.Count, normalizedEntries.Capacity);
                normalizedEntries.AddRange(listEntries.Select(e => e.TrimEnd('/')));

                // Is this a branch?
                if (branchSignatureEntries.IsSubsetOf(normalizedEntries))
                {
                    lastBranch.BranchName               = Path.GetFileName(url);
                    lastBranch.BranchURL                = url;
                    lastBranch.BranchRelativePath       = url.Remove(0, scanParams.EntryPointURL.Length + 1);
                    lastBranch.UnityProjectRelativePath = null;
                    lastBranch.UnityProjectURL          = null;
                }

                // This is a Unity project folder.
                if (m_UnityProjectEntries.IsSubsetOf(normalizedEntries))
                {
                    if (!string.IsNullOrEmpty(lastBranch.UnityProjectURL))
                    {
                        // TODO: if BranchURL == UnityURL => Shouldn't be a problem.
                        //		 if BranchURL != UnityRL => take the Unity folder name from the Working Copy (or find its original name in the repository branch). Accept only that name.
                        Debug.LogError($"Multiple Unity projects found in the branch \"{lastBranch.BranchURL}\". This is still not supported.\n{lastBranch.UnityProjectURL}\n{url}");
                    }

                    lastBranch.UnityProjectURL          = url;
                    lastBranch.UnityProjectRelativePath = url.Remove(0, scanParams.EntryPointURL.Length + 1);
                    results.Add(lastBranch);

                    // No need to dig in the Unity project folder.
                    continue;
                }

                for (int i = 0; i < normalizedEntries.Count; ++i)
                {
                    // Only interested in folders.
                    if (listEntries[i].LastOrDefault() != '/')
                    {
                        continue;
                    }

                    var folderName = normalizedEntries[i];

                    if (scanParams.ExcludesFolderNames.Contains(folderName))
                    {
                        continue;
                    }

                    urls.Enqueue(url + "/" + folderName);
                }
            }
        }
        private static void GatherConflicts(object param)
        {
            var jobData = (ConflictsScanJobData)param;
            var results = jobData.Reults;

            var logParams = new LogParams()
            {
                FetchAffectedPaths  = true,
                FetchCommitMessages = false,
                StopOnCopy          = true,
                Limit = 10,
            };

            const string svnDateFormat = "yyyy-MM-dd";

            switch (jobData.LimitType)
            {
            case ConflictsScanLimitType.Days:
                logParams.RangeStart = "{" + System.DateTime.Now.AddDays(-1 * jobData.LimitParam).ToString(svnDateFormat) + "}";
                logParams.RangeEnd   = "HEAD";
                break;

            case ConflictsScanLimitType.Weeks:
                logParams.RangeStart = "{" + System.DateTime.Now.AddDays(-1 * 7 * jobData.LimitParam).ToString(svnDateFormat) + "}";
                logParams.RangeEnd   = "HEAD";
                break;

            case ConflictsScanLimitType.Months:
                logParams.RangeStart = "{" + System.DateTime.Now.AddMonths(-1 * jobData.LimitParam).ToString(svnDateFormat) + "}";
                logParams.RangeEnd   = "HEAD";
                break;

            case ConflictsScanLimitType.Revisions:
                // Revisions are calculated per branch. Do nothing here.
                break;

            case ConflictsScanLimitType.Unlimited:
                logParams.RangeStart = "";
                break;

            default:
                Debug.LogError($"Unsupported ConflictsScanLimitType {jobData.LimitType} with param {jobData.LimitParam}");
                break;
            }

            List <LogEntry> logEntries = new List <LogEntry>();

            for (int i = 0; i < results.Length; ++i)
            {
                var result = results[i];

                logEntries.Clear();

                var targetURL         = result.UnityURL + "/" + jobData.TargetAssetPath;
                var targetRelativeURL = WiseSVNIntegration.AssetPathToRelativeURL(targetURL);

                // Either it doesn't exist in this branch or it was moved / deleted. Can't know for sure without some deep digging.
                if (string.IsNullOrEmpty(targetRelativeURL))
                {
                    result.State = ConflictState.Missing;
                    results[i]   = result;
                    continue;
                }

                if (jobData.LimitType == ConflictsScanLimitType.Revisions)
                {
                    var lastChangedRevision = WiseSVNIntegration.LastChangedRevision(targetURL);
                    if (lastChangedRevision < 0)
                    {
                        // Probably doesn't exist in this branch.
                        logParams.RangeStart = "";
                        logParams.RangeEnd   = "";
                    }
                    else
                    {
                        logParams.RangeStart = (lastChangedRevision - jobData.LimitParam).ToString();
                        logParams.RangeEnd   = lastChangedRevision.ToString();
                    }
                }

                var opResult = WiseSVNIntegration.Log(targetURL, logParams, logEntries, 60000 * 5);

                // Either it doesn't exist in this branch or it was moved / deleted. Can't know for sure without some deep digging.
                if (opResult == LogOperationResult.NotFound)
                {
                    result.State = ConflictState.Missing;
                    results[i]   = result;
                    continue;
                }

                if (opResult != LogOperationResult.Success)
                {
                    result.State = ConflictState.Error;
                    results[i]   = result;
                    continue;
                }

                result.State = ConflictState.Normal;

                foreach (var logEntry in logEntries)
                {
                    var logPath = logEntry.AffectedPaths.FirstOrDefault(ap => ap.Path.StartsWith(targetRelativeURL));

                    // If not found in the affected paths -> this is the log entry of the branch copy.
                    if (string.IsNullOrEmpty(logPath.Path))
                    {
                        continue;
                    }

                    result.State = ConflictState.Conflicted;

                    // Don't consider folder children for "Added" and "Deleted". Folders are just modified by their children.
                    if (logPath.Path != targetRelativeURL)
                    {
                        continue;
                    }

                    if (logPath.Added || logPath.Replaced)
                    {
                        result.State = ConflictState.Added;
                        break;
                    }

                    if (logPath.Deleted)
                    {
                        result.State = ConflictState.Missing;
                        break;
                    }
                }


                results[i] = result;
            }
        }
        private void DrawBranchesList()
        {
            using (var scrollView = new EditorGUILayout.ScrollViewScope(m_BranchesScroll)) {
                m_BranchesScroll = scrollView.scrollPosition;

                // For hover effects to work.
                if (Event.current.type == EventType.MouseMove)
                {
                    Repaint();
                }

                // TODO: Sort list by folder depths: compare by lastIndexOf('/'). If equal, by string.

                foreach (var branchProject in Database.BranchProjects)
                {
                    if (!string.IsNullOrEmpty(m_BranchFilter) && branchProject.BranchName.IndexOf(m_BranchFilter, System.StringComparison.OrdinalIgnoreCase) == -1)
                    {
                        continue;
                    }

                    // Apply setting only in Scanned mode since the thread will still be working otherwise and
                    // cause inconsistent GUILayout structure.
                    if (m_ConflictsScanState == ConflictsScanState.Scanned && !m_ConflictsShowNormal)
                    {
                        var conflictResult = m_ConflictsScanResults.First(r => r.UnityURL == branchProject.UnityProjectURL);
                        if (conflictResult.State == ConflictState.Normal)
                        {
                            continue;
                        }
                    }

                    using (new EditorGUILayout.HorizontalScope(/*BranchRowStyle*/)) {
                        float buttonSize   = 24f;
                        bool  repoBrowser  = GUILayout.Button(RepoBrowserContent, MiniIconButtonlessStyle, GUILayout.Height(buttonSize), GUILayout.Width(buttonSize));
                        bool  showLog      = GUILayout.Button(SelectShowLogContent(branchProject), MiniIconButtonlessStyle, GUILayout.Height(buttonSize), GUILayout.Width(buttonSize));
                        bool  switchBranch = GUILayout.Button(SwitchBranchContent, MiniIconButtonlessStyle, GUILayout.Height(buttonSize), GUILayout.Width(buttonSize));

                        bool branchSelected = GUILayout.Button(new GUIContent(branchProject.BranchRelativePath, branchProject.BranchURL), BranchLabelStyle);

                        if (repoBrowser)
                        {
                            SVNContextMenusManager.RepoBrowser(branchProject.UnityProjectURL + "/" + AssetDatabase.GetAssetPath(m_TargetAsset));
                        }

                        if (showLog)
                        {
                            SVNContextMenusManager.ShowLog(branchProject.UnityProjectURL + "/" + AssetDatabase.GetAssetPath(m_TargetAsset));
                        }

                        if (switchBranch)
                        {
                            bool confirm = EditorUtility.DisplayDialog("Switch Operation",
                                                                       "Unity needs to be closed while switching. Do you want to close it?\n\n" +
                                                                       "Reason: if Unity starts crunching assets while SVN is downloading files, the Library may get corrupted.",
                                                                       "Yes!", "No"
                                                                       );
                            if (confirm && UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                            {
                                var localPath = WiseSVNIntegration.WorkingCopyRootPath();
                                var targetUrl = branchProject.BranchURL;

                                if (branchProject.BranchURL != branchProject.UnityProjectURL)
                                {
                                    bool useBranchRoot = EditorUtility.DisplayDialog("Switch what?",
                                                                                     "What do you want to switch?\n" +
                                                                                     "- Working copy root (the whole checkout)\n" +
                                                                                     "- Unity project folder",
                                                                                     "Working copy root", "Unity project");
                                    if (!useBranchRoot)
                                    {
                                        localPath = WiseSVNIntegration.ProjectRoot;
                                        targetUrl = branchProject.UnityProjectURL;
                                    }
                                }

                                SVNContextMenusManager.Switch(localPath, targetUrl);
                                EditorApplication.Exit(0);
                            }
                        }

                        if (branchSelected)
                        {
                            var menu = new GenericMenu();

                            var prevValue = BranchContextMenu.CopyBranchName;
                            foreach (var value in System.Enum.GetValues(typeof(BranchContextMenu)).OfType <BranchContextMenu>())
                            {
                                if ((int)value / 10 != (int)prevValue / 10)
                                {
                                    menu.AddSeparator("");
                                }

                                menu.AddItem(new GUIContent(ObjectNames.NicifyVariableName(value.ToString())), false, OnSelectBranchOption, new KeyValuePair <BranchContextMenu, BranchProject>(value, branchProject));
                                prevValue = value;
                            }

                            menu.ShowAsContext();
                        }
                    }

                    var rect = EditorGUILayout.GetControlRect(GUILayout.ExpandWidth(true), GUILayout.Height(1f));
                    EditorGUI.DrawRect(rect, Color.black);
                }
            }
        }
Exemplo n.º 10
0
        public override void Initialize(bool freshlyCreated)
        {
            var lastModifiedDate = File.Exists(PROJECT_PREFERENCES_PATH)
                                ? File.GetLastWriteTime(PROJECT_PREFERENCES_PATH).Ticks
                                : 0
            ;

            if (freshlyCreated || m_ProjectPrefsLastModifiedTime != lastModifiedDate)
            {
                LoadPreferences();
            }

            if (freshlyCreated || m_RetryTextures)
            {
                LoadTextures();

                m_RetryTextures = false;

                // If WiseSVN was just added to the project, Unity won't manage to load the textures the first time. Try again next frame.
                if (FileStatusIcons[(int)VCFileStatus.Modified].image == null)
                {
                    // We're using a flag as assembly reload may happen and update callback will be lost.
                    m_RetryTextures = true;

                    EditorApplication.CallbackFunction reloadTextures = null;
                    reloadTextures = () => {
                        LoadTextures();
                        m_RetryTextures           = false;
                        EditorApplication.update -= reloadTextures;

                        if (FileStatusIcons[(int)VCFileStatus.Modified].image == null)
                        {
                            Debug.LogWarning("SVN overlay icons are missing.");
                        }
                    };

                    EditorApplication.update += reloadTextures;
                }

                Debug.Log($"Loaded WiseSVN Preferences. WiseSVN is turned {(PersonalPrefs.EnableCoreIntegration ? "on" : "off")}.");

                if (PersonalPrefs.EnableCoreIntegration)
                {
                    var svnError = "";
                    try {
                        svnError = WiseSVNIntegration.CheckForSVNErrors();
                    } catch (Exception ex) {
                        PersonalPrefs.EnableCoreIntegration = false;

                        Debug.LogError($"Calling SVN CLI (Command Line Interface) caused fatal error!\nDisabling WiseSVN integration. Please fix the error and restart Unity.\n{ex}\n\n");
#if UNITY_EDITOR_OSX
                        if (ex is IOException)
                        {
                            Debug.LogError($"If you installed SVN via Brew or similar, you may need to add \"/usr/local/bin\" (or wherever svn binaries can be found) to your PATH environment variable. Example:\nsudo launchctl config user path /usr/local/bin\nAlternatively, you may add relative SVN CLI path in your WiseSVN preferences (\"Assets/SVN/SVN Preferences -> Project\")\n");
                        }
#endif
                    }

                    // svn: warning: W155007: '...' is not a working copy!
                    // This can be returned when project is not a valid svn checkout. (Probably)
                    if (svnError.Contains("W155007"))
                    {
                        Debug.LogError("This project is NOT under version control (not a proper SVN checkout).");

                        // System.ComponentModel.Win32Exception (0x80004005): ApplicationName='...', CommandLine='...', Native error= The system cannot find the file specified.
                        // Could not find the command executable. The user hasn't installed their CLI (Command Line Interface) so we're missing an "svn.exe" in the PATH environment.
                        // This is allowed only if there isn't ProjectPreference specified CLI path.
                    }
                    else if (svnError.Contains("0x80004005"))
                    {
                        Debug.LogError("SVN CLI (Command Line Interface) not found. You need to install it in order for the SVN integration to work properly.");

                        // Any other error.
                    }
                    else if (!string.IsNullOrEmpty(svnError))
                    {
                        Debug.LogError($"SVN command line interface returned this error:\n{svnError}");
                    }
                }
            }

            SVNContextMenusManager.SetupContextType(PersonalPrefs.ContextMenusClient);
        }