Esempio n. 1
0
        private IEnumerable <IPathNode> GetNodeChildrenInternal(IProviderContext context)
        {
            //find the current parent node
            var item = this.ContainerNode;

            if (item == null || item.IsLeaf)
            {
                // WriteChildItem()/P2F can call us while 'dir -recurse' even if the node is set to leaflet.
                yield break;
            }

            // Set the ProviderContext as the DynamicParameters and Filter objects will be used in the
            // PowerShell module's GetChildItem().
            // If dynamic parameters are used, then SHiPS is not using cache.
            // ProviderContext has to be set right now because context.NeedRefresh uses it.
            item.SHiPSProviderContext.Set(context);

            // The item is the parent node from where we can find its child node list.
            // We will find child nodes from the cache if GetChildItem() has been called already and NeedRefresh is false.
            // Otherwise, we will execute the scriptblock and then add the returned nodes to item's child list
            if (item.UseCache && item.ItemNavigated && !context.NeedRefresh(item, _drive))
            {
                var list = item.Children.Values.SelectMany(each => each);

                foreach (var node in list)
                {
                    // Making sure to obey the StopProcessing.
                    if (context.Stopping)
                    {
                        yield break;
                    }
                    yield return(node);
                }
            }
            else
            {
                var script = Constants.ScriptBlockWithParam1.StringFormat(Constants.GetChildItem);
                var nodes  = PSScriptRunner.InvokeScriptBlockAndBuildTree(context, item, _drive, script, PSScriptRunner.ReportErrors)?.ToList();

                // Save the info of the node just visisted
                SHiPSProvider.LastVisisted.Set(context.Path, this, nodes);

                if (nodes == null || nodes.Count == 0)
                {
                    yield break;
                }

                foreach (var node in nodes)
                {
                    // Making sure to obey the StopProcessing.
                    if (context.Stopping)
                    {
                        yield break;
                    }
                    yield return(node);
                }
            }
        }
Esempio n. 2
0
        private IPathNode GetNodeObjectFromPath(IProviderContext context, ContainerNodeService parent, string pathName, bool force)
        {
            var parentNode = parent?.ContainerNode;

            if (parentNode == null)
            {
                return(null);
            }

            // Check if the node has been dir'ed
            // Here we do not need to add NeedRefresh check because:
            // For cd (set-location), there is no -force, i.e., NeedRefresh is always false. This means for cached cases,
            // a user needs to do 'dir -force' to get fresh data.
            // For dir case, path in ResolvePath() is pointing to the parent path, e.g., dir c:\foo\bar\baz.txt,
            // the path is poing to c:\foo\bar even if baz.txt just gets created. Thus ResolvePath() only needs to resolve
            // the parent path and the GetChildItem() will check NeedRefresh to get fresh data.
            if (!force && parentNode.UseCache && parentNode.ItemNavigated)
            {
                var nodes = parentNode.Children.Where(each => pathName.EqualsIgnoreCase(each.Key)).Select(item => item.Value)
                            .FirstOrDefault();

                if (nodes != null && nodes.Any())
                {
                    return(nodes.FirstOrDefault());
                }
                else
                {
                    // If a childitem exists and cached, but none of them matches what specified in the 'pathName',
                    // we will return null, because
                    //
                    // dir         --- Assuming displays a long list of child items. So user does
                    // dir a[tab]  --- a user wants to see any child items start with 'a'. This may be no child item starts with a.
                    //                 so we do not need to go out fetching again if cache misses.
                    //
                    // caveat:
                    // dir foobar  --- if a user expects foobar child item exists, and cache misses, SHiPS is not going out fetch
                    //                 automatically, unless -force
                    // By removing the else block, SHiPS will go out fetching for data if cache misses. But dir a[tab] will be slow.
                    return(null);
                }
            }

            var script   = Constants.ScriptBlockWithParam1.StringFormat(Constants.GetChildItem);
            var children = PSScriptRunner.InvokeScriptBlockAndBuildTree(context, parentNode, _drive, script, PSScriptRunner.ReportErrors)?.ToList();

            if (children == null)
            {
                return(null);
            }

            foreach (var node in children)
            {
                // Making sure to obey the StopProcessing.
                if (context.Stopping)
                {
                    return(null);
                }

                //add it to its child list
                if (node != null)
                {
                    if (pathName.EqualsIgnoreCase(node.Name))
                    {
                        return(node);
                    }
                }
            }
            return(null);
        }