Makefile: add pickrand
[cmccabe-bin] / p4_check.rb
1 #!/usr/bin/ruby -w
2
3 #
4 # p4_check
5 #
6 # This is a script I wrote while I was using the perforce revision control
7 # system. I later switched to mostly using git. This script might still be
8 # useful to someone still using perforce, though.
9 #
10 # Given a perforce tree, this script:
11 #  1. Verifies that none of the files in it have been 
12 #     made writable without being checked out.
13 #  2. Finds "phantom files" that exist in the filesystem but not in perforce
14 #
15 # Colin McCabe
16 #
17
18 require 'find'
19 require 'optparse'
20 require 'open3'
21 require 'ostruct'
22 require 'pp'
23
24 ##################### CLASSES ##################### 
25 class MyOptionParse
26   def self.parse(args)
27     # default values 
28     opts = OpenStruct.new
29
30     parser = OptionParser.new do |myparser|
31       myparser.banner = "Usage: p4_check [opts]"
32       myparser.separator "Specific options:"
33       #myparser.on("-i PATH", "--input-dir PATH",
34               #"The input directory") do |a|
35         #opts.input = a
36       #end
37     end
38
39     parser.parse!(args)
40     return opts
41   end
42 end
43
44 class NotOpened < RuntimeError
45 end
46
47 ##################### FUNCTIONS ##################### 
48 # Invoke perforce
49 def p4_call(cmd)
50   # If we allow non-arrays to be passed to this function, they will be subject
51   # to yucky shell expansion.
52   if (! cmd.kind_of?(Array)) then
53     $stderr.puts "FATAL: sorry, you must pass an array to this function." 
54   end
55
56   # p4 has the following calling convention:
57   # 1) exit code is always 0
58   # 2) errors are on stdout, output is on stderr
59   stdin, stdout, stderr = Open3.popen3(*cmd)
60   err = stderr.readlines
61   ret = stdout.readlines
62   
63   # Take a look at the errors generated by p4.
64   # Some are always fatal; for others, we throw an exception
65   if (! err.empty?()) then
66     if (err[0] =~ /Perforce password (P4PASSWD) invalid or unset./) then
67       $stderr.puts "FATAL: #{err[0]}"
68       exit 1
69     elsif (err[0] =~ /Client \'.*\' unknown - use \'client\' \
70         command to create it./) then
71       $stderr.puts "FATAL: #{err[0]}"
72       exit 1
73     else
74       raise NotOpened.new
75     end
76   end
77
78   return ret
79 end
80
81 def validate_p4
82   lines = p4_call(["p4"])
83   lines.each do |line|
84     if (line =~ /Perforce -- the Fast Software Configuration \
85 Management System/) then
86       return
87     end
88   end
89   throw "validate_p4: failed to validate p4 program: #{lines.join}"
90 end
91
92 ##################### CODE ##################### 
93 opts = MyOptionParse.parse(ARGV)
94 #pp opts
95
96 # verify 
97 validate_p4()
98
99 # Look at all files in the tree
100 Find.find( Dir.pwd ) do |fname|
101   #puts "fname = #{fname}"
102   if (File.file?(fname)) then 
103     if (File.writable?(fname)) then
104       begin
105         p4_call(["p4", "opened", fname])
106       rescue NotOpened
107         puts "unknown writable: #{fname}"
108       end
109     end
110   end
111 end