/// <summary> /// /// </summary> /// <param name="cProjects"></param> /// <param name="cDirectories"></param> /// <param name="rgpProjects"></param> /// <param name="rgFirstIndices"></param> /// <param name="rgpszMkDocuments"></param> /// <param name="rgFlags"></param> /// <returns></returns> /// <remarks>Deny a query only if allowing the operation would compromise your stable state</remarks> public int OnAfterAddDirectoriesEx(int cProjects, int cDirectories, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSADDDIRECTORYFLAGS[] rgFlags) { if (rgpProjects == null || rgpszMkDocuments == null) return VSConstants.E_POINTER; for (int i = 0; i < cDirectories; i++) { string dir = rgpszMkDocuments[i]; if (string.IsNullOrEmpty(dir) || !SvnItem.IsValidPath(dir)) continue; dir = SvnTools.GetNormalizedFullPath(dir); StatusCache.MarkDirty(dir); SvnItem item = StatusCache[dir]; if (!item.Exists || !item.IsDirectory || !SvnTools.IsManagedPath(dir)) continue; if ((DateTime.UtcNow - GetCreated(item)) > new TimeSpan(0, 1, 0)) continue; // Directory is older than one minute.. Not just copied using (SvnSccContext svn = new SvnSccContext(Context)) { // Ok; we have a 'new' directory here.. Lets check if VS broke the subversion working copy SvnWorkingCopyEntryEventArgs entry = svn.SafeGetEntry(dir); if (entry != null && entry.NodeKind == SvnNodeKind.Directory) // Entry exists, valid dir continue; // VS Added a versioned dir below our project -> Unversion the directory to allow adding files // Don't unversion the directory if the parent is not versioned string parentDir = SvnTools.GetNormalizedDirectoryName(dir); if (parentDir == null || !SvnTools.IsManagedPath(parentDir)) continue; svn.UnversionRecursive(dir); } } for (int iProject = 0, iDir=0; (iProject < cProjects) && (iDir < cDirectories); iProject++) { int iLastDirectoryThisProject = (iProject < cProjects - 1) ? rgFirstIndices[iProject + 1] : cDirectories; IVsSccProject2 sccProject = rgpProjects[iProject] as IVsSccProject2; bool track = SccProvider.TrackProjectChanges(sccProject); for (; iDir < iLastDirectoryThisProject; iDir++) { if (!track) continue; string dir = rgpszMkDocuments[iDir]; if (string.IsNullOrEmpty(dir) || !SvnItem.IsValidPath(dir)) continue; dir = SvnTools.GetNormalizedFullPath(dir); if (sccProject != null) SccProvider.OnProjectDirectoryAdded(sccProject, dir, rgFlags[iDir]); } } return VSConstants.S_OK; }
/// <summary> /// Fixes working copies which are invalidated by a rename operation /// </summary> /// <param name="rgszMkOldNames"></param> /// <param name="rgszMkNewNames"></param> private void FixWorkingCopyAfterRenames(string[] rgszMkOldNames, string[] rgszMkNewNames) { if (rgszMkNewNames == null || rgszMkOldNames == null || rgszMkOldNames.Length != rgszMkNewNames.Length) return; for (int i = 0; i < rgszMkOldNames.Length; i++) { string oldName = rgszMkOldNames[i]; string newName = rgszMkNewNames[i]; if (string.IsNullOrEmpty(oldName) || !SvnItem.IsValidPath(oldName)) continue; oldName = SvnTools.GetNormalizedFullPath(oldName); newName = SvnTools.GetNormalizedFullPath(newName); string oldDir; string newDir; bool safeRename =false; if (!Directory.Exists(newName)) { // Try to fix the parent of the new item oldDir = SvnTools.GetNormalizedDirectoryName(oldName); newDir = SvnTools.GetNormalizedDirectoryName(newName); } else { // The item itself is the directory to fix oldDir = oldName; newDir = newName; safeRename = true; } if (Directory.Exists(oldDir)) continue; // Nothing to fix up string parent = SvnTools.GetNormalizedDirectoryName(oldDir); if (!Directory.Exists(parent)) { continue; // We can't fix up more than one level at this time // We probably fix it with one of the following renames; as paths are included too } SvnItem item = StatusCache[oldDir]; if (!item.IsVersioned && item.Status.LocalContentStatus != SvnStatus.Missing) continue; // Item was not cached as versioned or now-missing (Missing implicits Versioned) StatusCache.MarkDirty(oldDir); StatusCache.MarkDirty(newDir); item = StatusCache[oldDir]; if (item.Status.LocalContentStatus != SvnStatus.Missing) continue; SvnItem newItem = StatusCache[newDir]; using (SvnSccContext svn = new SvnSccContext(Context)) { SvnWorkingCopyEntryEventArgs wa = svn.SafeGetEntry(newDir); string newParent = SvnTools.GetNormalizedDirectoryName(newDir); if (wa != null) continue; // Not an unexpected WC root else if (!SvnTools.IsManagedPath(newDir)) continue; // Not a wc root at all svn.SafeWcDirectoryCopyFixUp(oldDir, newDir, safeRename); // Recreate the old WC directory _delayedDeletes.Add(oldDir); // Delete everything in the old wc when done // TODO: Once Subversion understands true renames, fixup the renames in the delayed hook RegisterForSccCleanup(); // We have all files of the old wc directory unversioned in the new location now StatusCache.MarkDirtyRecursive(oldDir); StatusCache.MarkDirtyRecursive(newDir); } } }