Reputation: 575
I read one other post here that I can download a file from the Perforce depot into a local disk without a client workspace. To extend that further, I need to download all files (text & binary) from a depot dir into my local disk. Is this the correct p4 command to do that?
p4 print //depot/dir1/...
I have a few questions:
I'm using the p4api.net library. Will this code do it?
public void GetFiles(string DepotFilePath)
{
P4Command cmd = new P4Command( _repository, "print", true,
String.Format( "{0}/...", DepotFilePath ));
results = cmd.Run();
if (results.Success)
{
//do something here
}
}
I'm not sure where in the local disk it will dump the files into?
Thank you for your help in advance.
Upvotes: 9
Views: 6921
Reputation: 71424
Simple solution requiring no platform-specific scripting tools:
p4 client -df TEMP_CLIENT
p4 -c TEMP_CLIENT --field View="//depot/dir1/... //TEMP_CLIENT/..." client -o | p4 client -i
p4 -c TEMP_CLIENT sync -p
p4 client -d TEMP_CLIENT
This will download all files/directories from //depot/dir1
into your current directory. If you want to specify a different directory, add --field "Root=C:\Some Path"
to the first command in the same spot where the View
is specified.
Note that the -f
flag is necessary for the p4 client -d
if it has opened files or any other metadata that's potentially dangerous to delete, but it does require admin
permission. If you don't have admin permission, this process will still work fine without the -f
flag, as long as nobody else sabotages it by creating a client called TEMP_CLIENT
and leaving files open on it.
If you're trying to download the contents of a stream rather than a depot path, the stream automatically defines the View
for you when you create a client with the -S
flag:
p4 client -df TEMP_CLIENT
p4 -c TEMP_CLIENT client -S //depot/streamname -o | p4 client -i
p4 -c TEMP_CLIENT sync -p
p4 client -d TEMP_CLIENT
Upvotes: 6
Reputation: 434
Latest Perforce already supports it natively:
https://www.perforce.com/manuals/cmdref/Content/CmdRef/p4_print.html#p4_print
Upvotes: 2
Reputation: 3677
So I've spent some time to get this to work under different scenarios in bash, and even though it is not dotnet specific I thought I'd share my results, as the concepts are universal.
You have two options to get files from remote:
# p4 uses this global variable as client/workspace name by default.
# Alternatively, you can also use -c in every command.
P4CLIENT="TEMP_SCRIPT_CLIENT"
# mapping remote folder to relative workspace folder (recursive)
wokspaceMapping="//depot/dir1/... //$P4CLIENT/..."
p4 client -d $P4CLIENT # make sure the workspace does not exist already
# Creating a client on the console gives an editor popup to confirm the
# workspace specification, unless you provide a specification on stdin.
# You can however generate one to stdout, and pipe the result to stdin again.
p4 --field View="$wokspaceMapping" --field Root="/some/local/path" client -o |
p4 client -i
p4 sync -p # download all the files
p4 client -d $P4CLIENT # remove workspace when you are done.
p4 print
to print the content of each file as jhwist wrote suggested, so you don't need to define a workspace at all. The disadvantage is that you have to handle each file individually, and create any directories yourself.p4RemoteRoot="//depot/dir1"
# First, list files and strip output to file path
# because `p4 files` prints something like this:
# //depot/dir1/file1.txt#1 - add change 43444817 (text)
# //depot/dir1/folder/file2.txt#11 - edit change 43783713 (text)
files="$(p4 files $p4RemoteRoot/... | sed 's/\(.*\)#.*/\1/')"
for wsFile in $files; do
# construct the local path from the remote one
targetFile="$localPath/${wsFile#$p4RemoteRoot/}"
# create the parent dir if it doesn't exist. p4 files doesn't list directories
mkdir -p $(dirname $targetFile)
# print the file content from remote and write that to the local file.
p4 print -q $wsFile > $targetFile
done
Note: I couldn't find any documentation for the --field
argument, but it seems you can use everything from "Form Fields" as specified in the docs: https://www.perforce.com/manuals/v18.2/cmdref/Content/CmdRef/p4_client.html
Upvotes: 0
Reputation: 4776
For reference, here's a bash one liner that will do the manual procedure jhwist's answer:
for _file in $(p4 files //depot/dir/... | awk '{print $1}' | perl -ne '/(.*)#\d+$/ && print "$1\n"'); do p4 print -q $_file > /path/to/target/dir/$(basename $_file); done
The only bits you have to replace with the directories in question are //depot/dir
and /path/to/target/dir
. Note: the target directory has to already exist.
Pulling out what the for
loop is iterating over:
$(p4 files //depot/dir/... | awk '{print $1}' | perl -ne '/(.*)#\d+$/ && print "$1\n"')
Get list of files from perforce directory in question
First column of the output is depot location of file, so extract it with awk
Depot location has #revisionNumber
tacked on the end of it, so strip it off with perl
Upvotes: 1
Reputation:
p4 print
will output the content onto the standard output (see the excellent manual). Therefore, to answer your questions in order:
//depot/path/to/file#5 - edit change 430530 (text)
, followed by the content of that particular file.If you really don't want to create a client workspace for your task (why?), then you'd have to do something like the following:
p4 files
(manual)p4 print
for each filep4 print
to a file on the local disk, adhering to the directory structure in the depot.Upvotes: 3