From: Colin McCabe Date: Mon, 14 Dec 2009 00:01:41 +0000 (-0800) Subject: Add p4_check.rb script X-Git-Url: http://club.cc.cmu.edu/~cmccabe/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=357799d75b8f4e6f40c781300b45625daebfbfdb;p=cmccabe-bin Add p4_check.rb script --- diff --git a/p4_check.rb b/p4_check.rb new file mode 100755 index 0000000..33fd045 --- /dev/null +++ b/p4_check.rb @@ -0,0 +1,111 @@ +#!/usr/bin/ruby -w + +# +# p4_check +# +# This is a script I wrote while I was using the perforce revision control +# system. I later switched to mostly using git. This script might still be +# useful to someone still using perforce, though. +# +# Given a perforce tree, this script: +# 1. Verifies that none of the files in it have been +# made writable without being checked out. +# 2. Finds "phantom files" that exist in the filesystem but not in perforce +# +# Colin McCabe +# + +require 'find' +require 'optparse' +require 'open3' +require 'ostruct' +require 'pp' + +##################### CLASSES ##################### +class MyOptionParse + def self.parse(args) + # default values + opts = OpenStruct.new + + parser = OptionParser.new do |myparser| + myparser.banner = "Usage: p4_check [opts]" + myparser.separator "Specific options:" + #myparser.on("-i PATH", "--input-dir PATH", + #"The input directory") do |a| + #opts.input = a + #end + end + + parser.parse!(args) + return opts + end +end + +class NotOpened < RuntimeError +end + +##################### FUNCTIONS ##################### +# Invoke perforce +def p4_call(cmd) + # If we allow non-arrays to be passed to this function, they will be subject + # to yucky shell expansion. + if (! cmd.kind_of?(Array)) then + $stderr.puts "FATAL: sorry, you must pass an array to this function." + end + + # p4 has the following calling convention: + # 1) exit code is always 0 + # 2) errors are on stdout, output is on stderr + stdin, stdout, stderr = Open3.popen3(*cmd) + err = stderr.readlines + ret = stdout.readlines + + # Take a look at the errors generated by p4. + # Some are always fatal; for others, we throw an exception + if (! err.empty?()) then + if (err[0] =~ /Perforce password (P4PASSWD) invalid or unset./) then + $stderr.puts "FATAL: #{err[0]}" + exit 1 + elsif (err[0] =~ /Client \'.*\' unknown - use \'client\' \ + command to create it./) then + $stderr.puts "FATAL: #{err[0]}" + exit 1 + else + raise NotOpened.new + end + end + + return ret +end + +def validate_p4 + lines = p4_call(["p4"]) + lines.each do |line| + if (line =~ /Perforce -- the Fast Software Configuration \ +Management System/) then + return + end + end + throw "validate_p4: failed to validate p4 program: #{lines.join}" +end + +##################### CODE ##################### +opts = MyOptionParse.parse(ARGV) +#pp opts + +# verify +validate_p4() + +# Look at all files in the tree +Find.find( Dir.pwd ) do |fname| + #puts "fname = #{fname}" + if (File.file?(fname)) then + if (File.writable?(fname)) then + begin + p4_call(["p4", "opened", fname]) + rescue NotOpened + puts "unknown writable: #{fname}" + end + end + end +end