/// <summary> /// Excecute a command. /// </summary> /// <param name="isCommandEnabled">The options parameter, true if this command is enabled.</param> /// <param name="commandName">The friendly name of this command, for logging.</param> /// <param name="action">The method to be executed to carry out the command.</param> private void ExecuteCommand(bool isCommandEnabled, string commandName, Func <VsSelection, bool> action) { // DAB: I doubt if this is necessary, but the Microsoft sample SccProvider did this. Very defensive. if (!_sccService.IsSolutionLoaded) { Debug.Assert(false, "No solution, so the command should have been disabled"); return; } // DAB: I doubt if this is necessary, I'm being defensive. if (!isCommandEnabled) { LogCommandError(commandName); return; } if (!SaveSolution()) { return; } VsSelection selection = GetSelection(); action(selection); // All nodes and fileNames in the selection will be refreshed when P4Cache.P4CacheUpdated is thrown. }
/// <summary> /// Add one or more fileNames to the cache. This is NOT done on a background thread. /// </summary> /// <param name="vsSelection">A list of files to add or update.</param> public void AddOrUpdateFiles(VsSelection vsSelection) { IList <string> fileNames = vsSelection.FileNamesUnPiped; Log.Debug(String.Format("P4Cache.AddOrUpdateFiles(): Setting cache for {0} files", fileNames.Count)); Log.Debug("P4Cache:AddOrUpdateFiles: Starting SetFileStates()."); SetFileStates(fileNames); }
/// <summary> /// This is intended for when a new solution has been loaded. /// Clear the cache. /// Reload the cache with the fileNames (duplicates are okay). /// Then start a new thread to update the FileState for every file in fileNames. /// Then throw an event when all fileStates have been updated, so VS can rediscover glyphs (from NotSet to whatever is the correct FileState). /// All of this is to avoid sloooowww VS response time for large solutions while waiting for discovery of Perforce FileStates. /// </summary> /// <param name="vsSelection">A list of files to update and nodes to refresh.</param> public void Initialize(VsSelection vsSelection) { lock (_fileStatesLock) { _fileStates.Clear(); } AddOrUpdateFilesBackground(vsSelection); }
/// <summary> /// Add one or more fileNames to the cache. Also used to signal the need to update fileStates of existing files. /// Then kick off a thread to update their fileStates. /// Then start a new thread to update the FileState for every file in fileNames. /// Then throw an event when all fileStates have been updated, so VS can rediscover glyphs (from NotSet to whatever is the correct FileState). /// All of this is to avoid sloooowww VS response time for large solutions while waiting for discovery of Perforce FileStates. /// </summary> /// <param name="vsSelection">A list of files and nodes to refresh.</param> public void AddOrUpdateFilesBackground(VsSelection vsSelection) { if (vsSelection.FileNamesUnPiped.Count == 0) { return; } Trace.WriteLineIf(_traceSwitch.TraceVerbose, "P4Cache.AddOrUpdateFilesBackground started"); Log.Debug(String.Format("P4Cache.AddOrUpdateFilesBackground(): {0} files for {1} nodes", vsSelection.FileNamesUnPiped.Count, vsSelection.Nodes.Count)); SetFileStatesToNotSet(vsSelection); // Note: The updating flag *could* already be set if we get here between the time we release the lock and the // time the background thread is able to get the lock again. In that case, just do nothing more, because the // background thread will eventually get to run and update the files we just added to _fileStates. if (!_cacheIsUpdating) { _cacheIsUpdating = true; // Now kick off a thread that updates the FileState for every fileNode in tLhe dictionary. We do this // inside the lock, so that 2 threads can't do it at the same time. Trace.WriteLineIf(_traceSwitch.TraceVerbose, "P4Cache.AddOrUpdateFilesBackground starting SetFileStates on background thread"); Log.Debug("P4Cache:AddOrUpdateFilesBackground: Starting SetFileStates() on background thread."); _cacheUpdateTask = Task.Factory.StartNew(() => { // Execute the entire background thread with the lock engaged, to prevent another call to // AddOrUpdateFilesBackground from attempting to start us again until we've completed. It is // important that we reset the "is updating" flag while locked or we could get into this // race condition. lock (_fileStatesLock) { Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Background thread acquired lock."); try { SetFileStates(vsSelection); } catch (Exception ex) { Trace.WriteLineIf(_traceSwitch.TraceError, String.Format("Background update thread encountered exception: {0}", ex.Message)); // Regardless of how many times we may have tried before to update the cache, now that // it has failed, we must consider the cache inactive because it's not current and we // apparently cannot make it current. _cacheActive = false; } finally { // SetFileStates will reset this if it finishes successfully. This is here mostly in // case we get any exceptions. _cacheIsUpdating = false; } Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Background thread releasing lock."); } }); } Trace.WriteLineIf(_traceSwitch.TraceVerbose, "P4Cache.AddOrUpdateFilesBackground unlocking _fileStatesLock"); }
OLECMDF QueryStatus_icmdTimeLapse() { if (!_sccService.IsSolutionLoaded) { return(OLECMDF.OLECMDF_INVISIBLE); } if (!_sccService.Options.IsViewTimeLapseEnabled) { return(OLECMDF.OLECMDF_INVISIBLE); } VsSelection selection = GetSelection(); return(selection.FileNames.Any(file => _sccService.IsEligibleForTimeLapse(file)) ? OLECMDF.OLECMDF_ENABLED : OLECMDF.OLECMDF_SUPPORTED); }
OLECMDF QueryStatus_icmdGetLatestRevison() { if (!_sccService.IsSolutionLoaded) { return(OLECMDF.OLECMDF_INVISIBLE); } if (!_sccService.Options.IsGetLatestRevisionEnabled) { return(OLECMDF.OLECMDF_INVISIBLE); } VsSelection selection = GetSelection(); return(selection.FileNames.Any(file => _sccService.IsEligibleForGetLatestRevision(file)) ? OLECMDF.OLECMDF_ENABLED : OLECMDF.OLECMDF_SUPPORTED); }
OLECMDF QueryStatus_icmdRevertIfUnchanged() { if (!_sccService.IsSolutionLoaded) { return(OLECMDF.OLECMDF_INVISIBLE); } if (!_sccService.Options.IsRevertIfUnchangedEnabled) { return(OLECMDF.OLECMDF_INVISIBLE); } VsSelection selection = GetSelection(); return(selection.FileNames.Any(file => _sccService.IsEligibleForRevertIfUnchanged(file)) ? OLECMDF.OLECMDF_ENABLED : OLECMDF.OLECMDF_SUPPORTED); }
/// <summary> /// This is intended for when a new solution has been loaded. /// Clear the cache. /// Reload the cache with the fileNames (duplicates are okay). /// Then start a new thread to update the FileState for every file in fileNames. /// Then throw an event when all fileStates have been updated, so VS can rediscover glyphs (from NotSet to whatever is the correct FileState). /// All of this is to avoid sloooowww VS response time for large solutions while waiting for discovery of Perforce FileStates. /// </summary> /// <param name="vsSelection">A list of files to update and nodes to refresh.</param> public void Initialize(VsSelection vsSelection) { Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Initializing P4Cache"); lock (_fileStatesLock) { // Just to be safe, make sure we aren't already initializing or updating the cache... if (_cacheIsUpdating) { throw new P4CacheUpdateException("Initialize called while Initialize or an update is already active."); } _cacheActive = true; _fileStates.Clear(); AddOrUpdateFilesBackground(vsSelection); } Trace.WriteLineIf(_traceSwitch.TraceVerbose, "P4Cache initialized"); }
private void SetFileStatesToNotSet(VsSelection vsSelection) { IList <string> fileNames = vsSelection.FileNamesUnPiped; lock (_fileStatesLock) { foreach (var fileName in fileNames) { Trace.WriteLineIf(_traceSwitch.TraceVerbose, String.Format("P4Cache.SetFileStatesToNotSet received filename {0}", fileName)); if (_fileStates.ContainsKey(fileName)) { // Ignore duplicates. We may already have set their state. continue; } _fileStates[fileName] = FileState.NotSet; } } }
/// <summary> /// Add one or more fileNames to the cache. Also used to signal the need to update fileStates of existing files. /// Then kick off a thread to update their fileStates. /// Then start a new thread to update the FileState for every file in fileNames. /// Then throw an event when all fileStates have been updated, so VS can rediscover glyphs (from NotSet to whatever is the correct FileState). /// All of this is to avoid sloooowww VS response time for large solutions while waiting for discovery of Perforce FileStates. /// </summary> /// <param name="vsSelection">A list of files and nodes to refresh.</param> public void AddOrUpdateFilesBackground(VsSelection vsSelection) { IList <string> fileNames = vsSelection.FileNamesUnPiped; Log.Debug(String.Format("P4Cache.AddOrUpdateFilesBackground(): {0} files for {1} nodes", fileNames.Count, vsSelection.Nodes.Count)); lock (_fileStatesLock) { foreach (var fileName in fileNames) { if (_fileStates.ContainsKey(fileName)) { // Ignore duplicates. We may already have set their state. continue; } _fileStates[fileName] = FileState.NotSet; } } // Now kick off a thread that updates the FileState for every fileNode in tLhe dictionary. Log.Debug("P4Cache:AddOrUpdateFilesBackground: Starting SetFileStates() on background thread."); Task.Factory.StartNew(() => SetFileStates(vsSelection)); }
public P4CacheEventArgs(VsSelection vsSelection) { VsSelection = vsSelection; }