# Task: compare two labels, create report giving # lists of # only in first label # only in second label, # in both, but the revision in the label isn't same. # # num of calls to 'p4': 2 calls to 'p4 files' # status: tested on Win/NT using P4Ruby API, # tested on Darwin Mac OS X using P4Ruby API # # Copyright 2004 Perforce Corporation, Inc. All rights reserved. require 'getoptlong' label1 = label2 = nil debugOption = false defaultPort = nil defaultUser = nil options = GetoptLong.new( [ '--debug', '-d', GetoptLong::OPTIONAL_ARGUMENT], [ '--user', '-u', GetoptLong::REQUIRED_ARGUMENT], [ '--label1', '-1', GetoptLong::REQUIRED_ARGUMENT], [ '--label2', '-2', GetoptLong::REQUIRED_ARGUMENT], [ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT] ) options.each do |opt, arg| case opt when "--debug" debugOption = true when "--user" defaultUser = arg when "--port" defaultPort = arg when "--label1" label1 = arg when "--label2" label2 = arg end end raise RuntimeError, "--label1 XXXX must be given on command-line" if label1 == nil raise RuntimeError, "--label2 XXXX must be given on command-line" if label2 == nil require "P4" p4 = P4.new p4.port = defaultPort if defaultPort != nil p4.user = defaultUser if defaultUser != nil # p4.client = "dent.development" p4.tagged p4.parse_forms p4.connect begin puts "label1 = #{label1}" if debugOption puts "label2 = #{label2}" if debugOption # # strategy: # 1. We'll collect Perforce output in "label1list" # a.and in order to let Ruby "set operations" assist, # we'll make an Array of "label1filenames" that are # only the filenames;, # b.and for fast lookup of revisions, a "label1revbyfname" # 2. Afterwards, it's a set operation (subtract) to get # the list of filenames "in one label but not the other" # 3. And a set operation (intersection - that's "&") to # get the filenames in both places, which we can infer # are the ones we need to look at to see if there are # different revisions to report. (item 1b, above, # has the structures in place to do so.) #----------------------------------------------------------- # first call to P4: 'p4 files @label1' #----------------------------------------------------------- label1list = p4.run("files", "@#{label1}") label1revbyfname = {} label1list.each { |f| label1revbyfname[f['depotFile']] = f['rev'] } label1filenames = label1list.collect { |f| f['depotFile'] } puts label1filenames.inspect if debugOption #----------------------------------------------------------- # second call to P4: 'p4 files @label2' #----------------------------------------------------------- label2list = p4.run("files", "@#{label2}") label2filenames = label2list.collect { |f| f['depotFile'] } label2revbyfname = {} label2list.each { |f| label2revbyfname[f['depotFile']] = f['rev'] } puts label2filenames.inspect if debugOption # case 1: files in the first label but not the second filesOnlyInLabel1 = label1filenames - label2filenames filesOnlyInLabel1.each { |fname| puts "Only in #{label1}: #{fname}" } # case 2: files in the first label but not the second filesOnlyInLabel2 = label2filenames - label1filenames filesOnlyInLabel2.each { |fname| puts "Only in #{label2}: #{fname}" } # case 3: files in both labels, but different revisions filesInCommon = label2filenames & label1filenames puts "#{filesInCommon.length} files in common (but maybe different revs)" filesInCommon.each do |fname| rev1 = label1revbyfname[fname] rev2 = label2revbyfname[fname] puts "Comparing rev1=#{rev1} rev2=#{rev2} for #{fname}" if debugOption if rev1 != rev2 puts "#{fname} is rev #{rev1} in #{label1} but #{rev2} in #{label2}" end end rescue P4Exception p4.errors.each { |e| $stderr.puts( e ) } raise end p4.disconnect