dummy.rb #2

  • //
  • guest/
  • pascal_soccard/
  • Scripts/
  • dummy.rb
  • View
  • Commits
  • Open Download .zip Download (8 KB)
#!/usr/bin/ruby

################################################################################
#
# Copyright (c) 2009, Perforce Software, Inc.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# = Description
#   Create dummy revisions for file revisions reported MISSING by
#   the "p4 verify" command.
#   All dummy revisions are stored as gzipped file, therefore they can be
#   easily replaced later on if a user has one of the missing revisions
#   in a workspace.
#
# = Usage
#   p4 verify -q //a_path/... | ruby dummy.rb
#   or
#   ruby dummy.rb verify_output_file
#
################################################################################

require "P4"
require "zlib"
require "ftools"

# Regular expression used for parsing the output of "p4 verify"
MISSINGRexp = Regexp.new( '.*(//.*#\d+) -.*MISSING!' )
# Regular expression used for detecting absolute file path
ABSOLUTEPATHRexp = Regexp.new( '\w:.*|^/.*')

def InitialiseDepotMap(p4, p4root)
    depotMap = P4::Map.new()
    depots = p4.run_depots()
    depots.each do
    |d|
       path = d["map"]
       if !path.match( ABSOLUTEPATHRexp )
          path = p4root + "/" + path
       end
       depotMap.insert( "//" + d[ "name" ].to_s + "/...", path ) 
    end
    return depotMap
end

def RcsType?(type)
    result = false
    if (type == "text" or type == "unicode" or type =="utf16" or
        type == "utf16" or type == "ktext" or type == "xtext" or
        type == "kxtext" or type == "xunicode" or type == "xutf16")
       result = true
    end
    return result
end

def GzType?(type)
    result = false
    if (type == "binary" or type == "ctext" or type == "resource" or
        type == "apple" or type == "cxtext" or type == "xbinary" or
        type == "ctempobj")
       result = true
    end
    return result
end

def CreateRCSFile(rcsFile, lbrRev)
    success = 0
    begin
      # Create the missing rcs file revision only if rcs file does not exist
      if !File.exist?(rcsFile)
         # The subdirectores may not exist
         File.makedirs(File.dirname(rcsFile)) unless File.directory?(File.dirname(rcsFile))
         rcsFile = File.new(rcsFile, "w")
         rcsFile.puts "head     " + lbrRev + ";"
         rcsFile.puts "access   ;"
         rcsFile.puts "symbols  ;"
         rcsFile.puts "locks    ;comment  @@;"
         rcsFile.puts lbrRev
         rcsFile.puts "date     " + Time.now.strftime("%Y.%m.%d.%H.%M.%S") + ";  author p4;  state Exp;"
         rcsFile.puts "branches ;"
         rcsFile.puts "next     ;"
         rcsFile.puts "desc"
         rcsFile.puts "@@"
         rcsFile.puts lbrRev 
         rcsFile.puts "log"
         rcsFile.puts "@@"
         rcsFile.puts "text"
         rcsFile.puts "@This is a dummy revision.@"
         rcsFile.close
         success = 1
      end
    rescue
       puts "error: cannot create " + File.dirname(rcsFile) + " or " + rcsFile
    end
    return success
end

def CreateGzipFile(gzFile)
    success = 0
    begin
      if !File.exist?(gzFile)
        # The binary directory may not exist
        File.makedirs(File.dirname(gzFile)) unless File.directory?(File.dirname(gzFile))
        # create a gzip dummy revision
        Zlib::GzipWriter.open(gzFile) do |gz|
          gz.write 'This is a dummy revision.'
      end
      success = 1
    end
    rescue
      puts "error: cannot create " + File.dirname(gzFile) + " or " + gzFile
    end
    return success
end

def FixChecksum(p4, depotFile, depotRev, lazyCopyFile, lazyCopyRev)
    p4.run_verify("-v", depotFile + "#" + depotRev + ",#" + depotRev)
    if lazyCopyFile
       for i in 0...lazyCopyFile.size
           p4.run_verify("-v", lazyCopyFile[i] + lazyCopyRev[i])
       end 
    end 
end

begin
  p4 = P4.new
  p4.exception_level = P4::RAISE_ERRORS
  p4.connect

  p4info = p4.run_info().shift
  p4root = p4info [ "serverRoot" ]
  if (p4.server_level < 23)
    puts "error: a Perforce server 2007.2 or greater is required"
    exit(0)
  elsif (!p4root.match( ABSOLUTEPATHRexp ))
    puts("error: P4ROOT directroy must be set with an absolute path")
    exit(0)
  end

  depotMap = InitialiseDepotMap(p4, p4root)

  line = $<.gets
  while line
    if (md = MISSINGRexp.match(line))
      fstat = p4.run_fstat("-Oc", "-Oz", md[1]).shift
      depotFile = fstat[ "depotFile" ]
      lbrFile = fstat[ "lbrFile" ]
      # Only fix non-lazy copy revision
      if (depotFile == lbrFile)
        depotRev = fstat[ "headRev" ]
        lbrRev = fstat[ "lbrRev" ]
        lbrType = fstat[ "lbrType" ]
        lazyCopyFile = fstat[ "lazyCopyFile" ]
        lazyCopyRev = fstat[ "lazyCopyRev" ]
        revFile = depotFile + "#" + depotRev
        gzFile = depotMap.translate(lbrFile) + ",d/" + lbrRev +  ".gz"
        if RcsType?(lbrType)
          # Fix missing rcs revision
          rcsFile = depotMap.translate(lbrFile) + ",v"
          bakFile = rcsFile + ".dummy"
          if File.exist?(rcsFile)
            # missing revision in an existing rcs file
            File.rename(rcsFile, bakFile)
          end
          if CreateRCSFile(rcsFile, lbrRev) == 1
            # Convert rcs file to gz file
            p4.run_retype("-l", "-tctext", revFile + ",#" + depotRev)
            # Force recalculation of checksum to prevent BAD verify errors
            FixChecksum(p4, depotFile, depotRev, lazyCopyFile, lazyCopyRev)
            puts "info: " + revFile + " was fixed (" + gzFile + " was created)"
          else
            puts "error: " + revFile + " (" + rcsFile + ") cannot be fixed"
          end
          if File.exist?(bakFile)
            File.rename(bakFile, rcsFile)
          end
        elsif GzType?(lbrType)
            # Fix missing gzipped revision
            if File.exist?(gzFile)        
              # gzipped revision exist. Corruption?
              begin
                Zlib::GzipReader.open(gzFile) {
                |gz|
                   gz.read
                }
                puts "info: " + revFile + " was not changed (" + gzFile + ") is not corrupted"
                break
              rescue
                corruptedFile = gzFile + ".corrupted"
                File.rename(gzFile, corruptedFile)
                puts "info: " + revFile + " is corrupted" + " (" + corruptedFile + " was created)"
              end
            end
            if CreateGzipFile(gzFile) == 1 
              # Force recalculation of checksum to prevent BAD verify errors
              FixChecksum(p4, depotFile, depotRev, lazyCopyFile, lazyCopyRev)
              puts "info: " + revFile + " was fixed (" + gzFile + " was created)"
            else
              puts "error: " + revFile + " (" + gzFile + ") cannot be fixed"
            end
        end
       end
    end
    line = $<.gets
  end
rescue P4Exception
    p4.errors.each {
    |e|
       $stderr.puts( e )
    }
    raise
end
# Change User Description Committed
#8 8473 Pascal Soccard - Fixed dummy.rb call as the system call did not work with a large
data set (probably a buffer issue). dummy.rb can now run
"p4 verify -q" command if a depot path is passed as an argument.
- Added support for Ruby 1.9
- Fixed verify error capture as verify errors are reported as errors
in 2013.1 or greater
#7 7835 Pascal Soccard Fixed text+F and tempobj storage type detection
#6 7834 Pascal Soccard ubinary and +F files are now processed
#5 7554 Pascal Soccard Added support for librarian files manually deleted
after obliterate (broken lazy copy)
#4 7543 Pascal Soccard The script can now deal with lazy copies for which
the librarian file has been manually deleted after
the librarian depot file has been obliterated
#3 7537 Pascal Soccard Took server case sensitivity into account.
Requires P4Ruby 2009.2
#2 7481 Pascal Soccard Now can fix missing revision in an existing rcs file and
fix corrupted gzipped revision
#1 7398 Pascal Soccard Added script to create dummy revisions for files reported
MISSING by "p4 verify"