Warning, /sdk/kde-dev-scripts/cvscheck is written in an unsupported language. File is not indexed.
0001 #! /usr/bin/env perl 0002 0003 use POSIX qw(mktime ctime); 0004 use Time::Local qw( timegm ); 0005 0006 # Offline check for status of files in a checked-out 0007 # CVS module. 0008 # Artistic License, Dirk Mueller <mueller@kde.org> 2001-2003 0009 0010 # based on cvschanged by 0011 # Sirtaj Singh Kang <taj@kde.org> Nov 1998. 0012 0013 if ( defined $ARGV[0] && $ARGV[0] =~ /(?:-h|--help)/) { 0014 print "cvscheck (c) 2001-2003 Dirk Mueller <mueller\@kde.org>\n\nUsage:\n"; 0015 print " cvscheck [options] <dirs>\n\n"; 0016 print "Prints information about the status of your local CVS checkout without\n"; 0017 print "communicating with the server (therefore in speed only limited by your\n"; 0018 print "hard-disk throughput, much unlike cvs -n up).\n\n"; 0019 print "Every file is printed with a status character in front of its name:\n"; 0020 print "? foobar.c file is not known to CVS - maybe you should add it?\n"; 0021 print "M foobar.c file is for sure locally modified.\n"; 0022 print "m foobar.c file *might* have local changes (needs a diff with the server).\n"; 0023 print "C foobar.c file has a CVS conflict and therefore cannot be committed.\n"; 0024 print "U foobar.c file is in CVS but its somehow missing in your local checkout.\n"; 0025 print "T foobar.c file has an unusual sticky CVS tag.\n"; 0026 print "A foobar.c you cvs add'ed this file but did not yet commit.\n"; 0027 print "R foobar.c you cvs rm'ed this file but did not yet commit.\n"; 0028 0029 print <<EOF; 0030 0031 0032 Options: 0033 0034 -u | --unknown Show only unknown (?) files 0035 -m | --modified Show only modified (m/M) files 0036 --missing Show only missing (U) files 0037 -t | --tagged Show only tagged (T) files 0038 -a | --added Show only added (A) files 0039 -r | --removed Show only removed (R) files 0040 -c | --conflicts Show only conflict (C) files 0041 0042 If no option is given, it defaults to show all files and diagnostic messages. 0043 EOF 0044 exit; 0045 } 0046 0047 # default is HEAD 0048 $standardtag = ""; 0049 %defaulttag = (); 0050 @dirqueue = (); 0051 @merged = (); 0052 @uncommitted = (); 0053 @missing = (); 0054 @tagged = (); 0055 @removed = (); 0056 @unknown = (); 0057 @modified = (); 0058 @conflicts = (); 0059 0060 %months = ( 'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 0061 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 0062 'Nov' => 10, 'Dec' => 11); 0063 0064 %showoptions = (); 0065 $optionlocal = 0; 0066 0067 sub printinfo($) 0068 { 0069 print @_ if (defined($showoptions{"all"})); 0070 } 0071 0072 # convert text stamp to GMT 0073 sub strToTime 0074 { 0075 my( $timestr ) = @_; 0076 0077 if( ! ($timestr =~ 0078 /^(\w+)\s*(\w+)\s*(\d+)\s*(\d+):(\d+):(\d+)\s*(\d+)/) ) { 0079 0080 return -1; 0081 } 0082 0083 # CVS timestamps are in GMT. 0084 0085 my( $tm ) = timegm( $6, $5, $4, $3, $months{ $2 }, $7 - 1900); 0086 0087 return $tm; 0088 } 0089 0090 sub processEntries 0091 { 0092 my ( $dir ) = @_; 0093 my %dirunknown = (); 0094 0095 opendir (DIR, "$dir") || warn "Couldn't read '$dir'"; 0096 # first assume all are unknown 0097 while ( $e = readdir(DIR) ) { 0098 next if ($e eq "."); 0099 next if ($e eq ".."); 0100 next if ($e eq "RCS"); 0101 next if ($e eq "SCCS"); 0102 next if ($e eq "CVS"); 0103 next if ($e eq "CVS.adm"); 0104 next if ($e eq "RCSLOG"); 0105 next if ($e eq "tags"); 0106 next if ($e eq "TAGS"); 0107 next if ($e eq ".make.state"); 0108 next if ($e eq ".nse_depinfo"); 0109 next if ($e eq "core"); 0110 next if ($e eq ".libs"); 0111 next if ($e eq ".deps"); 0112 next if ($e =~ /^.+~$/); 0113 next if ($e =~ /^\#.+$/); 0114 next if ($e =~ /^\.\#.+$/); 0115 next if ($e =~ /^,.+$/); 0116 next if ($e =~ /^_\$.+$/); 0117 next if ($e =~ /^.+\$$/); 0118 next if ($e =~ /^.+\.old$/); 0119 next if ($e =~ /^.+\.bak$/); 0120 next if ($e =~ /^.+\.BAK$/); 0121 next if ($e =~ /^.+\.orig$/); 0122 next if ($e =~ /^.+\.rej$/); 0123 next if ($e =~ /^\.del-.+$/); 0124 next if ($e =~ /^.+\.a$/); 0125 next if ($e =~ /^.+\.olb$/); 0126 next if ($e =~ /^.+\.o$/); 0127 next if ($e =~ /^.*\.obj$/); 0128 next if ($e =~ /^.+\.so$/); 0129 next if ($e =~ /^.+\.Z$/); 0130 next if ($e =~ /^.+\.elc$/); 0131 next if ($e =~ /^.+\.ln$/); 0132 next if ($e =~ /^cvslog\..*$/); 0133 0134 # kde specific entries 0135 # TODO read from CVSROOT/cvsignore - if it's been checked out! 0136 next if ($e eq "config.cache"); 0137 next if ($e eq "config.log"); 0138 next if ($e eq "config.status"); 0139 next if ($e eq "index.cache.bz2"); 0140 next if ($e eq ".memdump"); 0141 next if ($e eq "autom4te.cache"); 0142 next if ($e eq "autom4te.cache"); 0143 next if ($e eq "Makefile.rules"); 0144 next if ($e eq "Makefile.calls"); 0145 next if ($e eq "Makefile.rules.in"); 0146 next if ($e eq "Makefile.calls.in"); 0147 next if ($e =~ /^.*\.moc$/); 0148 next if ($e =~ /^.+\.gmo$/); 0149 next if ($e =~ /^.+\.moc\.[^\.]+$/); 0150 next if ($e =~ /^.+\.lo$/); 0151 next if ($e =~ /^.+\.la$/); 0152 next if ($e =~ /^.+\.rpo$/); 0153 next if ($e =~ /^.+\.closure$/); 0154 next if ($e =~ /^.+\.all_cpp\.cpp$/); 0155 next if ($e =~ /^.+\.all_C\.C$/); 0156 next if ($e =~ /^.+\.all_cc\.cc$/); 0157 next if ($e =~ /^.+_meta_unload\.[^\.]+$/); 0158 next if ($e =~ /^.+\.kidl$/); 0159 next if ($e =~ /^.+_skel\.[^\.]+$/); 0160 0161 # Qt specific entries 0162 next if ($e eq ".ui"); 0163 next if ($e eq ".moc"); 0164 next if ($e eq ".obj"); 0165 0166 $dirunknown{$e} = 1; 0167 } 0168 closedir(DIR); 0169 if( open(CVSIGNORE, $dir."/.cvsignore") ) { 0170 while(<CVSIGNORE>) { 0171 s/\s*$//; 0172 my $line = $_; 0173 foreach my $entry ( split(/ /,$line) ) { 0174 if ($entry =~ /[\*\?]/) { 0175 my $pattern = quotemeta $entry; 0176 $pattern =~ s/\\\*/.*/g; 0177 $pattern =~ s/\\\?/./g; 0178 foreach $m (keys (%dirunknown)) { 0179 $dirunknown{$m} = 0 if ($m =~ /^$pattern$/); 0180 } 0181 next; 0182 } 0183 $dirunknown{$entry} = 0; 0184 } 0185 } 0186 close(CVSIGNORE); 0187 } 0188 0189 if ( !open( ENTRIES, $dir."/CVS/Entries" ) ) { 0190 &printinfo("I CVS/Entries missing in $dir\n"); 0191 return; 0192 } 0193 my $oldstandardtag = defined($defaulttag{$dir}) ? $defaulttag{$dir} : ""; 0194 my $staginfo = ""; 0195 if( open(CVSTAG, $dir."/CVS/Tag" ) ) { 0196 my $line = <CVSTAG>; 0197 if($line =~ /^[TDN](.+)$/) { 0198 $standardtag = $1; 0199 $staginfo = $1; 0200 } 0201 else { 0202 # something with D - assume HEAD 0203 $oldstandardtag = $standardtag = ""; # its HEAD 0204 &printinfo("I $dir has unknown stickyness: $line"); 0205 } 0206 close(CVSTAG); 0207 } 0208 else { 0209 $standardtag = ""; # its HEAD 0210 $staginfo = "(HEAD)"; 0211 } 0212 &printinfo("I $dir has sticky tag $staginfo\n") if($standardtag ne $oldstandardtag); 0213 while( <ENTRIES> ) { 0214 if ( m#^\s*D/([^/]+)/# ) { 0215 if (-d "$dir/$1" && !$optionlocal) { 0216 push ( @dirqueue, "$dir/$1" ); 0217 $defaulttag{"$dir/$1"} = $standardtag; 0218 } 0219 $dirunknown{$1} = 0; 0220 next; 0221 } 0222 0223 next if !m#^\s*/([^/]+)/([-]*[\d\.]*)/([^/]+)/([^/]*)/(\S*)$#; 0224 $fname = $1; 0225 $ver = $2; 0226 $stamp = $3; 0227 $options = $4; 0228 $tag = $5; 0229 $tag = $1 if ($tag =~ /^[TD](.+)$/); 0230 0231 $dirunknown{$fname} = 0; 0232 0233 my $taginfo=""; 0234 if(defined($showoptions{"all"})) { 0235 if ( $tag ne $standardtag ) { 0236 if ($tag eq "") { 0237 $taginfo = " (HEAD)"; 0238 } 0239 else { 0240 $taginfo = " ($tag)"; 0241 } 0242 } 0243 if ($options =~ /^\-k(.)$/) { 0244 $taginfo .= " (no RCS-tags)" if($1 eq "o"); 0245 $taginfo .= " (RCS binary file)" if($1 eq "b"); 0246 $taginfo .= " (RCS values only)" if($1 eq "v"); 0247 $taginfo .= " (RCS keywords only)" if($1 eq "k"); 0248 } 0249 } 0250 my $state = $stamp; 0251 if( $stamp =~ m(^(.+)\+(.+)$) ) { 0252 $state = $1; 0253 $stamp = $2; 0254 } 0255 if ( $state =~ /merge/ ) { 0256 # modified version merged with update from server 0257 # check for a conflict 0258 if ( open (F, "$dir/$fname") ) { 0259 my @conflict = grep /^<<<<<<</, <F>; 0260 close (F); 0261 if( @conflict ) { 0262 push @conflicts, "$dir/$fname$taginfo"; 0263 next; 0264 } 0265 } 0266 else { 0267 push @missing, "$dir/$fname$taginfo"; 0268 next; 0269 } 0270 } 0271 if ( $ver =~ /^\-.*/ ) { 0272 push @removed, "$dir/$fname$taginfo"; 0273 next; 0274 } 0275 $mtm = strToTime( $stamp ); 0276 if( $mtm < 0 ) { 0277 if ( $ver eq "0" ) { 0278 push @uncommitted, "$dir/$fname$taginfo"; 0279 } 0280 else { 0281 push @merged, "$dir/$fname$taginfo"; 0282 } 0283 next; 0284 } 0285 @sparams = lstat( "$dir/$fname" ); 0286 0287 if ( $#sparams < 0 ) { 0288 push @missing, "$dir/$fname$taginfo"; 0289 next; 0290 } 0291 if( $mtm < $sparams[ 9 ] ) { 0292 push @modified, "$dir/$fname$taginfo"; 0293 next; 0294 } 0295 if ( $tag ne $standardtag ) { 0296 push @tagged, "$dir/$fname$taginfo"; 0297 } 0298 } 0299 close( ENTRIES ); 0300 0301 my @unknownlist = sort keys (%dirunknown); 0302 foreach $entry (@unknownlist) { 0303 next if ($dirunknown{$entry} == 0); 0304 # ignore unusual files 0305 next if (-l "$dir/$entry" ); 0306 # its a CVS directory ? might be a different module 0307 if (-d "$dir/$entry" and -d "$dir/$entry/CVS") { 0308 $defaulttag{"$dir/$entry"} = $standardtag; 0309 push ( @dirqueue, "$dir/$entry" ); 0310 next; 0311 } 0312 push @unknown, "$dir/$entry"; 0313 } 0314 } 0315 0316 sub printlist($$@) 0317 { 0318 my ($status, $type, @flist) = @_; 0319 0320 return if (not defined($showoptions{"all"}) and 0321 not defined($showoptions{"$type"})); 0322 0323 if(defined($showoptions{"all"})) { 0324 foreach (@flist) { 0325 s/\.\///; 0326 print "$status $_\n"; 0327 } 0328 } 0329 else { 0330 foreach(@flist) { 0331 print "$_\n"; 0332 } 0333 } 0334 } 0335 0336 foreach $f ( @unknown ) { 0337 $f =~ s/^\.\///; 0338 print "? $f\n"; 0339 } 0340 foreach (@ARGV) { 0341 $showoptions{"unknown"}++ if(/^(?:-u|--unknown)$/); 0342 $showoptions{"modified"}++ if(/^(?:-m|--modified)$/); 0343 $showoptions{"missing"}++ if(/^(?:--missing)$/); 0344 $showoptions{"tagged"}++ if(/^(?:-t|--tagged)$/); 0345 $showoptions{"added"}++ if(/^(?:-a|--added)$/); 0346 $showoptions{"removed"}++ if(/^(?:-r|--removed)$/); 0347 $showoptions{"conflicts"}++ if(/^(?:-c|--conflicts)$/); 0348 $optionlocal++ if(/^(?:-l|--local)$/); 0349 0350 next if (/^-/); 0351 push (@dirqueue, "./$_"); 0352 } 0353 0354 # if no special flags set, show all files 0355 $showoptions{"all"}++ if(scalar(keys(%showoptions)) == 0); 0356 0357 # Try current directory if none specified 0358 push(@dirqueue, ".") if( $#dirqueue < 0 ); 0359 0360 # process directory queue 0361 while ($#dirqueue >= 0) { 0362 processEntries( pop @dirqueue ); 0363 } 0364 0365 &printlist("?", "unknown", @unknown); 0366 &printlist("M", "modified", @modified); 0367 &printlist("m", "modified", @merged); 0368 &printlist("U", "missing", @missing); 0369 &printlist("T", "tagged", @tagged); 0370 &printlist("A", "added", @uncommitted); 0371 &printlist("R", "removed", @removed); 0372 &printlist("C", "conflicts", @conflicts); 0373 0374 =head1 NAME 0375 0376 cvscheck -- Lists all files in checked out CVS modules that have been 0377 edited or changed locally. No connection is required to the CVS server, 0378 therefore being extremely fast. 0379 0380 =head1 AUTHOR 0381 0382 Dirk Mueller <mueller@kde.org> 0383 based on cvschanged by Sirtaj Singh Kang <taj@kde.org> 0384 0385 =cut