How do I get diffs of all the files in a pending Perforce changelist?
Asked Answered
N

9

42

I want to get diffs on files in a specific pending changelist. I wish I could do this:

p4 diff -c 999

Can someone help me string together some csh magic to make this happen?

Maybe take the output of p4 opened -c 999 and piping it to p4 diff?

Nitz answered 13/7, 2009 at 19:27 Comment(1)
Shelve the changes in the pending changelist, then run p4 describe -S -du 999Whomp
M
21

The easiest way is in p4v or p4win, but that's not what you were asking about.

Try this:

p4 opened -c 999 | awk 'BEGIN { FS = "#" } // { print "p4 diff " $1 }' | csh

You, of course, need to make sure that the sub shell has p4 in its path, and $P4CLIENT, etc... are all set up.

Moule answered 13/7, 2009 at 19:56 Comment(4)
great that works! one question though, how can I replace the 999 with a variable to use in an alias. This is as far as I got but my understanding of alias parameters and escaping rules is limited. alias p4diffchange 'p4 opened -c $1 | awk 'BEGIN { FS = "#" } // { print "p4 diff " $2 }' | csh';Nitz
Don't use an alias, put it in a shell script and use the script's positional parameters.Moule
What a pain! Why doesn't Perforce support displaying the diffs of a pending changelist with p4 describe?Affable
Note that this won't work for added or deleted files.Constantan
W
29

Shelve the changes in the pending changelist, then run

p4 describe -S -du 999
Whomp answered 7/11, 2012 at 23:57 Comment(4)
Hadn't heard of shelving before. Tried this and it worked a treat.Holtorf
This works, but it ought to be possible without having to shelve anything. Perforce need to do usability testing.Inclose
Also, there's no way to apply the resulting patch file. It's incompatible with the unix patch command "Only garbage was found in the patch input", and there isn't any special p4 patch command as you might expect.Inclose
"Perforce need to do usability testing." - Waiting for it to die off completely is more of a hopeful prospect at this point.Drafty
M
21

The easiest way is in p4v or p4win, but that's not what you were asking about.

Try this:

p4 opened -c 999 | awk 'BEGIN { FS = "#" } // { print "p4 diff " $1 }' | csh

You, of course, need to make sure that the sub shell has p4 in its path, and $P4CLIENT, etc... are all set up.

Moule answered 13/7, 2009 at 19:56 Comment(4)
great that works! one question though, how can I replace the 999 with a variable to use in an alias. This is as far as I got but my understanding of alias parameters and escaping rules is limited. alias p4diffchange 'p4 opened -c $1 | awk 'BEGIN { FS = "#" } // { print "p4 diff " $2 }' | csh';Nitz
Don't use an alias, put it in a shell script and use the script's positional parameters.Moule
What a pain! Why doesn't Perforce support displaying the diffs of a pending changelist with p4 describe?Affable
Note that this won't work for added or deleted files.Constantan
S
19

Solution

p4 opened -c 999 | sed -e 's/#.*//' | p4 -x - diff

Explanation

p4 -x gives you xargs like ability without having to use xargs. From p4 help utils:

The -x flag instructs p4 to read arguments, one per line, from the specified file. If you specify '-', standard input is read.

So you can almost just "take the output of p4 opened -c 999 and pipe it to p4 diff" as suggested in the question. The one tricky part is that the output of p4 opened contains revision numbers and explanatory text after the name of each open file e.g.

//depot/example#123 - edit change 999 (text) by day@office
//depot/new-example#1 - add change 999 (text) by day@office

But we can run this through a simple sed -e 's/#.*//' to strip off everything from the # onwards to leave just the paths:

//depot/example
//depot/new-example

which can then be consumed from standard input and fed to p4 diff thanks to p4 -x -.

If you have # in the names of any files then you'll need to get more clever with the sed command. And see a psychiatrist.

Surah answered 7/9, 2012 at 16:36 Comment(2)
jwd: That's true, but I don't think any of the other solutions work for added files either... Trouble is that p4 diff newfile itself will just say //depot/newfile - file(s) not opened for edit. Not very helpful.Surah
This works nicely with Kaleidoscope, my preferred $P4DIFF tool.Affable
D
10

p4 describe 999 | grep '#' | cut -d"#" -f1|cut -d" " -f2 | xargs p4 diff

Doerr answered 13/10, 2011 at 13:31 Comment(3)
This does not work for a pending changelist, as far as I can tell.Conscientious
It does work for me for a pending changelist in a very smooth fashion. I even created an alias for that long line of pipes. Thanks!Send
Note that this does not work for added or deleted files.Constantan
B
6

You can use shell script like this:

#!/bin/sh

list=`p4 opened -c $1 | cut -d# -f1`

for file in $list ;
do
  p4 diff -dwbu $file
done

call it with changelist number and you'll get patch in stdout.

Bookcase answered 4/11, 2010 at 22:43 Comment(1)
Is it possible to create something similar in windows batch file? Thank youOssifrage
T
1

I used a similar approach as Mark, but I used Perl instead of Awk, and a shell function (in zsh):

p4dc() { p4 opened -c $* | perl -ne 's/#.*//; system("p4", "diff", $_)' }

Note that you can provide a file path too, in addition to just the changelist name/number:

p4dc default | less
p4dc default ... | less
Tjaden answered 20/5, 2011 at 21:24 Comment(0)
S
1

For a one-liner that works from the Windows cmd shell, try this:

for /f "usebackq delims=#" %F in (`p4 opened -c 999`) do @p4 diff %F

To do this in a batch file you need to use %%F instead of just %F.

Note that some of the solution above will work under Windows if you have installed a unix-like utilities package such as cygwin or unixutils, but this one-liner has no external dependencies.

Ser answered 8/6, 2018 at 21:33 Comment(0)
O
0

The above answers your question but, if tile is read as diffing a directory on a change list it can be answered with the following:

p4 filelog ... | awk '
BEGIN {FS="[ /]";tc=999}
/^\/\// {fn=$NF;o=1;if (system("test -w " fn)) h=0; else h=""}
/^\.\.\.\ \#/ {if (h==0) h=$2;
  if ($4<=tc && o==1) {print "p4 diff -db -dw " fn h " " fn $2 " ;#"  $4;o=0}}' \
| sh

This will diff all the files in the directory against the changelist 999 it uses the "have" version if it has be checked out otherwise it uses the latest version.

this was tested with GNU Awk 3.1.3

Odell answered 2/4, 2010 at 5:33 Comment(0)
G
0

For Unshelved Changes( Changes still not in depot)

p4 opened -c 999 | awk 'BEGIN { FS = "#" } // { print "p4 diff " $1 }' | bash

For Shelved Changes( Changes that in depot ( p4 shelve -c 999)

p4 describe -S -du3 -O 999
Garotte answered 2/6, 2020 at 18:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.