perforce diff command: how to combine filtering arguments? - diff

Documentation says "To pass more than one option to the diff routine, group them together. For example: p4 diff -dub file"
While this might be working for "-d" option, it doesn't work for "-s".
> p4 diff -sa ...
file1
> p4 diff -se ...
file2
> p4 diff -sd ...
file3
> p4 diff -saed ...
file1
It seems to be taking only the first argument. Is it a bug in perforce or there is a way combine them?

Those options can't be combined. Trying to specify more than one should be reported as a usage error IMO.
For the most part they specify conditions that are mutually exclusive, so if you were able to combine all those filters ("display only files that are unopened AND opened AND ..."), you'd just get empty output. :)

Related

Generate Hg diff (or patch) that Only includes content for files modified by a revision/revset

Given a large codebase and two revisions or revsets (say, a local 'source' and a target) which may or may not share a recent parent and usually contain a large number of non-relevant file deltas;
How can diff output be generated to compare the changes only for files that are modified in the source revset itself?
(This should be the delta between the ancestry; but only for the files contained within the revset.)
Using hg diff -r target -r source shows all the changes in the ancestry, even for files not modified by the source sevision.
In addition, this should be done without any knowledge of the directory structure.
If I understand correctly, you want a diff between revs source and target, but you want to restrict it to the files that were modified in changeset source. You can do it in two steps (easily assembled into one with an alias or shell script):
List the files modified in source:
hg log -r source --template '{files}'
This just outputs a list of filenames.
Request a diff for these files:
hg diff -r target -r source $(hg log -r source --template '{files}')
Step 2 is a bash command with "command substitution" $(...), which inserts the output of step one. Other methods are possible.
From hg help diff
If only one revision is specified then that revision is compared to the working directory
i.e. you can try hg up $SOURCE; hg diff -r $TARGET

Diff between two branches in a client workspace

I have two branches in my local workspace. I need to take a diff between them and capture the filenames in a text file.
I looked into diff and diff2
p4 diff
gives the diff between a branch in the local client workspace and it's counterpart on the server
p4 diff2
can only be used to get the diff between two branches which are on the server.
By the way, if I do "Diff Against" on the two branches on the server through p4v client, I am able to see the list of the diff files. But I don't see anything there which would import the filesnames to a text file.
But if I try p4 diff2 through the command line on the two branches on the server, i get - protected namespace - access denied.
Any pointers will be much appreciated.
If you p4 sync both branches to the required version first, then all the files are on your disk and available to the regular diff command (not a p4 sub-command) - see the man page.
For example:
diff -qr branch1 branch2
Might give you output like:
Files branch1/newfile and branch2/newfile differ
Only in branch1: newfile2

Perforce: Find source changelist for a branch

Short version:
After branching in P4, how can I find out the "source" changelist of the branch?
Long version:
Let's say I have a main branch of my project at
//project/main/...
The latest changelist submitted here is #123, when I decide to create a branch for release 1.0 in
//project/1.0/...
From P4V, a new changelist is created (say #130), resolved and submitted.
From the CLI, it would look something like this:
p4 integrate -c 123 -o //project/main/... //project/1.0/...
p4 submit
Later, I look at the changelists under //project/1.0, and see the #130 changelist containing a lot of branched files.
How can I find out the changelist no. that this was originally branched from (that is, #123) ?
p4 changes will display a list of submitted changelists, optionally filtered to a specific path.
p4 changes //project/main/...
Change 123 ... 'Very last change.'
Change 122 ... 'Next-to-last change.'
Change 100 ... 'Only two changes to go...'
...
No surprise there, but, as you've found, p4 changes is less helpful when you integrate all those changes in a single change:
p4 changes //project/1.0/...
Change 130 ... 'Integrated everything from main.'
The trick is to use the -i option which includes any changelists integrated into the specified files.
p4 changes -i //project/1.0/...
Change 130 ... 'Integrated everything from main.'
Change 123 ... 'Very last change.'
Change 122 ... 'Next-to-last change.'
Change 100 ... 'Only two changes to go...'
...
To get exactly what you want (123) you'll need to write a script which filters the output from p4 changes -i //project/1.0/... to remove any change listed by p4 changes //project/1.0/... (and then take the most recent remaining change).
(When exploring, I frequently also find the -m max option useful. This limits changes to the 'max' most recent. This helps your output not flow offscreen when there are many changes.)
I don't know of any simple command that performs what you would like to do. If you are willing to script a little bit and the command doesn't have to execute fast you could perhaps try to script something like the following for all branched files:
Find the source file/revision for a target file.
p4 filelog //project/1.1/foo.bar#1
//project/1.1/foo.bar
... #1 change 6416 branch on 2009/07/10 by foo#bar (text) 'Release 1.1'
... ... branch from //project/main/foo.bar#1,#2
Get the change list at which the source file/revision was submitted.
p4 fstat //project/main/foo.bar#2
... depotFile //project/main/foo.bar
... headAction edit
... headType text
... headTime 1201771167
... headRev 2
... headChange 5353
... headModTime 1201770971
Repeat for all files in branch and select the highest change no (headChange above), which should be the latest change submitted to the parent before branching for that specific file. You could get a complete listing of all branched files using e.g. "p4 files //project/1.0/...#1".
(or perhaps take the easy way out and ask Perforce support)
Since none of the answers thus far provide the code for finding the source or root changelist of a branch, I thought I'd provide a one-liner to do just that. This approach is based on #Cwan's suggestion, and will print the "parent" changelist from which the branch was created. The FIRST_BRANCH_CL argument needs to be replaced with the branch creation changelist (i.e. the first changelist submitted to the new branch). As a concrete example, replacing FIRST_BRANCH_CL with 130 from the original question, this one-liner would output 123.
p4 describe -s FIRST_BRANCH_CL | perl -lne 'if(/^\.\.\. (.+#[0-9]+) .+$/) {print quotemeta $1}' | xargs p4 filelog -m1 | perl -lne 'if(/^\.\.\. \.\.\. branch from (.+#[0-9]+)/) {print quotemeta $1}' | xargs p4 fstat | perl -lne 'if(/^\.\.\. headChange (\d+)/) {$MaxCL=$1 if($1 > $MaxCL)} END {print $MaxCL}'
Short answer:
Use the Revision Graph in P4V is step back through time and investigate the integration history. Video on the Perforce website.
I have successfully used the revision graph on branches with thousands of files to track when an particular change was integrated into a branch. That is why I recommended it and linked to a training video as most people under-estimate it because they do not know how to use it.
Long answer:
... [Removed]
UPDATE: As the Revision Graph apparently is unfeasible, you can perhaps solve this using a process/policy, i.e., when you perform the integrate, add a note in the description "Branched # CL 123". We used this approach ourselves when integrating from a trunk to release lines.
If you use the history tab in p4v it will show you all changelists submitted against a branch, so look at this for
//project/1.0/...
once you have found the oldest submitted changelist, then on any one the files in that changelist view the Revision Graph for it, this will show you the branch that the file (and the rest of the files) were integrated from.
I'll see if I can come back with the p4 commands to do the same thing.
Updated Answer: I think this will work. Try this:
p4 interchanges from_branch to_branch
This will show unintegrated changes from your main branch to your release branch. I believe you can use the top changelist number minus 1 to find your source changelist. interchanges is an undocumented Perforce CLI feature. To find out more, type p4 help interchanges to find out more about this command.
Again, I think this will work. There may be some special cases where it will not, but it's my best guess to a tough and important problem.
"p4 integrated" worked for me. Look for "copy from" in the description

Perforce -- generate a diff including added files?

When I use "p4 diff", it ignores files that I have open for add. Is it possible to generate a diff that includes added files as well as changed files?
Considering the diff in Perforce compare the files in the client workspace to revisions in the depot, the short answer is "no".
There is no recorded history to compare to for the added file (not committed to the depot before a submit)
The longer answer would involve a script to complete the diff with the full content of the added files. (kind of like in this SO question)
This is a known missing feature of p4 diff that lots of tools dealing with Perforce have to work around.
The code review tool Reviewboard comes with the tool post-review. It is used to create diffs for a a codereview, but it will just do a diff if you want.
It's in python, you could pull out the diff section for your own use.
I wrote this to help me on cygwin:
#!/bin/bash
if [ $# -ne 1 ]; then
echo "usage: $0 <pathSpec>"
exit 1
fi
pathSpec=$1
doIt () {
p4 opened "$pathSpec" | egrep "#.* - add" | while read f; do
# figure out the workspace path
depotPath=${f%#*}
clientFileLine=$(p4 fstat "$depotPath" | grep clientFile)
workspacePathWin=${clientFileLine#... clientFile }
# diff output
echo ==== $depotPath#1 - $workspacePathWin ====
workspacePath=$(cygpath "$workspacePathWin")
lineCount=$(wc -l < "$workspacePath")
echo ## -0,0 +1,$lineCount ##
# the actual diff contents
sed -e 's/^/+/' "$workspacePath"
echo
done
}
doIt
I just worked around this issue and got my added files included in a Fisheye pre-commit review.
What I did was copy the edited files' diff hunk descriptor header. This includes one line which lists the depot and local paths - pretty straightforward - and another line with the range information, formatted as described here.
So, I added each appended each file's contents to the diff, each preceded by
==== //path/to/depot/file#1 - /path/to/workspace/file ====
## -1,1 +1,LEN ##
where LEN is the number of lines in the added file.
This worked for me; Your Mileage May Vary.
I just got this to work, branching off Aaron's answer. Instead of
==== //path/to/depot/file#1 - /path/to/workspace/file ====
I used
--- //path/to/file [TIMESTAMP GENERATED BY NORMAL DIFF]
+++ //path/to/file [TIMESTAMP GENERATED BY NORMAL DIFF]
## -1,1 +1,LEN ##
Then make sure to have a + at the beginning of each added line.
Just p4 print the added files (I know, that's not great) - but its definitely one way to go.

How to find untracked files in a Perforce tree? (analogue of svn status)

Anybody have a script or alias to find untracked (really: unadded) files in a Perforce tree?
EDIT: I updated the accepted answer on this one since it looks like P4V added support for this in the January 2009 release.
EDIT: Please use p4 status now. There is no need for jumping through hoops anymore. See #ColonelPanic's answer.
In the Jan 2009 version of P4V, you can right-click on any folder in your workspace tree and click "reconcile offline work..."
This will do a little processing then bring up a split-tree view of files that are not checked out but have differences from the depot version, or not checked in at all. There may even be a few other categories it brings up.
You can right-click on files in this view and check them out, add them, or even revert them.
It's a very handy tool that's saved my ass a few times.
EDIT: ah the question asked about scripts specifically, but I'll leave this answer here just in case.
On linux, or if you have gnu-tools installed on windows:
find . -type f -print0 | xargs -0 p4 fstat >/dev/null
This will show an error message for every unaccounted file. If you want to capture that output:
find . -type f -print0 | xargs -0 p4 fstat >/dev/null 2>mylogfile
Under Unix:
find -type f ! -name '*~' -print0| xargs -0 p4 fstat 2>&1|awk '/no such file/{print $1}'
This will print out a list of files that are not added in your client or the Perforce depot. I've used ! -name '*~' to exclude files ending with ~.
Ahh, one of the Perforce classics :) Yes, it really sucks that there is STILL no easy way for this built into the default commands.
The easiest way is to run a command to find all files under your clients root, and then attempt to add them to the depot. You'll end up with a changelist of all new files and existing files are ignored.
E.g dir /s /b /A-D | p4 -x - add
(use 'find . -type f -print' from a nix command line).
If you want a physical list (in the console or file) then you can pipe on the results of a diff (or add if you also want them in a changelist).
If you're running this within P4Win you can use $r to substitute the client root of the current workspace.
Is there an analogue of svn status or git status?
Yes, BUT.
As of Perforce version 2012.1, there's the command p4 status and in P4V 'reconcile offline work'. However, they're both very slow. To exclude irrelevant files you'll need to write a p4ignore.txt file per https://stackoverflow.com/a/13126496/284795
2021-07-16: THIS ANSWER MAY BE OBSOLETE.
I am reasonably sure that it was accurate in 2016, for whatever version of Perforce I was using them (which was not necessarily the most current). But it seems that this problem or design limitation has been remedied in subsequent releases of Perforce. I do not know what the stack overflow etiquette for this is -- should this answer be removed?
2016 ANSWER
I feel impelled to add an answer, since the accepted answer, and some of the others, have what I think is a significant problem: they do not understand the difference between a read-only query command, and a command that makes changes.
I don't expect any credit for this answer, but I hope that it will help others avoid wasting time and making mistakes by following the accepted but IMHO incorrect answer.
---+ BRIEF
Probably the most convenient way to find all untracked files in a perforce workspace is p4 reconcile -na.
-a says "give me files that are not in the repository, i.e. that should be added".
-n says "make no changes" - i.e. a dry-run. (Although the messages may say "opened for add", mentally you must interpret that as "would be opened for add if not -n")
Probably the most convenient way to find all local changes made while offline - not just files that might need to be added, but also files that might need to be deleted, or which have been changed without being opened for editing via p4 edit, is p4 reconcile -n.
Several answers provided scripts, often involving p4 fstat. While I have not verified all of those scripts, I often use similar scripts to make up for the deficiencies of perforce commands such as p4 reconcile -n - e.g. often I find that I want local paths rather than Perforce depot paths or workspace paths.
---+ WARNING
p4 status is NOT the counterpart to the status commands on other version control systems.
p4 status is NOT a read-only query. p4 status actually finds the same sort of changes that p4 reconcile does, and adds them to the repository. p4 status does not seem to have a -n dry-run option like p4 reconcile does.
If you do p4 status, look at the files and think "Oh, I don't need those", then you will have to p4 revert them if you want to continue editing in the same workspace. Or else the changes that p4 status added to your changeset will be checked in the next time.
There seems to be little or no reason to use p4 status rather than p4 reconcile -n, except for some details of local workspace vs depot pathname.
I can only imagine that whoever chose 'status' for a non-read-only command had limited command of the English language and other version control tools.
---+ P4V GUI
In the GUI p4v, the reconcile command finds local changes that may need to be added, deleted, or opened for editing. Fortunately it does not add them to a changelist by default; but you still may want to be careful to close the reconcile window after inspecting it, if you don't want to commit the changes.
Alternatively from P4Win, use the ""Local Files not in Depot" option on the left hand view panel.
I don't use P4V much, but I think the equivalent is to select "Hide Local Workspace Files" in the filter dropdown of the Workspace view tab.p4 help fstat
In P4V 2015.1 you'll find these options under the filter button like this:
I use the following in my tool that backs up any files in the workspace that differ from the repository (for Windows). It handles some odd cases that Perforce doesn't like much, like embedded blanks, stars, percents, and hashmarks:
dir /S /B /A-D | sed -e "s/%/%25/g" -e "s/#/%40/g" -e "s/#/%23/g" -e "s/\*/%2A/g" | p4 -x- have 1>NUL:
"dir /S /B /A-D" lists all files at or below this folder (/S) in "bare" format (/B) excluding directories (/A-D). The "sed" changes dangerous characters to their "%xx" form (a la HTML), and the "p4 have" command checks this list ("-x-") against the server discarding anything about files it actually locates in the repository ("1>NUL:"). The result is a bunch of lines like:
Z:\No_Backup\Workspaces\full\depot\Projects\Archerfish\Portal\Main\admin\html\images\nav\navxx_background.gif - file(s) not on client.
Et voilĂ !
Quick 'n Dirty: In p4v right-click on the folder in question and add all files underneath it to a new changelist. The changelist will now contain all files which are not currently part of the depot.
The following commands produce status-like output, but none is quite equivalent to svn status or git status, providing a one-line summary of the status of each file:
p4 status
p4 opened
p4 diff -ds
I don't have enough reputation points to comment, but Ross' solution also lists files that are open for add. You probably do not want to use his answer to clean your workspace.
The following uses p4 fstat (thanks Mark Harrison) instead of p4 have, and lists the files that aren't in the depot and aren't open for add.
dir /S /B /A-D | sed -e "s/%/%25/g" -e "s/#/%40/g" -e "s/#/%23/g" -e "s/\*/%2A/g" | p4 -x- fstat 2>&1 | sed -n -e "s/ - no such file[(]s[)]\.$//gp"
===Jac
Fast method, but little orthodox. If the codebase doesn't add new files / change view too often, you could create a local 'git' repository out of your checkout. From a clean perforce sync, git init, add and commit all files locally. Git status is fast and will show files not previously committed.
The p4 fstat command lets you test if a file exists in the workspace, combine with find to locate files to check as in the following Perl example:
// throw the output of p4 fstat to a 'output file'
// find:
// -type f :- only look at files,
// -print0 :- terminate strings with \0s to support filenames with spaces
// xargs:
// Groups its input into command lines,
// -0 :- read input strings terminated with \0s
// p4:
// fstat :- fetch workspace stat on files
my $status=system "(find . -type f -print0 | xargs -0 p4 fstat > /dev/null) >& $outputFile";
// read output file
open F1, $outputFile or die "$!\n";
// iterate over all the lines in F1
while (<F1>) {
// remove trailing whitespace
chomp $_;
// grep lines which has 'no such file' or 'not in client'
if($_ =~ m/no such file/ || $_ =~ m/not in client/){
// Remove the content after '-'
$_=~ s/-\s.*//g;
// below line is optional. Check ur output file for more clarity.
$_=~ s/^.\///g;
print "$_\n";
}
}
close F1;
Or you can use p4 reconcile -n -m ...
If it is 'opened for delete' then it has been removed from the workspace. Note that the above command is running in preview mode (-n).
I needed something that would work in either Linux, Mac or Windows. So I wrote a Python script for it. The basic idea is to iterate through files and execute p4 fstat on each. (of course ignoring dependencies and tmp folders)
You can find it here: https://gist.github.com/givanse/8c69f55f8243733702cf7bcb0e9290a9
This command can give you a list of files that needs to be added, edited or removed:
p4 status -aed ...
you can use them separately too
p4 status -a ...
p4 status -e ...
p4 status -d ...
In P4V, under the "View" menu item choose "Files in Folder" which brings up a new tab in the right pane.
To the far right of the tabs there is a little icon that brings up a window called "Files in Folder" with 2 icons.
Select the left icon that looks like a funnel and you will see several options. Choose "Show items not in Depot" and all the files in the folder will show up.
Then just right-click on the file you want to add and choose "Mark for Add...". You can verify it is there in the "Pending" tab.
Just submit as normal (Ctrl+S).