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<int, Changelist> _changes = new Dictionary<int, Changelist>(); static float poll_rate = 3 * 60; static DateTime last_refresh; public static void Initialize() { last_refresh = DateTime.Now; Engine.OnOperationPerformed += OnEngineOperationPerformed; } /// <summary> /// This functions gets called when P4Connect does *something* to files /// In this case we refresh the involved change list /// </summary> static void OnEngineOperationPerformed(PerforceConnection aConnection, List<FileAndMeta> 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); } /// <summary> /// Periodic Update method, triggers refreshes, not used /// </summary> 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<Changelist> 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 List<string> LocalOpenedFiles { get { List<string> retList = new List<string>(); // If no changes have been found, look for some if (_changes.Count == 0 || (!_changes.ContainsKey(DEFAULT_CHANGE))) { Refresh(); Refresh(DEFAULT_CHANGE); } // The Files array should be instantiated now foreach (var md in _changes[DEFAULT_CHANGE].Files) { if (md == null) log.DebugFormat("Null element in Files"); else retList.Add(Utils.LocalPathToAssetPath(md.LocalPath.Path)); } // log.DebugFormat("LocalOpened {0}", Logger.StringArrayToString(retList.ToArray())); return retList; } } /// <summary> /// Helper method to check if a file is in the depot list /// </summary> /// <param name="arOpenedFiles"></param> /// <param name="match"></param> /// <returns></returns> public static bool Contains(Predicate<FileMetaData> 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<Changelist> 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. } // Verify that all the files returned are rooted in this project var filesToRemove = _changes[changeId].Files.Where(entry => entry.ClientPath != null && entry.ClientPath.Path != null && ! entry.ClientPath.Path.StartsWith(Config.ClientProjectRootMatch) == false); foreach(var itemToRemove in filesToRemove) { log.Debug("Removing file from change " + changeId.ToString() + ", not in project: " + itemToRemove.ClientPath.Path); _changes[changeId].Files.Remove(itemToRemove); } } } 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"; // The default change opts["-C"] = Config.Workspace; // workspace must match opts["-u"] = Config.Username; // username must match also IList<File> allOpenedFiles = p4conn.P4Depot.GetOpenedFiles(Config.ProjectFileSpec, opts); if (!_changes.ContainsKey(DEFAULT_CHANGE)) { RefreshChangeLists(p4conn, false); // Changelists dictionary needs to be constructed first } _changes[DEFAULT_CHANGE].Files.Clear(); // Clear out old list of files if (allOpenedFiles != null) { List<FileSpec> fromMetas = allOpenedFiles.Cast<FileSpec>().ToList(); // Strip the version from each entry foreach (var m in fromMetas) m.Version = null; List<FileSpec> allOpenedFileSpecs = fromMetas.ToList(); //log.Debug("opened : " + Logger.FileSpecListToString(allOpenedFileSpecs)); Options fsopts = new Options(); fsopts["-Op"] = null; // Return "real" clientpaths // issue an fstat to get a proper FileMetaData for each file. We need lastAction and other fields List<FileMetaData> allFilesMeta = Engine.GetFileMetaData(p4conn, allOpenedFileSpecs, fsopts).ToList(); // log.Debug("opened metas: " + Logger.FileMetaDataListToString(allFilesMeta)); foreach (FileMetaData fmd in allFilesMeta) { _changes[DEFAULT_CHANGE].Files.Add(fmd); } } } } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#10 | 16251 | Norman Morse | Update Dev branch to match reorganization in workshop | ||
#9 | 14236 | Norman Morse | update dev branch with GA.8 release files | ||
#8 | 13872 | Norman Morse | Update dev branch from GA.5 release | ||
#7 | 12863 | Norman Morse |
import from main Recently updated from internal Several Bugfixes logging clean up |
||
#6 | 12564 | Norman Morse |
Made ChangeManager into Static Class. Improved close window behavior for when connection is invalid Fixed localOpenFiles not updating on submit |
||
#5 | 12558 | Norman Morse | Integrate from main to dev | ||
#4 | 12501 | Norman Morse |
Rewrote Configuration Window. Provided buttons to read values and to save configurations. Removed P4Config settings, replaced with P4Config button and reports to Debug.Log() Removed SaveConfigurationAsset Setting, replaced with "Save as Asset" button. Made Connection Configuration read only while connected. Made dialogs disappear if they become disconnected during OnGui() Bumped Beta Value. |
||
#3 | 12480 | Norman Morse |
Fixed crash in logging. Worked on UI issues. Cleaned up some connection usage. Still looking for the problem with pending changes. |
||
#2 | 12473 | Norman Morse | More minor fixes to logging and config | ||
#1 | 12445 | Norman Morse |
Integrated log4net and nunit into P4Connect. Still need cleanup and debugging, good enough for dev tree Also added ChangeManager and ChangeLists Classes for future use with multiple changes. |