void CopyContainerToContainer(ContainerCmdletProvider provider, string srcPath, string destPath, bool recurse, CopyContainers copyContainers, ProviderRuntime runtime) { // the "usual" case: if we don't use recursion (empty container is copied) or we want to maintain the // original hierarchy if (!recurse || copyContainers.Equals(CopyContainers.CopyTargetContainer)) { provider.CopyItem(srcPath, destPath, recurse, runtime); return; } // Otherwise we want a flat-hierachy copy of a folder (because copyContainers is CopyChildrenOfTargetContainer) // Make sure recurse is set if (!recurse) { var error = new PSArgumentException("Cannot copy container to existing leaf", "CopyContainerItemToLeafError", ErrorCategory.InvalidArgument).ErrorRecord; runtime.WriteError(error); return; } // otherwise do the flat copy. To do this: get all child names (recursively) and invoke copying without recursion var childNames = ChildItem.GetNames(srcPath, ReturnContainers.ReturnMatchingContainers, true); foreach (var child in childNames) { var childPath = Path.Combine(provider, srcPath, child, runtime); provider.CopyItem(childPath, destPath, false, runtime); } }
internal void Copy(string[] path, string destinationPath, bool recurse, CopyContainers copyContainers, ProviderRuntime runtime) { ProviderInfo destinationProvider; var destRuntime = new ProviderRuntime(runtime); var destination = Globber.GetProviderSpecificPath(destinationPath, destRuntime, out destinationProvider); // make sure we don't use the version of IsContainer that globs, or we will have unnecessary provider callbacks var destProvider = destinationProvider.CreateInstance() as ContainerCmdletProvider; // it's okay to be null var destIsContainer = IsContainer(destProvider, destination, destRuntime); GlobAndInvoke <ContainerCmdletProvider>(path, runtime, (curPath, provider) => { if (!runtime.PSDriveInfo.Provider.Equals(destinationProvider)) { var msg = "The source cannot be copied to the destination, because they're not from the same provider"; var error = new PSArgumentException(msg, "CopyItemSourceAndDestinationNotSameProvider", ErrorCategory.InvalidArgument); runtime.WriteError(error.ErrorRecord); return; } // Affected by #trailingSeparatorAmbiguity // PS would make sure the trailing slash of curPath is removed // check if src is a container if (IsContainer(provider, curPath, runtime)) { // if we copy a container to another, invoke a special method for this if (destIsContainer) { CopyContainerToContainer(provider, curPath, destination, recurse, copyContainers, runtime); return; } // otherwise the destination doesn't exist or is a leaf. Copying a container to a leaf doesn't work if (Exists(destination, destRuntime)) { var error = new PSArgumentException("Cannot copy container to existing leaf", "CopyContainerItemToLeafError", ErrorCategory.InvalidArgument).ErrorRecord; runtime.WriteError(error); return; } // otherwise we just proceed as normal } // either leaf to leaf, leaf to container, or container to not-existing (i.e. copy the container) provider.CopyItem(curPath, destination, recurse, runtime); } ); }
internal void Move(string[] path, string destinationPath, ProviderRuntime runtime) { ProviderInfo destinationProvider; var destination = Globber.GetProviderSpecificPath(destinationPath, runtime, out destinationProvider); GlobAndInvoke <NavigationCmdletProvider>(path, runtime, (curPath, provider) => { // TODO: I think Powershell checks whether we are currently in the path we want to remove // (or a subpath). Check this and throw an error if it's true if (!runtime.PSDriveInfo.Provider.Equals(destinationProvider)) { var msg = "The source cannot be moved to the destination, because they're not from the same provider"; var error = new PSArgumentException(msg, "MoveItemSourceAndDestinationNotSameProvider", ErrorCategory.InvalidArgument); runtime.WriteError(error.ErrorRecord); return; } provider.MoveItem(curPath, destination, runtime); } ); }
public void WriteError(ErrorRecord errorRecord) { ProviderRuntime.WriteError(errorRecord); }