mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	is available. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@28667 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			153 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env ruby
 | 
						|
 | 
						|
ENV.delete('PWD')
 | 
						|
 | 
						|
require 'optparse'
 | 
						|
 | 
						|
unless File.respond_to? :realpath
 | 
						|
  require 'pathname'
 | 
						|
  def File.realpath(arg)
 | 
						|
    Pathname(arg).realpath.to_s
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
Program = $0
 | 
						|
 | 
						|
class VCS
 | 
						|
  class NotFoundError < RuntimeError; end
 | 
						|
 | 
						|
  @@dirs = []
 | 
						|
  def self.register(dir)
 | 
						|
    @@dirs << [dir, self]
 | 
						|
  end
 | 
						|
 | 
						|
  def self.detect(path)
 | 
						|
    @@dirs.sort.reverse_each do |dir, klass|
 | 
						|
      return klass.new(path) if File.directory?("#{path}/#{dir}")
 | 
						|
    end
 | 
						|
    raise VCS::NotFoundError, "does not seem to be under a vcs: #{path}"
 | 
						|
  end
 | 
						|
 | 
						|
  def initialize(path)
 | 
						|
    @srcdir = path
 | 
						|
    super()
 | 
						|
  end
 | 
						|
 | 
						|
  # return a pair of strings, the last revision and the last revision in which
 | 
						|
  # +path+ was modified.
 | 
						|
  def get_revisions(path)
 | 
						|
    path = relative_to(path)
 | 
						|
    last, changed, *rest = Dir.chdir(@srcdir) {self.class.get_revisions(path)}
 | 
						|
    last or raise "last revision not found"
 | 
						|
    changed or raise "changed revision not found"
 | 
						|
    return last, changed, *rest
 | 
						|
  end
 | 
						|
 | 
						|
  def relative_to(path)
 | 
						|
    if path
 | 
						|
      srcdir = File.realpath(@srcdir)
 | 
						|
      path = File.realpath(path)
 | 
						|
      list1 = srcdir.split(%r{/})
 | 
						|
      list2 = path.split(%r{/})
 | 
						|
      while !list1.empty? && !list2.empty? && list1.first == list2.first
 | 
						|
        list1.shift
 | 
						|
        list2.shift
 | 
						|
      end
 | 
						|
      if list1.empty? && list2.empty?
 | 
						|
        "."
 | 
						|
      else
 | 
						|
        ([".."] * list1.length + list2).join("/")
 | 
						|
      end
 | 
						|
    else
 | 
						|
      '.'
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  class SVN < self
 | 
						|
    register(".svn")
 | 
						|
 | 
						|
    def self.get_revisions(path)
 | 
						|
      begin
 | 
						|
        nulldevice = %w[/dev/null NUL NIL: NL:].find {|dev| File.exist?(dev)}
 | 
						|
        if nulldevice
 | 
						|
          save_stderr = STDERR.dup
 | 
						|
          STDERR.reopen nulldevice, 'w'
 | 
						|
        end
 | 
						|
        info_xml = `svn info --xml "#{path}"`
 | 
						|
      ensure
 | 
						|
        if save_stderr
 | 
						|
          STDERR.reopen save_stderr
 | 
						|
          save_stderr.close
 | 
						|
        end
 | 
						|
      end
 | 
						|
      _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/)
 | 
						|
      [last, changed]
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  class GIT < self
 | 
						|
    register(".git")
 | 
						|
 | 
						|
    def self.get_revisions(path)
 | 
						|
      logcmd = %Q[git log -n1 --grep="^ *git-svn-id: .*@[0-9][0-9]* "]
 | 
						|
      idpat = /git-svn-id: .*?@(\d+) \S+\Z/
 | 
						|
      last = `#{logcmd}`[idpat, 1]
 | 
						|
      changed = path ? `#{logcmd} "#{path}"`[idpat, 1] : last
 | 
						|
      [last, changed]
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
@output = nil
 | 
						|
def self.output=(output)
 | 
						|
  if @output and @output != output
 | 
						|
    raise "you can specify only one of --changed, --revision.h and --doxygen"
 | 
						|
  end
 | 
						|
  @output = output
 | 
						|
end
 | 
						|
@suppress_not_found = false
 | 
						|
 | 
						|
srcdir = nil
 | 
						|
parser = OptionParser.new {|opts|
 | 
						|
  opts.on("--srcdir=PATH", "use PATH as source directory") do |path|
 | 
						|
    srcdir = path
 | 
						|
  end
 | 
						|
  opts.on("--changed", "changed rev") do
 | 
						|
    self.output = :changed
 | 
						|
  end
 | 
						|
  opts.on("--revision.h", "RUBY_REVISION macro") do
 | 
						|
    self.output = :revision_h
 | 
						|
  end
 | 
						|
  opts.on("--doxygen", "Doxygen format") do
 | 
						|
    self.output = :doxygen
 | 
						|
  end
 | 
						|
  opts.on("-q", "--suppress_not_found") do
 | 
						|
    @suppress_not_found = true
 | 
						|
  end
 | 
						|
}
 | 
						|
parser.parse! rescue abort "#{File.basename(Program)}: #{$!}\n#{parser}"
 | 
						|
 | 
						|
srcdir = srcdir ? srcdir : File.dirname(File.dirname(Program))
 | 
						|
begin
 | 
						|
  vcs = VCS.detect(srcdir)
 | 
						|
rescue VCS::NotFoundError => e
 | 
						|
  abort "#{File.basename(Program)}: #{e.message}" unless @suppress_not_found
 | 
						|
else
 | 
						|
  begin
 | 
						|
    last, changed = vcs.get_revisions(ARGV.shift)
 | 
						|
  rescue => e
 | 
						|
    abort "#{File.basename(Program)}: #{e.message}" unless @suppress_not_found
 | 
						|
    exit false
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
case @output
 | 
						|
when :changed, nil
 | 
						|
  puts changed
 | 
						|
when :revision_h
 | 
						|
  puts "#define RUBY_REVISION #{changed.to_i}"
 | 
						|
when :doxygen
 | 
						|
  puts "r#{changed}/r#{last}"
 | 
						|
else
 | 
						|
  raise "unknown output format `#{@output}'"
 | 
						|
end
 |