I am using the google cloud sdk which implements a provider to its storage service. Inside this provider, I can gci
and cd
around just fine, but when I want to cp
an object onto my local filesystem, hoping to emulate a download command like gcloud storage cp <bucket item> <local path>
, I get the error Copy-Item: Source and destination path did not resolve to the same provider.
I am thinking about trying to adapt this provider to support copying using google's .NET client libaries to make the remote call, but I am not sure PowerShell will allow me to do this.
I found the following issue that seems to imply it's an inherent limitation in the Copy-Item
cmdlet. Digging deeper, I found the file SessionStateContainer.cs throws the CopyItemSourceAndDestinationNotSameProvider
error in the CopyItem
internal method of the SessionStateInternal
class (line 4280 atm). (This error is resolved in SessionStateStrings.resx to the above error I was receiving).
I'm confused on how damning this is. When I Get-Command Copy-Item
, I see it's coming from a different dll, where Copy-Item
is defined in Navigation.cs. Here, there's no mention of any limitation on provider crossing.
Would implementing the CopyItem
method in a custom provider circumvent whatever the SessionStateInternal implementation is doing, so that I can wrap a remote call to download a file when using Copy-Item
on objects in this provider to my local filesystem, or am I just stuck with this limitation?
From what I understand, PowerShell's provider model:
Is based on providers providing uniform access to disparate data stores - such as the file-system, the registry, environment variables, ... - via a set of standard *-*Item
(e.g., Copy-Item
, Get-ChildItem
) cmdlets operating on custom PowerShell drives that model data store(s) of a given kind using a drive metaphor.
Does not support cross-provider operations, as implied by the error message you encountered: PowerShell expects a given call to a provider cmdlet such as Copy-Item
to target only one provider, for a provider-internal operation.
Separate providers model separate items (entities in their respective namespace), and converting between the item types of different providers isn't part of the provider model, yet it is what would be required to support copying items between different providers via Copy-Item
.
While this limitation may be less understandable in the case of a cloud provider that, like the file system, ultimate stores files, consider an example such as Copy-Item $PROFILE env:/
- what would the semantics of such an operation be, if it were permitted?
Hypothetically, you could write your own provider that combines the functionality of the Google provider and the file-system provider, which would then have to publish a new custom drive that, say, has two top-level containers (directories), one representing the cloud storage, and the other the local file-system(s).
Obviously, this would be a substantial undertaking that duplicates existing functionality, and doesn't seem like it's worth the effort.
The much simpler solution is to use the dedicated cmdlets for transferring files between the local file-system and the cloud offered by Google Cloud Tools for PowerShell (of which the Google Cloud PowerShell provider is a part), namely Read-GcsObject
(copy from the cloud to the local file-system) and Write-GcsObject
(copy to the cloud from the local file-system) - see the docs.