#!/usr/bin/env ruby # git.rb - a P4 shim that pretends to be Git so that it can work with Xcode # entirely experimental: here be dragons require 'fileutils' begin f = File.open('/Users/matt/fauxgit_log.txt', 'a') f.puts ARGV.join(' ') f.puts "Total args: #{ARGV.size()}" p4 = '/usr/local/bin/p4' # require a P4 URI because it's my tool # URIs are of the form [username@]p4:// case ARGV[0] when 'clone' matches = /p4:\/\/(.+?)@(.+?)\/(.*)|p4:\/\/(.+?)\/(.*)/.match(ARGV[4]) user = matches.captures[0] port = matches.captures[1] || matches.captures[3] path = matches.captures[2] || matches.captures[4] # let's be civilized and not require a port if port !~ /:\d*/ port = port + ":1666" end cmd = "#{p4} -d #{ARGV[5]}" cmd += " -u #{user}" if user # running the clone and creating a fake git repo to appease Xcode f.puts "#{cmd} clone -p #{port} -f //#{path}/..." `#{cmd} clone -p #{port} -f //#{path}/...` FileUtils.mkdir_p "#{ARGV[5]}/.git/info" FileUtils.mkdir_p "#{ARGV[5]}/.git/refs" FileUtils.mkdir_p "#{ARGV[5]}/.git/objects" FileUtils.mkdir_p "#{ARGV[5]}/.git/hooks" FileUtils.touch "#{ARGV[5]}/.git/HEAD" FileUtils.touch "#{ARGV[5]}/.git/config" FileUtils.touch "#{ARGV[5]}/.git/description" # totally lying here, but it seems to make XCode happy? # will experiment sometime with removing this now that I # do a better job of creating the directories it wants puts "Cloning into '#{ARGV[4]}'..." puts "remote: Counting objects: 596, done." puts "remote: Compressing objects: 100% (309/309), done." puts "remote: Total 596 (delta 275), reused 596 (delta 275)" puts "Receiving objects: 100% (596/596), 107.22 KiB | 0 bytes/s, done." puts "Resolving deltas: 100% (275/275), done." puts "Checking connectivity... done." when 'init' f.puts "#{p4} init" `#{p4} init` FileUtils.mkdir_p ".git/info" FileUtils.mkdir_p ".git/refs" FileUtils.mkdir_p ".git/objects" FileUtils.mkdir_p ".git/hooks" FileUtils.touch ".git/HEAD" FileUtils.touch ".git/config" FileUtils.touch ".git/description" when 'add' f.puts "#{p4} rec" `#{p4} rec ...` when 'status' f.puts "#{p4} -ztag -F '%change% %action% %localFile%' status" results = `#{p4} -ztag -F '%change% %action% %localFile%' status` results.each_line do |r| if r.start_with?(' add ') puts "?? #{r.split(' ')[1]}" elsif r.start_with?('default add ') puts "A #{r.split(' ')[2]}" elsif r.start_with?(' edit ') puts " M #{r.split(' ')[1]}" elsif r.start_with?('default edit ') puts "M #{r.split(' ')[2]}" elsif r.start_with?(' delete ') puts " D #{r.split(' ')[1]}" elsif r.start_with?('default delete ') puts "D #{r.split(' ')[2]}" end end when 'branch' if ARGV.size() == 1 results = `#{p4} switch -l` results.each_line do |r| if r.end_with?("*\n") puts "* #{r.split(' ')[0]}" else puts " #{r}" end end elsif ARGV.size() == 3 results = `#{p4} switch -cr -P #{ARGV[2]} #{ARGV[1]}` end when 'mv' f.puts "#{p4} edit #{ARGV[1]}" f.puts "#{p4} move #{ARGV[1]} #{ARGV[2]}" `#{p4} edit #{ARGV[1]}` `#{p4} move #{ARGV[1]} #{ARGV[2]}` when 'rm' if ARGV[1] == '-f' && ARGV[2] == '-r' && ARGV[3] == '--' ARGV[4..-1].each do |f| f.puts "#{p4} delete #{f}" f.puts "#{p4} delete #{f}/..." `#{p4} delete #{f}` `#{p4} delete #{f}/...` end end when 'commit' `#{p4} rec` # Git forces the file to commit by specifying it, we don't have that `#{p4} submit -d #{ARGV[2]}` when 'checkout' `#{p4} switch #{ARGV[1]}` when 'blame' puts 'p4 annotate' when 'archive' STDOUT.write `find . -name #{ARGV[2]} | xargs /usr/bin/tar c` when 'log' `p4 changes -m1` when 'config' && ARGV[1] == '--get' if ARGV[2] == 'branch.default.remote' puts 'default' elsif ARGV[2] == 'branch.default.merge' puts 'refs/heads/default' elsif ARGV[2] == 'remote.origin.url' puts 'matt_attaway@perforce.com/stuff' end when 'remote' puts "origin\x09http://xxxxx (fetch)" puts "origin\x09http://xxxxx (push)" when 'ls-remote' puts "3828d854bb849581255a20cbbc4e0e639fba2eb7\trefs/heads/master" end f.puts "" f.close() end