41

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?

Daryl Spitzer
  • 143,156
  • 76
  • 154
  • 173
ack
  • 14,285
  • 22
  • 55
  • 73

9 Answers9

27

Shelve the changes in the pending changelist, then run

p4 describe -S -du 999
Alexander Bird
  • 38,679
  • 42
  • 124
  • 159
  • Hadn't heard of shelving before. Tried this and it worked a treat. – PeteUK Jun 12 '13 at 08:19
  • 9
    This works, but it ought to be possible without having to shelve anything. Perforce need to do usability testing. – Colonel Panic Oct 18 '16 at 13:23
  • 2
    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. – Colonel Panic Oct 18 '16 at 13:31
  • 1
    "Perforce need to do usability testing." - Waiting for it to die off completely is more of a hopeful prospect at this point. – Alex Jansen Sep 23 '22 at 03:18
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.

Mark
  • 6,108
  • 3
  • 34
  • 49
  • 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'; – ack Jul 14 '09 at 00:16
  • 5
    Don't use an alias, put it in a shell script and use the script's positional parameters. – Mark Jul 14 '09 at 02:00
  • 25
    What a pain! Why doesn't Perforce support displaying the diffs of a pending changelist with `p4 describe`? – Daryl Spitzer Dec 03 '11 at 01:23
  • Note that this won't work for added or deleted files. – jamesdlin Aug 04 '17 at 02:08
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.

Day
  • 9,465
  • 6
  • 57
  • 93
  • 1
    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. – Day Oct 16 '13 at 15:28
  • This works nicely with Kaleidoscope, my preferred $P4DIFF tool. – Daryl Spitzer Dec 16 '16 at 00:59
10

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

user17521
  • 3
  • 2
shadkam islam
  • 101
  • 1
  • 2
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.

voronaam
  • 111
  • 1
  • 5
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.

yoyo
  • 8,310
  • 4
  • 56
  • 50
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
Ken Williams
  • 22,756
  • 10
  • 85
  • 147
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

Frobbit
  • 1,652
  • 17
  • 30
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
Alok Prasad
  • 622
  • 7
  • 12