/// <summary> /// Returns a list of controllable projects in the solution /// </summary> internal Hashtable GetLoadedControllableProjectsEnum() { Hashtable mapHierarchies = new Hashtable(); IVsSolution sol = (IVsSolution)GetService(typeof(SVsSolution)); Guid rguidEnumOnlyThisType = new Guid(); IEnumHierarchies ppenum = null; ErrorHandler.ThrowOnFailure(sol.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref rguidEnumOnlyThisType, out ppenum)); IVsHierarchy[] rgelt = new IVsHierarchy[1]; uint pceltFetched = 0; while (ppenum.Next(1, rgelt, out pceltFetched) == VSConstants.S_OK && pceltFetched == 1) { IVsSccProject2 sccProject2 = rgelt[0] as IVsSccProject2; if (sccProject2 != null) { mapHierarchies[rgelt[0]] = true; } } return(mapHierarchies); }
/// <summary> /// Returns a list of controllable projects in the solution /// </summary> public List <IVsSccProject2> GetLoadedControllableProjects() { var list = new List <IVsSccProject2>(); IVsSolution sol = (IVsSolution)_sccProvider.GetService(typeof(SVsSolution)); list.Add(sol as IVsSccProject2); Guid rguidEnumOnlyThisType = new Guid(); IEnumHierarchies ppenum = null; ErrorHandler.ThrowOnFailure(sol.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref rguidEnumOnlyThisType, out ppenum)); IVsHierarchy[] rgelt = new IVsHierarchy[1]; uint pceltFetched = 0; while (ppenum.Next(1, rgelt, out pceltFetched) == VSConstants.S_OK && pceltFetched == 1) { IVsSccProject2 sccProject2 = rgelt[0] as IVsSccProject2; if (sccProject2 != null) { list.Add(sccProject2); } } return(list); }
/// <summary> /// Returns a list of source controllable files in the selection /// </summary> private List <string> GetSelectedFiles(out IList <VSITEMSELECTION> selectedNodes) { List <string> sccFiles = new List <string>(); selectedNodes = GetSelectedNodes(); // now look in the rest of selection and accumulate scc files foreach (VSITEMSELECTION vsItemSel in selectedNodes) { IVsSccProject2 pscp2 = vsItemSel.pHier as IVsSccProject2; if (pscp2 == null) { // solution case sccFiles.Add(GetSolutionFileName()); } else { List <string> nodefilesrec = GetProjectFiles(pscp2, vsItemSel.itemid); foreach (string file in nodefilesrec) { sccFiles.Add(file); } } } return(sccFiles); }
void IAnkhSccProviderEvents.OnProjectFileRenamed(IVsSccProject2 sccProject, string oldName, string newName, VSRENAMEFILEFLAGS vSRENAMEFILEFLAGS) { SccProjectData data; ProjectMap.EnsureSccProject(sccProject, out data); OnProjectFileRenamed(data, oldName, newName); }
void IAnkhSccProviderEvents.OnProjectDirectoryRemoved(IVsSccProject2 sccProject, string dir, VSREMOVEDIRECTORYFLAGS vSREMOVEDIRECTORYFLAGS) { SccProjectData data; ProjectMap.EnsureSccProject(sccProject, out data); OnProjectDirectoryRemoved(data, dir); }
public static async Task <List <IVsSccProject2> > GetLoadedControllableProjects() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var list = new List <IVsSccProject2>(); IVsSolution sol = await GetActiveSolution(); list.Add(sol as IVsSccProject2); Guid rguidEnumOnlyThisType = new Guid(); IEnumHierarchies ppenum = null; ErrorHandler.ThrowOnFailure(sol.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref rguidEnumOnlyThisType, out ppenum)); IVsHierarchy[] rgelt = new IVsHierarchy[1]; uint pceltFetched = 0; while (ppenum.Next(1, rgelt, out pceltFetched) == VSConstants.S_OK && pceltFetched == 1) { IVsSccProject2 sccProject2 = rgelt[0] as IVsSccProject2; if (sccProject2 != null && await IsProjectInGitRepoitory(sccProject2)) { list.Add(sccProject2); } } return(list); }
/// <summary> /// Gets the list of source controllable files in the specified project /// </summary> public static async Task <IList <string> > GetProjectFiles(IVsSccProject2 pscp2Project, uint startItemId) { IList <string> projectFiles = new List <string>(); if (pscp2Project == null) { return(projectFiles); } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsHierarchy hierProject = (IVsHierarchy)pscp2Project; var itemid = VSConstants.VSITEMID_ROOT; object objProj; hierProject.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out objProj); var project = objProj as EnvDTE.Project; if (project != null && project.Kind != ProjectKinds.vsProjectKindSolutionFolder) { try { FindFilesInProject(project.ProjectItems, projectFiles); } catch (Exception) { Debug.WriteLine("==== Error With : " + project.Name + " Type : " + project.Kind); } } return(projectFiles); }
/// <summary> /// Gets the list of selected controllable project hierarchies /// </summary> /// <returns>True if a solution was created.</returns> public Hashtable GetSelectedHierarchies(ref IList <VSITEMSELECTION> sel, out bool solutionSelected) { // Initialize output arguments solutionSelected = false; Hashtable mapHierarchies = new Hashtable(); foreach (VSITEMSELECTION vsItemSel in sel) { if (vsItemSel.pHier == null || (vsItemSel.pHier as IVsSolution) != null) { solutionSelected = true; } // See if the selected hierarchy implements the IVsSccProject2 interface // Exclude from selection projects like FTP web projects that don't support SCC IVsSccProject2 sccProject2 = vsItemSel.pHier as IVsSccProject2; if (sccProject2 != null) { mapHierarchies[vsItemSel.pHier] = true; } } return(mapHierarchies); }
public void AddFile(string filename, IVsSccProject2 project) { if (_projects.Contains(project)) { AddFileToList(filename, project); } }
/// <summary> /// Gets the list of source controllable files in the specified project /// </summary> public static async Task<IList<string>> GetProjectFiles(IVsSccProject2 pscp2Project, uint startItemId) { IList<string> projectFiles = new List<string>(); if (pscp2Project == null) { return projectFiles; } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsHierarchy hierProject = (IVsHierarchy)pscp2Project; var itemid = VSConstants.VSITEMID_ROOT; object objProj; hierProject.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out objProj); var project = objProj as EnvDTE.Project; if (project != null && project.Kind != ProjectKinds.vsProjectKindSolutionFolder) { try { FindFilesInProject(project.ProjectItems, projectFiles); } catch (Exception) { Debug.WriteLine("==== Error With : " + project.Name + " Type : " + project.Kind); } } return projectFiles; }
void IAnkhSccProviderEvents.OnProjectFileAdded(IVsSccProject2 project, string filename) { SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectFileAdded(data, filename); }
/// <summary> /// Defines a method to call after a project upgrade. /// </summary> /// <param name="pHierarchy">[in] Pointer to the <see cref="T:Microsoft.VisualStudio.Shell.Interop.IVsHierarchy"></see> interface of the project.</param> /// <param name="fUpgradeFlag">[in] Integer. Flag indicating the nature of the upgrade. Values taken from the <see cref="T:Microsoft.VisualStudio.Shell.Interop.__VSPPROJECTUPGRADEVIAFACTORYFLAGS"></see> enumeration. Will only be PUVFF_COPYUPGRADE, PUVFF_SXSBACKUP, or PUVFF_COPYBACKUP.</param> /// <param name="bstrCopyLocation">[in] String containing the location of the copy upgrade (PUVFF_COPYUPGRADE) or back up copy (PUVFF_COPYBACKUP).</param> /// <param name="stUpgradeTime">[in] A <see cref="T:Microsoft.VisualStudio.Shell.Interop.SYSTEMTIME"></see> value. The time the upgrade was done.</param> /// <param name="pLogger">[in] Pointer to an <see cref="T:Microsoft.VisualStudio.Shell.Interop.IVsUpgradeLogger"></see> interface to use for logging upgrade messages.</param> /// <returns> /// If the method succeeds, it returns <see cref="F:Microsoft.VisualStudio.VSErr.S_OK"></see>. If it fails, it returns an error code. /// </returns> public int OnAfterUpgradeProject(IVsHierarchy pHierarchy, uint fUpgradeFlag, string bstrCopyLocation, SYSTEMTIME stUpgradeTime, IVsUpgradeLogger pLogger) { if (!SccProvider.IsActive) { return(VSErr.S_OK); } IProjectFileMapper mapper = GetService <IProjectFileMapper>(); IFileStatusMonitor monitor = GetService <IFileStatusMonitor>(); if (monitor == null || mapper == null) { return(VSErr.S_OK); } if (SccProvider.IsSafeSccPath(bstrCopyLocation)) { monitor.ScheduleSvnStatus(bstrCopyLocation); } IVsSccProject2 project = pHierarchy as IVsSccProject2; if (project != null) { ISccProjectInfo info = mapper.GetProjectInfo(new SccProject(null, project)); if (info != null && !string.IsNullOrEmpty(info.ProjectFile)) { monitor.ScheduleSvnStatus(info.ProjectFile); } } return(VSErr.S_OK); }
/// <summary> /// Returns a list of files associated with each specified node. /// </summary> /// <param name="hier"></param> /// <param name="itemId"></param> /// <returns></returns> private IList <string> GetNodeFiles(IVsHierarchy hier, uint itemId) { ThreadHelper.ThrowIfNotOnUIThread(); IVsSccProject2 pscp2 = hier as IVsSccProject2; return(GetNodeFiles(pscp2, itemId)); }
private void OnProjectRegister(IVsSccProject2 project) { if (project != null) { repository.UpdateProject(project); } }
//TODO Move TO Provider /// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> public async Task RefreshNodesGlyphs(IList <VSITEMSELECTION> selectedNodes) { foreach (VSITEMSELECTION vsItemSel in selectedNodes) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsSccProject2 sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = await GetSolutionFileName(); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = await _sccProvider.GetServiceAsync(typeof(SVsSolution)) as IVsHierarchy; solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyph() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); } } else { // It may be easier/faster to simply refresh all the nodes in the project, // and let the project call back on GetSccGlyph, but just for the sake of the demo, // let's refresh ourselves only one node at a time IList <string> sccFiles = await GetNodeFiles(sccProject2, vsItemSel.itemid); // We'll use for the node glyph just the Master file's status (ignoring special files of the node) if (sccFiles.Count > 0) { string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = sccFiles[0]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[1]; rguiAffectedNodes[0] = vsItemSel.itemid; sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } } }
public void AddFile(string filename, IVsSccProject2 project) { if (_projects.Contains(project)) { AddFileToList(filename, project); } }
void IAnkhSccProviderEvents.OnProjectOpened(IVsSccProject2 sccProject, bool added) { SccProjectData data; ProjectMap.EnsureSccProject(sccProject, out data); OnProjectOpened(data, added); }
public int OnAfterOpenProject([InAttribute] IVsHierarchy pHierarchy, [InAttribute] int fAdded) { Trace.WriteLine("OnAfterOpenProject"); //if (fAdded == 1) { IVsSccProject2 project = pHierarchy as IVsSccProject2; IList <string> fileList = SccProvider.GetProjectFiles(project); _sccStatusTracker.AddFileToProjectCache(fileList, project); if (fileList.Count > 0) { string[] files = new string[fileList.Count]; fileList.CopyTo(files, 0); // add only files wich are not ignored if (Configuration.Global._autoAddFiles) { _sccStatusTracker.AddWorkItem(new HGLib.TrackFilesAddedNotIgnored(files)); } else { _sccStatusTracker.AddWorkItem(new HGLib.UpdateFileStatusCommand(files)); } } } _sccProvider._LastSeenProjectDir = SccProjectData.ProjectDirectory(pHierarchy); _sccStatusTracker.UpdateProject(pHierarchy as IVsSccProject2); return(VSConstants.S_OK); }
void IAnkhSccProviderEvents.OnProjectFileRemoved(IVsSccProject2 project, string oldName) { SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectFileRemoved(data, oldName); }
private void ProjectPropertyPageFixup(ProjectMap.SccDocumentData dd) { // Ok, we have a project setting page here. // Project settings pages break (our) SCC handling in a number of ways // * It creates an editor buffer for the AssemblyInfo file, but does // not notify changes or tell the user that you should save the file // * It makes the project dirty without notifying // * Saving the setting pages doesn't save your projec // // To work around this we poll all files in the current project for dirty IVsSccProject2 prj = dd.Hierarchy as IVsSccProject2; if (prj != null) { SccProject project = new Ankh.Selection.SccProject(null, prj); foreach (string file in GetService <IProjectFileMapper>().GetAllFilesOf(project)) { SccDocumentData data; if (_docMap.TryGetValue(file, out data)) { data.CheckDirty(_poller); } } } }
void IAnkhSccProviderEvents.OnProjectRenamed(IVsSccProject2 project) { SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectRenamed(data); }
internal void InitProjectInfos(SVsServiceProvider provider, ABnfFactory factory) { if (factory == null) { return; } if (m_server != null) { return; } m_server = new ALanguageServer(); m_server.Start(factory); if (m_cookie != 0) { return; } if (m_solution != null) { return; } m_solution = provider.GetService(typeof(SVsSolution)) as IVsSolution; if (m_solution == null) { return; } m_dot_ext = factory.GetDotExt(); m_file_icon = factory.GetFileIcon(); // 读取所有工程 m_projects.Clear(); Guid rguidEnumOnlyThisType = new Guid(); IEnumHierarchies ppenum = null; m_solution.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref rguidEnumOnlyThisType, out ppenum); IVsHierarchy[] rgelt = new IVsHierarchy[1]; uint pceltFetched = 0; while (ppenum.Next(1, rgelt, out pceltFetched) == VSConstants.S_OK && pceltFetched == 1) { IVsSccProject2 sccProject2 = rgelt[0] as IVsSccProject2; if (sccProject2 != null) { string project_path = GetProjectPath(rgelt[0]); if (project_path != null) { if (m_server != null) { m_server.AddTask(() => m_server.AddProjectInfo(project_path)); } m_projects[rgelt[0]] = new UIProjectInfo(this, rgelt[0], project_path, m_dot_ext, m_file_icon); } } } // 监听工程变化 m_solution.AdviseSolutionEvents(this, out m_cookie); }
void IAnkhSccProviderEvents.OnProjectClosed(IVsSccProject2 project, bool removed) { SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectClosed(data, removed); }
public bool IsProjectManagedRaw(object project) { ThreadHelper.ThrowIfNotOnUIThread(); if (!IsActive) { return(false); } if (project == null) { return(IsSolutionManaged); } IVsSccProject2 sccProject = project as IVsSccProject2; if (sccProject == null) { return(false); } SccProjectData data; if (ProjectMap.TryGetSccProject(sccProject, out data)) { return(data.IsManaged); } return(false); }
public void SetProjectManagedRaw(object project, bool managed) { ThreadHelper.ThrowIfNotOnUIThread(); if (!IsActive) { return; } if (project == null) { // We are talking about the solution if (managed != IsSolutionManaged) { _managedSolution = managed; IsSolutionDirty = true; foreach (SccProjectData p in ProjectMap.AllSccProjects) { if (p.IsStoredInSolution) { p.SetManaged(managed); if (managed) { p.NotifyGlyphsChanged(); } } } } return; } IVsSccProject2 sccProject = project as IVsSccProject2; if (sccProject == null) { if (project is IVsSolution) { SetProjectManagedRaw(null, managed); } return; } SccProjectData data; if (!ProjectMap.TryGetSccProject(sccProject, out data)) { return; } if (managed == data.IsManaged) { return; // Nothing to change } data.SetManaged(managed); }
public IEnumerable <string> GetAllFilesOf(ICollection <SccProject> projects, bool exceptExcluded) { SortedList <string, string> files = new SortedList <string, string>(StringComparer.OrdinalIgnoreCase); Hashtable handled = new Hashtable(); foreach (SccProject p in projects) { SccProject project = ResolveRawProject(p); IVsSccProject2 scc = project.RawHandle; SccProjectData data; if (scc == null || !TryGetSccProject(scc, out data)) { if (p.IsSolution && SolutionFilename != null && !files.ContainsKey(SolutionFilename)) { files.Add(SolutionFilename, SolutionFilename); if (exceptExcluded && IsSccExcluded(SolutionFilename)) { continue; } yield return(SolutionFilename); } continue; } if (handled.Contains(data)) { continue; } handled.Add(data, data); foreach (string file in data.GetAllFiles()) { if (file[file.Length - 1] == '\\') // Don't return paths { continue; } if (files.ContainsKey(file)) { continue; } files.Add(file, file); if (exceptExcluded && IsSccExcluded(file)) { continue; } yield return(file); } } }
public void EnsureSccProject(IVsSccProject2 rawProject, out SccProjectData projectData) { if (!TryGetSccProject(rawProject, out projectData)) { // This method is called before the OpenProject calls AddProject(rawProject, projectData = new SccProjectData(this, rawProject)); } }
private bool IgnoreSideEffects(IVsSccProject2 sccProject) { if (sccProject != null && ProjectMap.IgnoreEnumerationSideEffects(sccProject)) { return(true); } return(false); }
public static bool IsSolutionSccProject(IVsSccProject2 project) { if (project == null) { throw new ArgumentNullException("project"); } return(project is SolutionSccHelper); }
void IAnkhSccProviderEvents.OnProjectRenamed(IVsSccProject2 project) { ThreadHelper.ThrowIfNotOnUIThread(); SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectRenamed(data); }
void IAnkhSccProviderEvents.OnProjectDirectoryRemoved(IVsSccProject2 sccProject, string dir, VSREMOVEDIRECTORYFLAGS vSREMOVEDIRECTORYFLAGS) { ThreadHelper.ThrowIfNotOnUIThread(); SccProjectData data; ProjectMap.EnsureSccProject(sccProject, out data); OnProjectDirectoryRemoved(data, dir); }
void IAnkhSccProviderEvents.OnProjectFileRemoved(IVsSccProject2 project, string oldName) { ThreadHelper.ThrowIfNotOnUIThread(); SccProjectData data; ProjectMap.EnsureSccProject(project, out data); OnProjectFileRemoved(data, oldName); }
public static async Task<bool> IsProjectInGitRepoitory(IVsSccProject2 project) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var filename = await GetProjectFileName(project as IVsHierarchy); if (!string.IsNullOrWhiteSpace(filename)) { return RepositoryManager.Instance.IsProjectInGitRepoitory(filename); } return false; }
private void AddFileToList(string filename, IVsSccProject2 project) { List<IVsSccProject2> projects; if (!_fileProjectLookup.TryGetValue(filename, out projects)) { _fileProjectLookup.TryAdd(filename, new List<IVsSccProject2> { project }); } else { if (!projects.Contains(project)) { projects.Add(project); } } }
/// <summary> /// Called when a file in a project is renamed /// </summary> /// <param name="project">The SCC project.</param> /// <param name="oldName">The old name.</param> /// <param name="newName">The new name.</param> /// <param name="flags">The flags.</param> internal void OnProjectRenamedFile(IVsSccProject2 project, string oldName, string newName, VSRENAMEFILEFLAGS flags) { SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; // Not managed by us else data.CheckProjectRename(project, oldName, newName); // Just to be sure (should be handled by other event) data.RemovePath(oldName); data.AddPath(newName); if (!IsActive) return; using (GitSccContext git = new GitSccContext(Context)) { if (!git.IsUnversioned(oldName)) { if (!Directory.Exists(newName)) // Fails if the new name is a directory! git.SafeWcMoveFixup(oldName, newName); } MarkDirty(new string[] { oldName, newName }, true); } }
public bool ProjectAddedToCache(IVsSccProject2 project) { return _projects.Contains(project); }
public async Task QuickRefreshNodesGlyphs(IVsSccProject2 project, List<string> files) { try { if (files.Count > 0) { string[] rgpszFullPaths = new string[files.Count]; for (int i = 0; i < files.Count; i++) rgpszFullPaths[i] = files[i]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[files.Count]; uint[] rgdwSccStatus = new uint[files.Count]; GetSccGlyph(files.Count, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[files.Count]; //TODO We could/Should cache this mapping !!!! await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IList<uint> subnodes = await SolutionExtensions.GetProjectItems((IVsHierarchy)project, VSConstants.VSITEMID_ROOT); var dict = new Dictionary<string, uint>(); var proj = project as IVsProject2; foreach (var id in subnodes) { string docname; var res = proj.GetMkDocument(id, out docname); if (res == VSConstants.S_OK && !string.IsNullOrEmpty(docname)) dict[docname] = id; } for (int i = 0; i < files.Count; ++i) { uint id; if (dict.TryGetValue(files[i], out id)) { rguiAffectedNodes[i] = id; } } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); project.SccGlyphChanged(files.Count, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } catch (Exception ex) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsActivityLog log = _sccProvider.GetService(typeof(SVsActivityLog)) as IVsActivityLog; if (log == null) return; int hr = log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, ex.StackTrace, string.Format(CultureInfo.CurrentCulture, "Called for: {0}", this.ToString())); } }
/// <summary> /// Called by ProjectDocumentTracker when a scc-capable project is opened /// </summary> /// <param name="project">The loaded project</param> /// <param name="added">The project was added after opening</param> internal void OnProjectOpened(IVsSccProject2 project, bool added) { SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) _projectMap.Add(project, data = new SccProjectData(Context, project)); if (data.IsSolutionFolder || data.IsWebSite) { if (IsSolutionManaged) { // We let them follow the solution settings (See OnSolutionOpen() for the not added case if (added && data.IsSolutionFolder) data.SetManaged(true); } // Solution folders are projects without Scc state data.NotifyGlyphsChanged(); } _syncMap = true; // Don't take the focus from naming the folder. The rename will perform the .Load() // and dirty check if (added && data.IsSolutionFolder) return; bool isReload = (_reloading == data.ProjectLocation); _reloading = null; if (added && !isReload) { if (!string.IsNullOrEmpty(SolutionFilename)) DocumentTracker.CheckDirty(SolutionFilename); } RegisterForSccCleanup(); }
/// <summary> /// Returns a list of source controllable files associated with the specified node /// </summary> private IList<string> GetNodeFiles(IVsSccProject2 pscp2, uint itemid) { // NOTE: the function returns only a list of files, containing both regular files and special files // If you want to hide the special files (similar with solution explorer), you may need to return // the special files in a hastable (key=master_file, values=special_file_list) // Initialize output parameters IList<string> sccFiles = new List<string>(); if (pscp2 != null) { var pathStr = new CALPOLESTR[1]; var flags = new CADWORD[1]; if (pscp2.GetSccFiles(itemid, pathStr, flags) == 0) { for (int elemIndex = 0; elemIndex < pathStr[0].cElems; elemIndex++) { var pathIntPtr = Marshal.ReadIntPtr(pathStr[0].pElems, elemIndex); var path = Marshal.PtrToStringAuto(pathIntPtr); sccFiles.Add(path); // See if there are special files if (flags.Length > 0 && flags[0].cElems > 0) { int flag = Marshal.ReadInt32(flags[0].pElems, elemIndex); if (flag != 0) { // We have special files var specialFiles = new CALPOLESTR[1]; var specialFlags = new CADWORD[1]; pscp2.GetSccSpecialFiles(itemid, path, specialFiles, specialFlags); for (int i = 0; i < specialFiles[0].cElems; i++) { IntPtr specialPathIntPtr = Marshal.ReadIntPtr(specialFiles[0].pElems, i * IntPtr.Size); String specialPath = Marshal.PtrToStringAuto(specialPathIntPtr); sccFiles.Add(specialPath); Marshal.FreeCoTaskMem(specialPathIntPtr); } if (specialFiles[0].cElems > 0) { Marshal.FreeCoTaskMem(specialFiles[0].pElems); } } } Marshal.FreeCoTaskMem(pathIntPtr); } if (pathStr[0].cElems > 0) { Marshal.FreeCoTaskMem(pathStr[0].pElems); } } } return sccFiles; }
/// <summary> /// Called when a directory in a project is renamed /// </summary> /// <param name="project">The SCC project.</param> /// <param name="oldName">The old name.</param> /// <param name="newName">The new name.</param> /// <param name="flags">The flags.</param> internal void OnProjectDirectoryRenamed(IVsSccProject2 project, string oldName, string newName, VSRENAMEDIRECTORYFLAGS flags) { SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; // Not managed by us if (!IsActive) return; Debug.Assert(!Directory.Exists(oldName)); Debug.Assert(Directory.Exists(newName)); GC.KeepAlive(newName); GC.KeepAlive(oldName); }
/// <summary> /// Returns a list of source controllable files associated with the specified node /// </summary> private static async Task<IList<string>> GetNodeFiles(IVsSccProject2 pscp2, uint itemid) { // NOTE: the function returns only a list of files, containing both regular files and special files // If you want to hide the special files (similar with solution explorer), you may need to return // the special files in a hastable (key=master_file, values=special_file_list) // Initialize output parameters IList<string> sccFiles = new List<string>(); if (pscp2 != null) { CALPOLESTR[] pathStr = new CALPOLESTR[1]; CADWORD[] flags = new CADWORD[1]; await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (pscp2.GetSccFiles(itemid, pathStr, flags) == 0) { for (int elemIndex = 0; elemIndex < pathStr[0].cElems; elemIndex++) { IntPtr pathIntPtr = Marshal.ReadIntPtr(pathStr[0].pElems, elemIndex); String path = Marshal.PtrToStringAuto(pathIntPtr); sccFiles.Add(path); // See if there are special files if (flags.Length > 0 && flags[0].cElems > 0) { int flag = Marshal.ReadInt32(flags[0].pElems, elemIndex); if (flag != 0) { // We have special files CALPOLESTR[] specialFiles = new CALPOLESTR[1]; CADWORD[] specialFlags = new CADWORD[1]; pscp2.GetSccSpecialFiles(itemid, path, specialFiles, specialFlags); for (int i = 0; i < specialFiles[0].cElems; i++) { IntPtr specialPathIntPtr = Marshal.ReadIntPtr(specialFiles[0].pElems, i * IntPtr.Size); String specialPath = Marshal.PtrToStringAuto(specialPathIntPtr); sccFiles.Add(specialPath); Marshal.FreeCoTaskMem(specialPathIntPtr); } if (specialFiles[0].cElems > 0) { Marshal.FreeCoTaskMem(specialFiles[0].pElems); } } } Marshal.FreeCoTaskMem(pathIntPtr); } if (pathStr[0].cElems > 0) { Marshal.FreeCoTaskMem(pathStr[0].pElems); } } } else if (itemid == VSConstants.VSITEMID_ROOT) { sccFiles.Add(await GetSolutionFileName()); } return sccFiles; }
/// <summary> /// Called by ProjectDocumentTracker when a scc-capable project is closed /// </summary> /// <param name="project">The project.</param> /// <param name="removed">if set to <c>true</c> the project is being removed or unloaded from the solution.</param> internal void OnProjectClosed(IVsSccProject2 project, bool removed) { SccProjectData data; _reloading = null; if (_projectMap.TryGetValue(project, out data)) { data.OnClose(); _projectMap.Remove(project); if (data.Unloading) _reloading = data.ProjectLocation; } if (removed && _reloading == null) { if (!string.IsNullOrEmpty(SolutionFilename)) DocumentTracker.CheckDirty(SolutionFilename); } }
//[CLSCompliant(false)] public static bool GetSccFiles(IVsHierarchy hierarchy, IVsSccProject2 sccProject, uint id, out string[] files, out int[] flags, bool includeNoScc, IDictionary<string, uint> map) { if (hierarchy == null) throw new ArgumentNullException("hierarchy"); int hr; bool ok = false; files = null; flags = null; try { if (sccProject != null) { CALPOLESTR[] str = new CALPOLESTR[1]; CADWORD[] dw = new CADWORD[1]; if (ErrorHandler.Succeeded(hr = sccProject.GetSccFiles(id, str, dw))) { files = GetFileNamesFromOleBuffer(str, true); flags = GetFlagsFromOleBuffer(dw, true); if (!includeNoScc || files.Length > 0) return ok = true; // We have a result else ok = true; // Try the GetMkDocument route to find an alternative } else if (hr != VSConstants.E_NOTIMPL) return false; // } // If sccProject2.GetSccFiles() returns E_NOTIMPL we must try GetMkDocument // We also try this if the item does not implement IVsSccProject2 IVsProject project = hierarchy as IVsProject; if (project != null) { string mkDocument; if (ErrorHandler.Succeeded(project.GetMkDocument(id, out mkDocument))) { if (!IsValidPath(mkDocument)) files = new string[0]; else files = new string[] { mkDocument }; return true; } return ok; // No need to check our interface for projects } if (hierarchy is IVsSolution) { return ok; // Will fail in GetCanonicalName in VS2008 SP1 Beta 1 } string name; try { if (ErrorHandler.Succeeded(hierarchy.GetCanonicalName(id, out name))) { if (IsValidPath(name, true)) { files = new string[] { name }; return true; } } } catch { } // Ok, this seems to error in some managed tree implementations like TFS :( return ok; } finally { if (ok && map != null && files != null) { foreach (string file in files) map[file] = id; } } }
internal bool TrackProjectChanges(IVsSccProject2 project, out bool trackCopies) { // We can be called with a null project SccProjectData data; if (project != null && _projectMap.TryGetValue(project, out data)) { trackCopies = true; if (data.IsWebSite) { int busy; if (BuildManager != null && ErrorHandler.Succeeded(BuildManager.QueryBuildManagerBusy(out busy)) && busy != 0) { trackCopies = false; } } else if (_syncMap) data.Load(); return data.TrackProjectChanges(); // Allows temporary disabling changes } trackCopies = false; return false; }
/// <summary> /// This method is called by projects that are under source control /// when they are first opened to register project settings. /// </summary> /// <param name="pscp2Project">The PSCP2 project.</param> /// <param name="pszSccProjectName">Name of the PSZ SCC project.</param> /// <param name="pszSccAuxPath">The PSZ SCC aux path.</param> /// <param name="pszSccLocalPath">The PSZ SCC local path.</param> /// <param name="pszProvider">The PSZ provider.</param> /// <returns></returns> public int RegisterSccProject(IVsSccProject2 pscp2Project, string pszSccProjectName, string pszSccAuxPath, string pszSccLocalPath, string pszProvider) { SccProjectData data; if (!_projectMap.TryGetValue(pscp2Project, out data)) { // This method is called before the OpenProject calls _projectMap.Add(pscp2Project, data = new SccProjectData(Context, pscp2Project)); } data.IsManaged = (pszProvider == VisualGitId.GitSccName); data.IsRegistered = true; _syncMap = true; RegisterForSccCleanup(); return VSConstants.S_OK; }
internal bool TrackProjectChanges(IVsSccProject2 project) { bool trackCopies; return TrackProjectChanges(project, out trackCopies); }
/// <summary> /// Called when a project is explicitly refreshed /// </summary> /// <param name="project"></param> internal void RefreshProject(IVsSccProject2 project) { if (project == null) throw new ArgumentNullException("project"); SccProjectData data; if (_projectMap.TryGetValue(project, out data)) { data.Reload(); } }
internal void OnProjectRenamed(IVsSccProject2 project) { if (string.IsNullOrEmpty(SolutionFilename)) return; SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; string oldLocation = data.ProjectLocation; try { using (SccProjectData newData = new SccProjectData(Context, project)) { string newLocation = newData.ProjectLocation; if (newLocation == null && oldLocation == null) return; // No need to do anything for this case (e.g. solution folders) SccStore.OnProjectRenamed(oldLocation, newLocation); if (string.Equals(newData.ProjectFile, data.ProjectFile, StringComparison.OrdinalIgnoreCase)) return; // Project rename, without renaming the project file (C++ project for instance) } } finally { // Mark the sln file edited, so it shows up in Pending Changes/Commit if (!string.IsNullOrEmpty(SolutionFilename)) DocumentTracker.CheckDirty(SolutionFilename); data.Reload(); // Reload project name, etc. } }
/// <summary> /// Called when a file is removed from a project /// </summary> /// <param name="project">The project.</param> /// <param name="filename">The filename.</param> /// <param name="flags">The flags.</param> internal void OnProjectFileRemoved(IVsSccProject2 project, string filename, VSREMOVEFILEFLAGS flags) { SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; // Not managed by us data.RemovePath(filename); if (!IsActive) return; // Let the other SCC package manage it MarkDirty(filename); if (GitUpdatesDisabled || !StatusCache[filename].IsVersioned) return; // Don't bother using (GitSccContext git = new GitSccContext(Context)) { if (File.Exists(filename)) { // The file was only removed from the project. We should not touch it // Some projects delete the file before (C#) and some after (C++) calling OnProjectFileRemoved if (_delayedDelete == null) _delayedDelete = new List<string>(); if (!_delayedDelete.Contains(filename)) _delayedDelete.Add(filename); RegisterForSccCleanup(); return; } if (git.IsUnversioned(filename)) return; git.SafeDeleteFile(filename); } }
/// <summary> /// Gets the list of source controllable files in the specified project /// </summary> public static async Task<IList<string>> GetProjectFiles(IVsSccProject2 pscp2Project) { return await GetProjectFiles(pscp2Project, VSConstants.VSITEMID_ROOT); }
/// <summary> /// Called when a file is added to a project /// </summary> /// <param name="project">The project.</param> /// <param name="filename">The filename.</param> /// <param name="fileOrigin">The file origin.</param> /// <param name="flags">The flags.</param> internal void OnProjectFileAdded(IVsSccProject2 project, string filename, string fileOrigin, VSADDFILEFLAGS flags) { // First update the filemap SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; // Not managed by us data.AddPath(filename); if (!IsActive) return; // Let the other SCC package manage it }
internal void OnProjectBeforeUnload(IVsSccProject2 project, IVsHierarchy pStubHierarchy) { SccProjectData data; if (_projectMap.TryGetValue(project, out data)) { data.Unloading = true; Monitor.ScheduleMonitor(data.GetAllFiles()); // Keep track of changes in files of unloaded project } }
/// <summary> /// Called when a directory is removed from a project /// </summary> /// <param name="project">The SCC project.</param> /// <param name="directoryname">The directoryname.</param> /// <param name="flags">The flags.</param> internal void OnProjectDirectoryRemoved(IVsSccProject2 project, string directoryname, VSREMOVEDIRECTORYFLAGS flags) { SccProjectData data; if (!_projectMap.TryGetValue(project, out data)) return; // Not managed by us // a directory can be added like a folder but with an ending '\' string dir = GitTools.GetNormalizedFullPath(directoryname); data.RemovePath(dir); if (!IsActive) return; RegisterForSccCleanup(); }
public int UnregisterSccProject(IVsSccProject2 pscp2Project) { return VSConstants.S_OK; }
public static bool IsSolutionSccProject(IVsSccProject2 project) { if (project == null) throw new ArgumentNullException("project"); return project is SolutionSccHelper; }
/// <summary> /// Called by ProjectDocumentTracker when a scc-capable project is loaded /// </summary> /// <param name="project"></param> internal void OnProjectLoaded(IVsSccProject2 project) { if (!_projectMap.ContainsKey(project)) _projectMap.Add(project, new SccProjectData(Context, project)); }
/// <summary> /// Called by projects registered with the source control portion of the environment before they are closed. /// </summary> /// <param name="pscp2Project">The PSCP2 project.</param> /// <returns></returns> public int UnregisterSccProject(IVsSccProject2 pscp2Project) { SccProjectData data; if (_projectMap.TryGetValue(pscp2Project, out data)) { data.IsRegistered = false; } return VSConstants.S_OK; }
public int RegisterSccProject(IVsSccProject2 pscp2Project, string pszSccProjectName, string pszSccAuxPath, string pszSccLocalPath, string pszProvider) { return VSConstants.S_OK; }
public async Task AddProject(IVsSccProject2 project) { if (!_projects.Contains(project) && project != null) { _projects.Add(project); } var files = await SolutionExtensions.GetProjectFiles(project); foreach (var file in files) { AddFileToList(file, project); } }
//[CLSCompliant(false)] static bool GetSccFiles(IVsHierarchy hierarchy, IVsSccProject2 sccProject, uint id, out string[] files, bool includeSpecial, bool includeNoScc, IDictionary<string, uint> map) { int[] flags; files = null; if (!GetSccFiles(hierarchy, sccProject, id, out files, out flags, includeNoScc, map)) return false; else if (flags == null || sccProject == null || !includeSpecial) return true; int n = Math.Min(files.Length, flags.Length); List<string> allFiles = new List<string>(files); for (int i = 0; i < n; i++) { if (0 != (flags[i] & (int)tagVsSccFilesFlags.SFF_HasSpecialFiles)) { CALPOLESTR[] str = new CALPOLESTR[1]; CADWORD[] dw = new CADWORD[1]; if (ErrorHandler.Succeeded(sccProject.GetSccSpecialFiles(id, allFiles[i], str, dw))) { files = GetFileNamesFromOleBuffer(str, true); GetFlagsFromOleBuffer(dw, true); // Free the flags (No need to parse at this time) if (files != null && files.Length > 0) allFiles.AddRange(files); } } } files = allFiles.ToArray(); return true; }