Пример #1
0
    /// <summary>
    /// Locks a set of files in git.
    /// </summary>
    /// <param name="paths"></param>
    /// <returns></returns>
    public bool GitLockFile(string[] paths)
    {
        if (!GitHelper.LFSEnabled)
        {
            return(false);
        }

        var cmdstring = new StringBuilder();

        foreach (var path in paths)
        {
            cmdstring.Append('"' + path + '"');
        }

        /*
         * GitHelper.RunGitCommand("track -- " + cmdstring,
         *  proc =>
         *  {
         *      if (!proc.WaitForExit(5000))
         *      {
         *          return true;
         *      }
         *      return false;
         *  }
         * );*/

        bool hasError = GitHelper.RunGitCommand("lfs lock -- " + cmdstring,
                                                proc =>
        {
            try
            {
                while (!proc.HasExited)
                {
                    if (paths.Length > 1)
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Locking files " + (cmdstring.ToString()) + "...", 0))
                        {
                            proc.Kill();
                            return(true);
                        }
                    }
                    else
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Locking file " + Path.GetFileName(paths[0]) + "...", 0))
                        {
                            proc.Kill();
                            return(true);
                        }
                    }
                    Thread.Sleep(16);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            return(false);
        },
                                                result =>
        {
            Debug.Log("[LFS Lock] " + result);
            if (!result.Contains("Locked"))
            {
                // Failed for some reason and didn't go to std::error, search for updated locks.
                RefreshGitLocks();
            }
            else
            {
                foreach (var path in paths)
                {
                    var locked  = new LockedFile();
                    locked.Path = GitHelper.GitToUnityPath(path);
                    locked.User = GitHelper.Username;
                    LockedFiles.Add(path.Trim(), locked);
                }
            }
        },
                                                error =>
        {
            Debug.Log("Failed to lock " + cmdstring);
            Debug.LogError(error);
            return(true);
        });

        EditorApplication.RepaintProjectWindow();
        UpdateLockedFiles();
        return(!hasError);
    }
Пример #2
0
 public override bool IsFileLocked(string path)
 {
     return(LockedFiles.ContainsKey(path));
 }
Пример #3
0
    public override void Initialize()
    {
        if (!GitHelper.VCSEnabled)
        {
            return;
        }

        if (!FindGitRoot())
        {
            Debug.LogError("[VCS] Unable to find .git folder, git support disabled");
            return;
        }

        Thread m_asyncthread = new Thread(() =>
        {
            while (true)
            {
                try
                {
                    if (!GitHelper.VCSEnabled)
                    {
                        break;
                    }

                    if (inPlayMode)
                    {
                        Thread.Sleep(100);
                        continue;
                    }

                    UpdateModifiedFilesAsync();

                    var newLockFiles = new Dictionary <string, LockedFile>();
                    if (GitHelper.LFSEnabled)
                    {
                        // Update locks
                        GitHelper.RunGitCommand("lfs locks",
                                                proc =>
                        {
                            if (!proc.WaitForExit(5000))
                            {
                                return(true);
                            }
                            return(false);
                        },

                                                result =>
                        {
                            try
                            {
                                var parts = result.Split('\t');
                                var path  = GitHelper.GitToUnityPath(parts[0]);
                                var user  = parts[1];

                                var locked  = new LockedFile();
                                locked.Path = path;
                                locked.User = user;
                                newLockFiles.Add(path.Trim(), locked);
                            }
                            catch (System.Exception ex)
                            {
                                Debug.LogError("[VCS Async] " + ex);
                            }
                        },

                                                error =>
                        {
                            Debug.LogError("[VCS]" + error);
                            return(true);
                        }
                                                );

                        lock (_actionQueueLock)
                        {
                            var cnt        = LockedFiles.Count;
                            string hashStr = "";
                            foreach (var v in LockedFiles)
                            {
                                hashStr += v.Key + ": " + v.Value.User.GetHashCode();
                            }

                            int hash = hashStr.GetHashCode();
                            _toRunOnMainThread.Enqueue(() =>
                            {
                                // Locked files
                                if (cnt == LockedFiles.Count)
                                {
                                    var newHashStr = "";
                                    foreach (var v in LockedFiles)
                                    {
                                        newHashStr += v.Key + ": " + v.Value.User.GetHashCode();
                                    }

                                    int newhash = newHashStr.GetHashCode();

                                    // Let's make sure that the super lazy hashes match
                                    if (newhash == hash)
                                    {
                                        foreach (var v in LockedFiles)
                                        {
                                            if (v.Value.FileLock != null)
                                            {
                                                v.Value.FileLock.Dispose();
                                            }
                                        }

                                        LockedFiles.Clear();
                                        _lockedFiles = newLockFiles;
                                        foreach (var v in LockedFiles)
                                        {
                                            if (v.Value.User != GitHelper.Username && GitHelper.PreventEditsOnRemoteLock)
                                            {
                                                if (File.Exists(v.Value.Path))
                                                {
                                                    try
                                                    {
                                                        v.Value.FileLock = new FileStream(v.Value.Path, FileMode.Open, FileAccess.Read, FileShare.Read);
                                                    }
                                                    catch (System.Exception ex)
                                                    {
                                                        Debug.LogError("Failed to create file lock for " + v.Key + ": " + ex);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                UpdateLockedFiles();
                            });
                        }
                    }
                    Thread.Sleep(10000);
                }
                catch (ThreadAbortException ex)
                {
                    throw ex;
                }
                catch (System.Exception ex)
                {
                    Debug.LogError("[VCS Async] " + ex);
                }
            }
        });

        m_asyncthread.Name = "Git Async Thread";
        m_asyncthread.Start();

        // Preserves locked files for play mode, etc
        AssemblyReloadEvents.beforeAssemblyReload += () =>
        {
            foreach (var v in LockedFiles)
            {
                if (v.Value.FileLock != null)
                {
                    v.Value.FileLock.Dispose();
                }
            }
            m_asyncthread.Abort();
            UpdateLockedFiles();
        };

        UnityEditor.SceneManagement.EditorSceneManager.sceneSaved += (scn) =>
        {
            if (GitHelper.SceneAutoLock)
            {
                if (string.IsNullOrEmpty(scn.path))
                {
                    return;
                }

                if (!IsFileLockedByLocalUser(scn.path))
                {
                    GitLockFile(new string[] { scn.path });
                }
            }
        };

        EditorApplication.playModeStateChanged += (s) =>
        {
            if (s == PlayModeStateChange.ExitingEditMode)
            {
                UpdateLockedFiles();
            }
        };

        EditorApplication.projectWindowItemOnGUI +=
            (string guid, Rect rect) =>
        {
            var path     = AssetDatabase.GUIDToAssetPath(guid);
            var iconRect = rect;
            var oldBack  = GUI.backgroundColor;
            GUI.backgroundColor = new Color(0, 0, 0, 0);

            if (ModifiedPaths.Contains(path))
            {
                GUI.Box(iconRect, VCSHelper.ModifiedItemIcon);
            }

            if (IsFileLockedByLocalUser(path))
            {
                GUI.Box(iconRect, new GUIContent(VCSHelper.LocalLockIcon, "Locked by " + LockedFiles[path].User + " (local user)"));
            }
            else if (IsFileLocked(path))
            {
                GUI.Box(iconRect, new GUIContent(VCSHelper.RemoteLockIcon, "Locked by " + LockedFiles[path].User));
            }


            GUI.backgroundColor = oldBack;
        };

        if (VCSPrefs.HasInitializedKeys && !GitHelper.Configured)
        {
            if (EditorUtility.DisplayDialog("Version Control", "You have not yet set up your GitHub username and you will not be able to lock files.  Would you like to open the configuration window?", "Yes", "No"))
            {
                VCSConfigWindow.OpenWindow();
            }
        }
        else
        {
            LoadLockedFilesFromVCSPrefs();
            RefreshGitLockTypes();
        }
    }
Пример #4
0
    public void RefreshGitLocks()
    {
        if (GitHelper.AutoUpdateSubmodules)
        {
            try
            {
                var startinfo = new ProcessStartInfo();
                startinfo.FileName = "git";
                startinfo.RedirectStandardOutput = true;
                startinfo.RedirectStandardError  = true;
                startinfo.UseShellExecute        = false;
                startinfo.CreateNoWindow         = true;
                startinfo.Arguments = "submodule update --init --recursive";

                var    proc = Process.Start(startinfo);
                string line = "Downloading...";
                while (!proc.HasExited)
                {
                    while (!proc.StandardError.EndOfStream && (line = proc.StandardError.ReadLine()) != null)
                    {
                        Debug.LogError(line);
                    }

                    while (!proc.StandardOutput.EndOfStream && (line = proc.StandardOutput.ReadLine()) != null)
                    {
                        Debug.Log(line);
                    }

                    EditorUtility.DisplayProgressBar("Downloading submodules...", line, 0);
                    Thread.Sleep(30);
                }
                Debug.Log("Submodules completed");
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            AssetDatabase.Refresh();
        }

        GitHelper.RunGitCommand("lfs",
                                proc =>
        {
            // If it doesn't work in 10 seconds there's something wrong
            proc.WaitForExit(10000);
            return(false);
        },
                                result =>
        {
        },
                                error =>
        {
            if (error.Contains("'lfs' is "))
            {
                EditorUtility.DisplayDialog("Version Control", "Error: Git LFS is not installed.  File locking will not work.  Please install Git LFS.", "Okay");
                GitHelper.LFSEnabled = false;
            }
            return(true);
        });

        if (!GitHelper.LFSEnabled)
        {
            return;
        }

        foreach (var v in LockedFiles)
        {
            if (v.Value.FileLock != null)
            {
                v.Value.FileLock.Dispose();
            }
        }

        LockedFiles.Clear();

        if (GitHelper.LFSEnabled)
        {
            GitHelper.RunGitCommand("lfs locks",
                                    proc =>
            {
                try
                {
                    while (!proc.HasExited)
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Refreshing LFS locks...", 0))
                        {
                            proc.Kill();
                            return(true);
                        }
                        Thread.Sleep(16);
                    }
                }
                finally
                {
                    EditorUtility.ClearProgressBar();
                }
                return(false);
            },

                                    result =>
            {
                var parts = result.Split('\t');
                var path  = GitHelper.GitToUnityPath(parts[0]);
                Debug.Log("Locking path " + path + "(from " + parts[0] + ")");
                var user = parts[1];

                var locked  = new LockedFile();
                locked.Path = path;
                locked.User = user;

                if (user != GitHelper.Username && GitHelper.PreventEditsOnRemoteLock)
                {
                    if (File.Exists(path))
                    {
                        try
                        {
                            locked.FileLock = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                        }
                        catch (System.Exception ex)
                        {
                            Debug.LogError("Failed to create file lock for " + path + ": " + ex);
                        }
                    }
                }
                LockedFiles.Add(path.Trim(), locked);
            },

                                    error =>
            {
                Debug.LogError(error);
                return(true);
            }
                                    );
        }

        UpdateLockedFiles();
        EditorApplication.RepaintProjectWindow();
    }
Пример #5
0
    public bool GitUnlockFile(string[] paths)
    {
        if (!GitHelper.LFSEnabled)
        {
            return(false);
        }

        var cmdstring = new StringBuilder();

        foreach (var path in paths)
        {
            cmdstring.Append('"' + path + '"');
        }

        bool hasError = GitHelper.RunGitCommand("lfs unlock -- " + cmdstring.ToString(),
                                                proc =>
        {
            try
            {
                while (!proc.HasExited)
                {
                    if (paths.Length > 1)
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Unlocking files " + (cmdstring.ToString()) + "...", 0))
                        {
                            proc.Kill();
                            return(true);
                        }
                    }
                    else
                    {
                        if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Unlocking file " + Path.GetFileName(paths[0]) + "...", 0))
                        {
                            proc.Kill();
                            return(true);
                        }
                    }
                    Thread.Sleep(16);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            return(false);
        },
                                                result =>
        {
            Debug.Log("[LFS Unlock] " + result);
            if (!result.Contains("Unlocked"))
            {
                // Failed for some reason and didn't go to std::error, search for updated locks.
                RefreshGitLocks();
            }
            else
            {
                foreach (var path in paths)
                {
                    LockedFiles.Remove(path.Trim());
                }
            }
        },
                                                error =>
        {
            EditorUtility.DisplayDialog("Version Control", "Error while unlocking file: " + error, "Okay");

            // If it's erroring because it's already locked with local changes, ignore.
            // Otherwise, someone else locked the file before we did so everything is confused
            if (!error.Contains("uncommitted"))
            {
                RefreshGitLocks();
            }

            return(true);
        }
                                                );

        EditorApplication.RepaintProjectWindow();
        UpdateLockedFiles();
        return(!hasError);
    }
Пример #6
0
    public void RefreshGitLocks()
    {
        foreach (var v in LockedFiles)
        {
            if (v.Value.FileLock != null)
            {
                v.Value.FileLock.Close();
            }
        }

        LockedFiles.Clear();

        GitHelper.RunGitCommand("lfs locks",
                                proc =>
        {
            try
            {
                while (!proc.HasExited)
                {
                    if (EditorUtility.DisplayCancelableProgressBar("Version Control", "Refreshing LFS locks...", 0))
                    {
                        proc.Kill();
                        return(true);
                    }
                    Thread.Sleep(16);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            return(false);
        },

                                result =>
        {
            var parts = result.Split('\t');
            var path  = parts[0];
            var user  = parts[1];

            var locked  = new LockedFile();
            locked.Path = path;
            locked.User = user;
            if (user != GitHelper.Username && GitHelper.PreventEditsOnRemoteLock)
            {
                try
                {
                    locked.FileLock = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
                }
                catch (System.Exception ex)
                {
                    Debug.LogError("Failed to create file lock for " + path + ": " + ex);
                }
            }
            LockedFiles.Add(path.Trim(), locked);
        },

                                error =>
        {
            Debug.LogError(error);
            return(true);
        }
                                );

        UpdateLockedFiles();
        EditorApplication.RepaintProjectWindow();
    }