Context: Someone does some restructuring work on a large Perforce depot under active development, and p4 move
s files around while they are still being worked on. Everyone else needs to keep their pending changes, but move them to the new locations in the new directory structure.
Consider my pending changelist with adds, edits, deletes and moves of various files.
If another user submits a p4 move
of all those files into a sub-directory, while my changelist is still pending, how do I resolve so that the same changes are applied to the same files in their new location?
After the other user moves the files and I do a p4 sync
which makes the files in their new location in my workspace, p4 resolve
just says there are No file(s) to resolve
.
I have tried to do a p4 move path newdir/path
for every file in my change, this doesn't quite work:
-f
flag on p4 move
(without it you get //depot/newdir/path - is synced; use -f to force move
). OK.//depot/path - can't move (already opened for delete)
). BAD//depot/path
to //depot/newpath
, and the other change has moved //depot/path
to //depot/newdir/path
then I can p4 move newpath newdir/newpath
to pick up the "move/add" part of the change but I cannot p4 move path newdir/path
to also pick up the "move/delete" part of the change (same error as previous point). BAD.If bare p4 commands won't work, I'll have to bust out the bash-fu to move files and glue together the right commands. I need an automated solution, as there may be a large number of pending changes across a large number of users all affected by the move, and these all need resolving as easily as possible.
I've also considered adapting the Working Disconnected From The Perforce Server method to apply my changes in the new location, but this loses the "move" metadata and, more importantly, won't work if multiple people have to do the same thing as they will have to resolve with the changes made by me if I get in before them.
If you want to play along with a toy example, here are my reproducing test case steps:
# Get p4 client and server, install in path (~/bin for me)
cd ~/bin
wget http://www.perforce.com/downloads/perforce/r12.1/bin.linux26x86/p4
chmod +x p4
wget http://www.perforce.com/downloads/perforce/r12.1/bin.linux26x86/p4d
chmod +x p4d
# Start p4 server in a test area (server dumps files in CWD)
mkdir -p ~/p4test/server
cd ~/p4test/server
p4d&
sleep 3
export P4PORT=localhost:1666
unset P4CONFIG # In case you use elsewhere :)
# Create some default client specs and workspaces for them.
mkdir ../workspace1
cd ../workspace1
export P4CLIENT=client1
p4 client -o | p4 client -i
mkdir ../workspace2
cd ../workspace2
export P4CLIENT=client2
p4 client -o | p4 client -i
# Create files and commit initial depot from client1
cd ../workspace1
export P4CLIENT=client1
for i in 1 2 3 4; do echo "This is file $i" > file$i; done
p4 add file*
p4 submit -d 'Initial files'
# Now make some changes to the files. But do not submit - leave pending.
# Add
echo "New file 0" > file0
p4 add file0
# Edit
p4 edit file1
echo "Edited $(date)" >> file1
# Delete
p4 delete file2
# Move
p4 edit file3
p4 move file3 file3.1
# Pending changelist looks like this:
# p4 opened
#//depot/file0#1 - add default change (text)
#//depot/file1#1 - edit default change (text)
#//depot/file2#1 - delete default change (text)
#//depot/file3#1 - move/delete default change (text)
#//depot/file3.1#1 - move/add default change (text)
# Meanwhile, in client2, another user moves everything to a new dir
cd ../workspace2
export P4CLIENT=client2
p4 sync
p4 edit file*
p4 move ... main/...
p4 submit -d 'Move everything to new "main" directory'
# Now what happens in client1?
cd ../workspace1
export P4CLIENT=client1
p4 sync
# //depot/file4#1 - deleted as /home/day/p4test/workspace1/file4
# //depot/file1#1 - is opened for edit - not changed
# //depot/file2#1 - is opened for delete - not changed
# //depot/file3#1 - is opened for move/delete - not changed
# //depot/file3.1#1 - is opened for move/add - not changed
# //depot/main/file1#1 - added as /home/day/p4test/workspace1/main/file1
# //depot/main/file2#1 - added as /home/day/p4test/workspace1/main/file2
# //depot/main/file3#1 - added as /home/day/p4test/workspace1/main/file3
# //depot/main/file4#1 - added as /home/day/p4test/workspace1/main/file4
# day@office:~/p4test/workspace1$ tree
# .
# ├── file0
# ├── file1
# ├── file3.1
# └── main
# ├── file1
# ├── file2
# ├── file3
# └── file4
#
# 1 directory, 7 files
# Now ... how to resolve?
In theory, you should now be able to do this:
p4 move -f ... main/... # meld your opened files to their renamed files
p4 move -f main/file3.1 main/file3 # meld your renamed file to their renamed file
p4 revert '*' # revert your now-spurious pending deletes
p4 move main/file3 main/file3.1 # move their renamed file to the name you wanted
p4 resolve # merge their edits with your edits
But there seems to be a bug with that third 'p4 move', and it's dropping the pending resolve on main/file3.1 (fka main/file3).
However, it does seem to work right if you do it in this order:
p4 move -f ... main/...
p4 move -f main/file3.1 main/file3
p4 revert '*'
p4 resolve
p4 move main/file3 main/file3.1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With