diff --git a/ChangeLog b/ChangeLog index fba9014f09..296da1bdf6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sat Mar 13 17:48:43 2010 Nobuyoshi Nakada + + * tool/file2lastrev.rb: refactord. fixed changed revision of git. + Sat Mar 13 15:44:20 2010 Yukihiro Matsumoto * io.c (rb_io_print): should not print field separator at the end @@ -11,7 +15,7 @@ Sat Mar 13 14:49:55 2010 Yukihiro Matsumoto Sat Mar 13 12:26:13 2010 Nobuyoshi Nakada - * include/ruby/io.h (MakeOpenFile): finalize fptr get rid of + * include/ruby/io.h (MakeOpenFile): finalize fptr to get rid of memory leak. Sat Mar 13 11:14:26 2010 Shugo Maeda diff --git a/tool/file2lastrev.rb b/tool/file2lastrev.rb index e913783d71..66a13b457a 100755 --- a/tool/file2lastrev.rb +++ b/tool/file2lastrev.rb @@ -5,47 +5,77 @@ ENV.delete('PWD') require 'optparse' require 'pathname' -SRCDIR = Pathname(File.dirname($0)).parent.freeze -class VCSNotFoundError < RuntimeError; end +Program = Pathname($0) -def detect_vcs(path) - path = SRCDIR - return :svn, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.svn") - return :git_svn, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.git/svn") - return :git, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.git") - raise VCSNotFoundError, "does not seem to be under a vcs" -end +class VCS + class NotFoundError < RuntimeError; end -# return a pair of strings, the last revision and the last revision in which -# +path+ was modified. -def get_revisions(path) - vcs, path = detect_vcs(path) + @@dirs = [] + def self.register(dir) + @@dirs << [dir, self] + end - info = case vcs - when :svn - info_xml = `cd "#{SRCDIR}" && svn info --xml "#{path}"` - _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/) + 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 + 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 = Dir.chdir(@srcdir) {yield path} + last or raise "last revision not found" + changed or raise "changed revision not found" return last, changed - when :git_svn - `cd "#{SRCDIR}" && git svn info "#{path}"` - when :git - git_log = `cd "#{SRCDIR}" && git log HEAD~1..HEAD "#{path}"` - git_log =~ /git-svn-id: .*?@(\d+)/ - return $1, $1 end - if /^Revision: (\d+)/ =~ info - last = $1 - else - raise "last revision not found" - end - if /^Last Changed Rev: (\d+)/ =~ info - changed = $1 - else - raise "changed revision not found" + def relative_to(path) + path ? Pathname(path).relative_path_from(@srcdir) : '.' end - return last, changed + class SVN < self + register(".svn") + + def get_revisions(path) + super do + info_xml = `svn info --xml "#{path}"` + _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/) + [last, changed] + end + end + end + + class GIT_SVN < self + register(".git/svn") + + def get_revisions(path) + super do + info = `git svn info "#{path}"` + [info[/^Revision: (\d+)/, 1], info[/^Last Changed Rev: (\d+)/, 1]] + end + end + end + + class GIT < self + register(".git") + + def get_revisions(path) + logcmd = %Q[git log -n1 --grep='^ *git-svn-id: .*@[0-9][0-9]* '] + idpat = /git-svn-id: .*?@(\d+) \S+\Z/ + super do + last = `#{logcmd}`[idpat, 1] + changed = path ? `#{logcmd} "#{path}"`[idpat, 1] : last + [last, changed] + end + end + end end @output = nil @@ -57,27 +87,33 @@ def self.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") do + opts.on("--revision.h", "RUBY_REVISION macro") do self.output = :revision_h end - opts.on("--doxygen") do + opts.on("--doxygen", "Doxygen format") do self.output = :doxygen end opts.on("-q", "--suppress_not_found") do @suppress_not_found = true end } -parser.parse! - +parser.parse! rescue abort "#{Program.basename}: #{$!}\n#{parser}" +srcdir = (srcdir ? Pathname(srcdir) : Program.parent.parent).freeze begin - last, changed = get_revisions(ARGV.shift) -rescue VCSNotFoundError - raise unless @suppress_not_found + vcs = VCS.detect(srcdir) +rescue VCS::NotFoundError => e + abort "#{Program.basename}: #{e.message}" unless @suppress_not_found +else + last, changed = vcs.get_revisions(ARGV.shift) end case @output