internal static bool GetSccFiles(SelectionItem item, out string[] files, bool includeSpecial, bool includeNoScc, IDictionary <string, uint> map) { ThreadHelper.ThrowIfNotOnUIThread(); if (item == null) { throw new ArgumentNullException("item"); } if (GetSccFiles(item.Hierarchy, item.SccProject, item.Id, out files, includeSpecial, includeNoScc, map)) { // The managed package SDK for VS 2005 and VS2008 returns // new string[] { GetMkDocument() }; on the generic HierarchyNode // without checking if GetMkDocument returns a valid path // So: Unless the project itself overrides this method it might contain garbage // At least the BlackBerry add-in 1.0.1 has this issue, so we have to check int nEmpty = 0; foreach (string s in files) { if (!IsValidPath(s)) { nEmpty++; } } if (nEmpty == 0) { return(true); // No need to copy } string[] fls = new string[files.Length - nEmpty]; if (fls.Length > 0) { int n = 0; for (int i = 0; i < files.Length; i++) { string s = files[i]; if (!IsValidPath(s)) { continue; } fls[n++] = s; } } files = fls; return(true); } return(false); }
private bool RecurseInto(SelectionItem si, ProjectWalkDepth depth) { ThreadHelper.ThrowIfNotOnUIThread(); object value; if (VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID.VSHPROPID_HasEnumerationSideEffects, out value))) { if (value != null) { bool hasSideEffects = (bool)value; // Unless we are walking SCC projects, don't go deeper // because we don't want side effects! if (hasSideEffects) { if (depth == ProjectWalkDepth.AllDescendantsInHierarchy && IgnoreSideEffects(si.SccProject)) { return(true); } return(false); } } } if (si.SccProject == null && VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID2.VSHPROPID_ChildrenEnumerated, out value))) { if (value != null) { bool childrenEnumerated = (bool)value; if (!childrenEnumerated) { return(false); } } } return(true); }
/// <summary> /// Gets the list of files specified by the hierarchy (IVsSccProject2 or IVsHierarchy) /// </summary> /// <param name="hierarchy"></param> /// <param name="id"></param> /// <param name="depth"></param> /// <returns></returns> /// <remarks>The list might contain duplicates if files are included more than once</remarks> public IEnumerable <string> GetSccFiles(IVsHierarchy hierarchy, uint id, ProjectWalkDepth depth, IDictionary <string, uint> map) { ThreadHelper.ThrowIfNotOnUIThread(); // Note: This command is not cached like the other commands on this object! if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } SelectionItem si = new SelectionItem(hierarchy, id); string[] files; if (!SelectionUtils.GetSccFiles(si, out files, depth >= ProjectWalkDepth.SpecialFiles, IncludeNoScc(depth), map)) { yield break; } foreach (string file in files) { yield return(SvnTools.GetNormalizedFullPath(file)); } if (depth > ProjectWalkDepth.SpecialFiles) { Dictionary <SelectionItem, SelectionItem> previous = new Dictionary <SelectionItem, SelectionItem>(); previous.Add(si, si); foreach (SelectionItem item in GetDescendants(si, previous, depth)) { if (!SelectionUtils.GetSccFiles(item, out files, depth >= ProjectWalkDepth.SpecialFiles, depth != ProjectWalkDepth.AllDescendantsInHierarchy, map)) { continue; } foreach (string file in files) { yield return(SvnTools.GetNormalizedFullPath(file)); } } } }
/// <summary> /// Gets the descendants of a selection item; yielding for each result to allow delay loading /// </summary> /// <param name="si"></param> /// <param name="previous"></param> /// <returns></returns> private IEnumerable <SelectionItem> GetDescendants(SelectionItem si, Dictionary <SelectionItem, SelectionItem> previous, ProjectWalkDepth depth) { if (si == null) { throw new ArgumentNullException("si"); } // A hierarchy node can have 2 identities. We only need the inner one uint subId; IntPtr hierPtr; int hr; try { hr = si.Hierarchy.GetNestedHierarchy(si.Id, ref hierarchyId, out hierPtr, out subId); } catch (Exception e) { ExternalException ee = e as ExternalException; if (ee != null && !VSErr.Succeeded(ee.ErrorCode)) { hr = ee.ErrorCode; // Should have been returned instead } else if (e is NotImplementedException) { hr = VSErr.E_NOTIMPL; // From Microsoft.VisualStudio.PerformanceTools.DummyVsUIHierarchy.GetNestedHierarchy() } else { hr = VSErr.E_FAIL; } hierPtr = IntPtr.Zero; subId = VSItemId.Nil; } if (VSErr.Succeeded(hr) && hierPtr != IntPtr.Zero) { IVsHierarchy nestedHierarchy = Marshal.GetObjectForIUnknown(hierPtr) as IVsHierarchy; Marshal.Release(hierPtr); if (nestedHierarchy == null || (nestedHierarchy == MiscellaneousProject)) { yield break; } if (depth <= ProjectWalkDepth.AllDescendantsInHierarchy) { yield break; // Don't walk into sub-hierarchies } else { si = new SelectionItem(nestedHierarchy, subId); } } if (!previous.ContainsKey(si)) { previous.Add(si, si); yield return(si); } // Note: VS2005 and earlier have all projects on the top level; from VS2008+ projects are nested // We can ignore that as we would include the projects anyway if (!RecurseInto(si, depth)) { yield break; } object value; if (!VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID.VSHPROPID_FirstChild, out value))) { yield break; } uint childId = GetItemIdFromObject(value); while (childId != VSItemId.Nil) { SelectionItem i = new SelectionItem(si.Hierarchy, childId); foreach (SelectionItem ii in GetDescendants(i, previous, depth)) { yield return(ii); } if (!VSErr.Succeeded(si.Hierarchy.GetProperty(i.Id, (int)__VSHPROPID.VSHPROPID_NextSibling, out value))) { yield break; } childId = GetItemIdFromObject(value); } }