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 //log.Debug("P4Client: " + aConnection.P4Client.Name); //log.Debug("P4Server: " + aConnection.P4Server.Address.ToString()); 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 | |
---|---|---|---|---|---|
#4 | 20581 | Norman Morse |
Add P4Connect.Skin Fixed issues in ChangeManager Renamed ChangeLists to ChangeListsWindow. |
||
#3 | 20275 | Norman Morse |
Update source to match 2016.2 patch 2 release Much thrashing of source during refactor. Proper caching of asset statuses, reducing fstats issued. Some bug fixes by Liz Lam Cleanup of Pending changes, rework of initialization and play/stop play transitions |
||
#2 | 16350 | Norman Morse |
Minor Code Clean Up Minor Documentation Clean Up Changed Post Processor callback to ignore directories Added option to use Server Typemap |
||
#1 | 16209 | Norman Morse | Move entire source tree into "main" branch so workshop code will act correctly. | ||
//guest/perforce_software/p4connect/src/P4Connect/P4Connect/P4Connect.ChangeManager.cs | |||||
#9 | 15244 | Norman Morse |
Better Directory support in "add" "get latest" "refresh" and other commands. Improved Project Root detection Various Bug Fixes and Clean up |
||
#8 | 14193 | Norman Morse |
GA.7 release Refactor Pending Changes Resolve Submit issues. Fixed Menu entries. Handle mismatched file and meta states. |
||
#7 | 13824 | Norman Morse |
Changes to have fstat return true client paths. Remove versions, fixes problems with "local" paths sneaking into results. |
||
#6 | 13813 | Norman Morse |
Changed Config to call CheckProjectRoot which creates ClientProjectRoot and DepotProjectRoot Filter files in changelists to include only files under the Project root. Run fstat on files in the default change to make sure we have complete metadata |
||
#5 | 13692 | Norman Morse |
Fix FileSpec corruption issue Make sure that the logged in user is verified against files in the default change. Multiple users can share the same workspace and cause lots of confusion. Also changed the code in Perforce.P4.Changelist.ToString() to create new FileSpecs instead of doing implicite casts. This should fix the exception if the source FileMetaData is incomplete some how. |
||
#4 | 12862 | Norman Morse |
Fixed problem with an empty default change list not refresshing. Fixed crash in is_ignored Removed a lot of log output |
||
#3 | 12565 | Norman Morse |
Integrated from Dev Branch Made ChangeManager into Static Class. Improved close window behavior for when connection is invalid Fixed localOpenFiles not updating on submit |
||
#2 | 12553 | Norman Morse |
integrate from internal main Build fixes for EC. Major changes to Configuration and re-initialization code. Bug fixes |
||
#1 | 12512 | Norman Morse | Integrate from Dev branch, preparing for Beta3 release | ||
//guest/norman_morse/dev/p4connect/src/P4Connect/P4Connect/P4Connect.ChangeManager.cs | |||||
#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. |