Exemple #1
0
        Collection <string> BuiltInGlobbing(CmdletProvider provider, string path, ProviderRuntime runtime)
        {
            var containerProvider = CmdletProvider.As <ContainerCmdletProvider>(provider);
            var ciIntrinsics      = new ChildItemCmdletProviderIntrinsics(_sessionState);
            // first we split the path into globbable components and put them on a stack to work with
            var componentStack = PathToStack(containerProvider, path, runtime);


            // we create a working list with partially globbed paths. each iteration will take all items from the
            // list and add the newly globbed part
            var workingPaths = new List <string>()
            {
                ""
            };

            while (componentStack.Count > 0)
            {
                var partialPaths = new List <string>(workingPaths);
                workingPaths.Clear();
                var globComp = componentStack.Pop();
                // check if the current stack component has wildcards. If not, simply append it to all partialPaths
                // and add to workingPaths
                if (!WildcardPattern.ContainsWildcardCharacters(globComp))
                {
                    workingPaths.AddRange(from p in partialPaths select Path.Combine(containerProvider, p, globComp, runtime));
                    continue;
                }

                // otherwise get all childnames, check wildcard and combine the paths
                var globWC = new WildcardPattern(globComp, WildcardOptions.IgnoreCase);
                foreach (var partPath in partialPaths)
                {
                    if (!containerProvider.ItemExists(partPath, runtime) ||
                        !containerProvider.HasChildItems(partPath, runtime))
                    {
                        // TODO: throw an error if there was no globbing already performed (then the first part of
                        // the path already did not exists as in a pattern like "/home/notExisting/*.txt"
                        continue;
                    }
                    // TODO: verify if we should only consider matching containers or all. maybe the filter won't
                    // apply to partial parts and we need to consider all
                    var childNames = ciIntrinsics.GetValidChildNames(containerProvider, partPath,
                                                                     ReturnContainers.ReturnMatchingContainers, runtime);
                    // TODO: check if Include/Exclude also match partial parts, but i guess only complete ones
                    // add all combined path to the workingPaths for the next stack globbing iteration
                    workingPaths.AddRange(from c in childNames
                                          where globWC.IsMatch(c)
                                          select Path.Combine(containerProvider, partPath, c, runtime));
                }
            }
            // now filter the working paths by include/exlude. last flag is false or we wouldn't be globbing
            var filter       = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, false);
            var globbedPaths = from p in workingPaths where filter.Accepts(p) select p;

            return(new Collection <string>(globbedPaths.ToList()));
        }
Exemple #2
0
        internal Collection<string> GetGlobbedProviderPaths(string path, ProviderRuntime runtime, bool itemMustExist,
                                                            out CmdletProvider provider)
        {
            var results = new Collection<string>();
            ProviderInfo providerInfo;

            // get internal path, resolve home path and set provider info and drive info (if resolved)
            path = GetProviderSpecificPath(path, runtime, out providerInfo);
            provider = _sessionState.Provider.GetInstance(providerInfo);

            if (!ShouldGlob(path, runtime))
            {
                // Although even ItemCmdletProvider supports ItemExists, PS doesn't seem
                // to throw errors when resolving paths with ItemProviders, only for ContainerProviders or higher
                // this behavior can be seen in the tests
                var containerProvider = provider as ContainerCmdletProvider;
                if (itemMustExist && containerProvider != null && !containerProvider.ItemExists(path, runtime))
                {
                    var msg = String.Format("An item with path {0} doesn't exist", path);
                    runtime.WriteError(new ItemNotFoundException(msg).ErrorRecord);
                    return results;
                }
                results.Add(path);
                return results;
            }

            if (providerInfo.Capabilities.HasFlag(ProviderCapabilities.ExpandWildcards))
            {
                var filter = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, runtime.IgnoreFiltersForGlobbing);
                foreach (var expanded in CmdletProvider.As<ItemCmdletProvider>(provider).ExpandPath(path, runtime))
                {
                    if (filter.Accepts(expanded))
                    {
                        results.Add(expanded);
                    }
                }
            }
            else
            {
                results = BuiltInGlobbing(provider, path, runtime);
            }

            return results;
        }
Exemple #3
0
        internal Collection <string> GetGlobbedProviderPaths(string path, ProviderRuntime runtime, bool itemMustExist,
                                                             out CmdletProvider provider)
        {
            var          results = new Collection <string>();
            ProviderInfo providerInfo;

            // get internal path, resolve home path and set provider info and drive info (if resolved)
            path     = GetProviderSpecificPath(path, runtime, out providerInfo);
            provider = _sessionState.Provider.GetInstance(providerInfo);

            if (!ShouldGlob(path, runtime))
            {
                // Although even ItemCmdletProvider supports ItemExists, PS doesn't seem
                // to throw errors when resolving paths with ItemProviders, only for ContainerProviders or higher
                // this behavior can be seen in the tests
                var containerProvider = provider as ContainerCmdletProvider;
                if (itemMustExist && containerProvider != null && !containerProvider.ItemExists(path, runtime))
                {
                    var msg = String.Format("An item with path {0} doesn't exist", path);
                    runtime.WriteError(new ItemNotFoundException(msg).ErrorRecord);
                    return(results);
                }
                results.Add(path);
                return(results);
            }

            if (providerInfo.Capabilities.HasFlag(ProviderCapabilities.ExpandWildcards))
            {
                var filter = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, runtime.IgnoreFiltersForGlobbing);
                foreach (var expanded in CmdletProvider.As <ItemCmdletProvider>(provider).ExpandPath(path, runtime))
                {
                    if (filter.Accepts(expanded))
                    {
                        results.Add(expanded);
                    }
                }
            }
            else
            {
                results = BuiltInGlobbing(provider, path, runtime);
            }

            return(results);
        }
Exemple #4
0
        Collection<string> BuiltInGlobbing(CmdletProvider provider, string path, ProviderRuntime runtime)
        {
            var containerProvider = CmdletProvider.As<ContainerCmdletProvider>(provider);
            var ciIntrinsics = new ChildItemCmdletProviderIntrinsics(_sessionState);
            // first we split the path into globbable components and put them on a stack to work with
            var componentStack = PathToStack(containerProvider, path, runtime);


            // we create a working list with partially globbed paths. each iteration will take all items from the
            // list and add the newly globbed part
            var workingPaths = new List<string>() { "" };
            while (componentStack.Count > 0)
            {
                var partialPaths = new List<string>(workingPaths);
                workingPaths.Clear();
                var globComp = componentStack.Pop();
                // check if the current stack component has wildcards. If not, simply append it to all partialPaths
                // and add to workingPaths
                if (!WildcardPattern.ContainsWildcardCharacters(globComp))
                {
                    workingPaths.AddRange(from p in partialPaths select Path.Combine(containerProvider, p, globComp, runtime));
                    continue;
                }

                // otherwise get all childnames, check wildcard and combine the paths
                var globWC = new WildcardPattern(globComp, WildcardOptions.IgnoreCase);
                foreach (var partPath in partialPaths)
                {
                    if (!containerProvider.ItemExists(partPath, runtime) ||
                        !containerProvider.HasChildItems(partPath, runtime))
                    {
                        // TODO: throw an error if there was no globbing already performed (then the first part of
                        // the path already did not exists as in a pattern like "/home/notExisting/*.txt"
                        continue;
                    }
                    // TODO: verify if we should only consider matching containers or all. maybe the filter won't
                    // apply to partial parts and we need to consider all
                    var childNames = ciIntrinsics.GetValidChildNames(containerProvider, partPath,
                                         ReturnContainers.ReturnMatchingContainers, runtime);
                    // TODO: check if Include/Exclude also match partial parts, but i guess only complete ones
                    // add all combined path to the workingPaths for the next stack globbing iteration
                    workingPaths.AddRange(from c in childNames
                                          where globWC.IsMatch(c)
                                          select Path.Combine(containerProvider, partPath, c, runtime));
                }
            }
            // now filter the working paths by include/exlude. last flag is false or we wouldn't be globbing
            var filter = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, false);
            var globbedPaths = from p in workingPaths where filter.Accepts(p) select p;
            return new Collection<string>(globbedPaths.ToList());
        }
        // actual work with callid the providers

        internal void Get(string[] paths, bool recurse, ProviderRuntime runtime)
        {
            // the include/exclude filters apply to the results, not to the globbing process. Make this sure
            runtime.IgnoreFiltersForGlobbing = true;

            // globbing is here a little more complicated, so we do it "manually" (without GlobAndInvoke)
            foreach (var curPath in paths)
            {
                var path = curPath;
                // if the path won't be globbed or filtered, we will directly list it's child
                var listChildsWithoutRecursion = !Globber.ShouldGlob(path, runtime) && !runtime.HasFilters();

                // the Path might be a mixture of a path and an include filter
                bool clearIncludeFilter;
                path = SplitFilterFromPath(path, recurse, runtime, out clearIncludeFilter);

                // now perform the actual globbing
                CmdletProvider provider;
                var globbed = Globber.GetGlobbedProviderPaths(path, runtime, out provider);
                var containerProvider = CmdletProvider.As<ContainerCmdletProvider>(provider);
                var filter = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, false);

                foreach (var globPath in globbed)
                {
                    try
                    {
                        // if we need to actively filter that stuff, we have to handle the recursion manually
                        if (!filter.CanBeIgnored)
                        {
                            ManuallyGetChildItems(containerProvider, globPath, recurse, filter, runtime);
                            return;
                        }
                        // otherwise just get the child items / the item directly
                        if (recurse || listChildsWithoutRecursion)
                        {
                            GetItemOrChildItems(containerProvider, globPath, recurse, runtime);
                            return;
                        }
                        // no recursion and globbing was performed: get the item, not the child items
                        containerProvider.GetItem(globPath, runtime);
                    }
                    catch (Exception e)
                    {
                        HandleCmdletProviderInvocationException(e);
                    }
                }
                // clean up the include filter of the runtime for the next item, if we split a filter from the path
                if (clearIncludeFilter)
                {
                    runtime.Include.Clear();
                }
            }
        }
 private void ManuallyGetChildNames(ContainerCmdletProvider provider, string providerPath, string relativePath,
     ReturnContainers returnContainers, bool recurse, IncludeExcludeFilter filter, ProviderRuntime runtime)
 {
     // Affected by #trailingSeparatorAmbiguity
     // Sometimes, PS removes or appends a trailing slash to the providerPath
     // E.g. when the recurse == true, there is a trailing slash, but not when recurse == false.
     // As it calls the method with the slash being appended and not appended, PS doesn't seem to make
     // promises to the provider implementation whether or not the path has a trailing slash
     var childNames = GetValidChildNames(provider, providerPath, returnContainers, runtime);
     foreach (var childName in childNames)
     {
         // add the child only if the filter accepts it
         if (!filter.Accepts(childName))
         {
             continue;
         }
         var path = Path.Combine(provider, relativePath, childName, runtime);
         runtime.WriteObject(path);
     }
     // check if we need to handle this recursively
     if (!recurse)
     {
         return;
     }
     // okay, we should use recursion, so get all child containers and call this function again
     childNames = GetValidChildNames(provider, providerPath, ReturnContainers.ReturnAllContainers, runtime);
     foreach (var childName in childNames)
     {
         var providerChildPath = Path.Combine(provider, providerPath, childName, runtime);
         if (Item.IsContainer(providerChildPath, runtime))
         {
             // recursive call wirth child's provider path and relative path
             var relativeChildPath = Path.Combine(provider, relativePath, childName, runtime);
             ManuallyGetChildNames(provider, providerChildPath, relativeChildPath, returnContainers,
                 true, filter, runtime);
         }
     }
 }
 private void ManuallyGetChildItemsFromContainer(ContainerCmdletProvider provider, string path, bool recurse, 
                                                 IncludeExcludeFilter filter, ProviderRuntime runtime)
 {
     // we deal with a container: get all child items (all containers if we recurse)
     Dictionary<string, bool> matches = null;
     // When a provider specific filter is set, and we need to recurse, we need to check recurse into all
     // containers, but just get those that match the internal filter. Therefore we construct a lookup dict.
     // Looking up in a dictionary whether or not the itemis a match should be faster than using a list
     // If there is no filter, then ReturnAllContainers and ReturnMatchingContainers don't differ
     if (!String.IsNullOrEmpty(runtime.Filter))
     {
         matches = GetValidChildNames(provider, path, ReturnContainers.ReturnMatchingContainers,
                                      runtime).ToDictionary(c => c, c => true);
     }
     var childNames = GetValidChildNames(provider, path, ReturnContainers.ReturnAllContainers, runtime);
     foreach (var childName in childNames)
     {
         var childPath = Path.Combine(provider, path, childName, runtime);
         // if the filter accepts the child (leaf or container) and it's potentially a filter match, get it
         if (filter.Accepts(childName) && (matches == null || matches.ContainsKey(childName)))
         {
             provider.GetItem(childPath, runtime);
         }
         // if we need to recurse and deal with a container, dive into it
         if (recurse && Item.IsContainer(childPath, runtime))
         {
             ManuallyGetChildItemsFromContainer(provider, childPath, true, filter, runtime);
         }
     }
 }
 private void ManuallyGetChildItems(ContainerCmdletProvider provider, string path, bool recurse, 
                                    IncludeExcludeFilter filter, ProviderRuntime runtime)
 {
     // recursively get child names of containers or just the current child if the filter accepts it
     if (recurse && Item.IsContainer(path, runtime))
     {
         ManuallyGetChildItemsFromContainer(provider, path, recurse, filter, runtime);
         return;
     }
     var childName = Path.ParseChildName(provider, path, runtime);
     if (filter.Accepts(childName))
     {
         provider.GetItem(path, runtime);
     }
 }
        internal void GetNames(string[] path, ReturnContainers returnContainers, bool recurse, ProviderRuntime runtime)
        {
            // the include/exclude filters apply to the results, not to the globbing process. Make this sure
            runtime.IgnoreFiltersForGlobbing = true;
            // compile here, not in every recursive iteration
            var filter = new IncludeExcludeFilter(runtime.Include, runtime.Exclude, false);

            // do the globbing manually, because the behavior depends on it...
            foreach (var p in path)
            {
                CmdletProvider provider;
                var doGlob = Globber.ShouldGlob(p, runtime);
                // even if we don't actually glob, the next method will return the resolved path & provider
                var resolved = Globber.GetGlobbedProviderPaths(p, runtime, out provider);
                var contProvider = CmdletProvider.As<ContainerCmdletProvider>(provider);
                foreach (var curPath in resolved)
                {
                    if (!doGlob && filter.CanBeIgnored && !recurse)
                    {
                        contProvider.GetChildNames(curPath, returnContainers, runtime);
                        continue;
                    }
                    if ((recurse || !doGlob) && Item.IsContainer(contProvider, curPath, runtime))
                    {
                        ManuallyGetChildNames(contProvider, curPath, "", returnContainers, recurse, filter, runtime);
                        continue;
                    }
                    var cn = Path.ParseChildName(contProvider, curPath, runtime);
                    if (filter.Accepts(cn))
                    {
                        runtime.WriteObject(cn);
                    }
                }
            }
        }