views:

3187

answers:

3

Hi everyone,

I'd like to find files in ClearCase that are labeled with a specific label but that do not have any other labels set.

For example, if I have files labeled like this:

file1 LBL_A, LBL_B
file2 LBL_A

I'd like to have a query that gives me just file2 and not file1.

Is there a way to do this with cleartool find? If this is not possible to do with a single query, I'd also be happy for any ideas how to do this in several steps (I'll be calling cleartool from a perl script, so it will be easy to save lists of files temporarily and run further commands on them).

Thanks a lot in advance!

Jan

+2  A: 

Assuming LBL_A is the (only) label you want running

cleartool find /some/dir -version 'lbtype(LBL_A)' -print | xargs cleartool describe -fmt "%n: %l"

should give

file1: (LBL_A, LBL_B)
file2: (LBL_A)

as output which you then can check in your perl script or filter through sed -n 's/\(.*\): (LBL_A)/\1/p' (assuming no colons in filenames).

Update: As VonC correctly points out, the command above will fail for files with spaces in. To handle that run as:

cleartool find ... -print | tr '\012' '\000' | xargs -0 cleartool ....

which will translate newlines into ascii null and then have xargs use that as delimiter.

hlovdal
@hlovdal you did not miss anything (like I did). I just canceled the downvote and rewrite my post :)
VonC
@hlovdal I fix my post and propose another (simple) way to filter the result. Since your post follow is essentially correct: +1
VonC
Thanks, that's exactly what I need!
Jan
+1  A: 

hlovdal's answer illustrates that, in this case, you have to find more elements than you need, and then filter them (despite all the ClearCase find features).

Note:

 cleartool find . -type f -element 'lbtype_sub(LBL_A)' -print

could give you directly the elements (and not the version which may not be interesting in this case). You can find the version with -version and a format directive as explained below.

With the help of fmt_ccase, you can tailor the output to get precisely what your perl script will need to go on:

 cleartool find . -type f -element 'lbtype_sub(LBL_A)' -exec 'cleartool describe -fmt "%En %Cl\n" \"$CLEARCASE_XPN\"' | grep -v ","
  • -fmt "%En %l\n" will display the full path of the element (instead of the version: /a/b/myFile@@/main/myVersion) => /a/b/myFile'. the '\n` ensure one result per line.
  • -version and -fmt "%n %l\n" would display the version
  • \"$CLEARCASE_XPN\": the double quotes arount the extended path of the version found ensure a file with spaces in its name will still work.
  • grep -v ",": if there is any comma, that means "more than one label"
  • %Cl: avoid displaying the all list of labels. Anyway, if there are more than one, you are not interested!

So, for finding the exact version:

 cleartool find . -type f -version 'lbtype_sub(LBL_A)' -exec 'cleartool describe -fmt "%n %Cl\n" \"$CLEARCASE_XPN\"' | grep -v ","|awk '{sub(/ \(.*/,"");print}'

Note:
The above works with unix syntax. The windows syntax would be:

cleartool find . -type f -element "lbtype(LBL_A)" -exec "cleartool describe -fmt \"%n %Cl\n\" \"%CLEARCASE_XPN%\"" | grep -v "," | gawk "{gsub(/ \(.*,"");print}"

, which would list the version of files with only one (correct) label.

  • awk '{sub(/ \(.*/,"");print}' will transform "myFile@@/main/myVersion (LBL_A)" into "myFile@@/main/myVersion"
VonC
Eh, did I miss something? The question says "any other labels", you are only explicitly testing LBL_B.
hlovdal
@hlovdal You are correct, and and have rewritten my answer to actually respond to the OP ;)
VonC
thanks to you, too - because I need the version, hlovdal's version suits me better, but also the link to of fmtccase was very helpful!
Jan
A: 

You can do this directly without having to pipe:

cleartool find . -ver "lbtype(LBL_A) && !lbtype(LBL_B)" -print
Garen