using UnityEngine; using UnityEditor; using System; using System.Collections.Generic; using System.Linq; using System.Text; using Perforce.P4; using log4net; namespace P4Connect { public static class ChangeManager { private static readonly ILog log = LogManager.GetLogger(typeof(ChangeManager)); public static int DEFAULT_CHANGE = -1; static Dictionary _changes = new Dictionary(); static float poll_rate = 3 * 60; static DateTime last_refresh; public static void Initialize() { last_refresh = DateTime.Now; Engine.OnOperationPerformed += OnEngineOperationPerformed; } /// /// This functions gets called when P4Connect does *something* to files /// In this case we refresh the involved change list /// static void OnEngineOperationPerformed(PerforceConnection aConnection, List aFilesAndMetas) { // ToDo: Check the changelist associated to the files DEFAULT_CHANGE for now.... // ToDo: Refresh the involved changelist in prep for a localOpenedFiles() call later RefreshChange(aConnection, DEFAULT_CHANGE); } /// /// Periodic Update method, triggers refreshes, not used /// static void Update() { if (Config.ValidConfiguration) { DateTime now = DateTime.Now; TimeSpan delta = now - last_refresh; if (delta.TotalSeconds > poll_rate) { last_refresh = now; log.Debug("ChangeManager Tick"); RefreshAll(); } } } // Update the list of change lists public static void Refresh() { if (Config.ValidConfiguration) { using (PerforceConnection con = new PerforceConnection()) { RefreshChangeLists(con); } } } // Refresh the files in a specific change lists public static void Refresh(int changeId) { if (Config.ValidConfiguration) { if (_changes.Count == 0 || (!_changes.ContainsKey(changeId))) { RefreshAll(); } using (PerforceConnection con = new PerforceConnection()) { RefreshChange(con, changeId); } } } // Get all changelists and all files in them public static void RefreshAll() { if (Config.ValidConfiguration) { using (PerforceConnection con = new PerforceConnection()) { RefreshChangeLists(con, true); } } } public static IList Changelists { get { if (_changes.Count == 0 ) { RefreshAll(); } return (_changes.Values.ToList()); } } public static Changelist GetChangelist(int id) { if (_changes.ContainsKey(id)) { return (_changes[id]); } return null; } public static string ChangeIdToString(int id) { if (id <= DEFAULT_CHANGE) return "default"; return id.ToString(); } public static IEnumerable LocalOpenedFiles { get { if (!Config.ValidConfiguration) yield break; if (_changes.Count == 0 || (! _changes.ContainsKey(DEFAULT_CHANGE))) { Refresh(); Refresh(DEFAULT_CHANGE); } //log.DebugFormat("Changelists: {0}", _changes.Count); IList files = _changes[DEFAULT_CHANGE].Files; if (files != null && files.Count > 0) { //log.DebugFormat("file: {0}", Logger.ToStringNullSafe(files[0].ClientPath.Path)); for (int i = 0; i < files.Count; ++i) { yield return Utils.ClientPathToLocalPath(files[i].ClientPath.Path); } } } } /// /// Helper method to check if a file is in the depot list /// /// /// /// public static bool Contains(Predicate aMatch) { foreach (FileMetaData fmd in _changes[DEFAULT_CHANGE].Files) { if (aMatch(fmd)) return true; } return false; } // Collect all the Changelists and put them in the _changes dictionary static void RefreshChangeLists(PerforceConnection p4conn, bool all = false) { if (Config.ValidConfiguration) { //log.DebugFormat("RefreshChangeLists {0}", all.ToString()); _changes.Clear(); // Create a placeholder for the default change Changelist dchange = new Changelist() { Description = "Default", OwnerName = Config.Username, ClientId = Config.Workspace }; dchange.initialize(p4conn.P4Connection); _changes.Add(DEFAULT_CHANGE, dchange); if (all) { RefreshChange(p4conn, DEFAULT_CHANGE); } // Now go get the numbered change lists ChangesCmdOptions opts = new ChangesCmdOptions(ChangesCmdFlags.FullDescription, null, 0, ChangeListStatus.Pending, null); IList allChanges = p4conn.P4Depot.GetChangelists(opts, null); if (allChanges != null) { foreach (var change in allChanges) { change.initialize(p4conn.P4Connection); _changes.Add(change.Id, change); if (all) { RefreshChange(p4conn, change.Id); } } } } } // Collect all the files and shelves for a specific changelist static void RefreshChange( PerforceConnection p4conn, int changeId) { if (Config.ValidConfiguration) { //log.DebugFormat("RefreshChange {0}", changeId); if (changeId <= DEFAULT_CHANGE) { RefreshDefaultChange(p4conn); return; } // Get files for the specified changeId _changes[changeId].initialize(p4conn.P4Connection); // Get shelves too P4Command cmd = new P4Command(p4conn.P4Connection, "describe", true, "-S", changeId.ToString()); P4CommandResult results = cmd.Run(); if ((results.Success) && (results.TaggedOutput != null) && (results.TaggedOutput.Count > 0)) { _changes[changeId].FromChangeCmdTaggedOutput(results.TaggedOutput[0], true, string.Empty, false); // FIXME: the time zone is wrong. } } } static void RefreshDefaultChange(PerforceConnection p4conn) { if (Config.ValidConfiguration) { // Use "p4 opened -c default" to get the opened files in the default changelist Options opts = new Options(); opts["-c"] = "default"; opts["-C"] = Config.Workspace; IList allOpenedFiles = p4conn.P4Depot.GetOpenedFiles(null, opts); if (!_changes.ContainsKey(DEFAULT_CHANGE)) { RefreshChangeLists(p4conn, false); // Changelists dictionary needs to be constructed first } //Debug.Log("Resetting Default Change"); _changes[DEFAULT_CHANGE].Files.Clear(); // Clear out old list of files if (allOpenedFiles != null) { foreach (File fd in allOpenedFiles) { FileMetaData fmd = fd; // log.Debug("file: " + Logger.ToStringNullSafe(fmd.ClientPath)); _changes[DEFAULT_CHANGE].Files.Add(fmd); } } else { //log.Debug("allOpenedFiles returned null"); } } } } }