summaryrefslogtreecommitdiff
path: root/tool/make-snapshot
blob: 997582b636cf6878b43af5d6d15bd19664bc5739 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/ruby
require 'uri'
require 'digest/md5'
require 'digest/sha2'
require 'fileutils'
require 'tmpdir'
STDOUT.sync = true

ENV["LC_ALL"] = ENV["LANG"] = "C"
SVNURL = URI.parse("http://svn.ruby-lang.org/repos/ruby/")
RUBY_VERSION_PATTERN = /^\#define\s+RUBY_VERSION\s+"([\d.]+)"/

ENV["VPATH"] ||= "include/ruby"
YACC = ENV["YACC"] ||= "bison"
ENV["BASERUBY"] ||= "ruby"
ENV["RUBY"] ||= "ruby"
ENV["MV"] ||= "mv"
ENV["MINIRUBY"] ||= "ruby"

path = ENV["PATH"].split(File::PATH_SEPARATOR)
%w[YACC BASERUBY RUBY MV MINIRUBY].each do |var|
  cmd = ENV[var]
  unless path.any? {|dir|
      file = File.join(dir, cmd)
      File.file?(file) and File.executable?(file)
    }
    abort "#{File.basename $0}: #{var} command not found - #{cmd}"
  end
end

unless destdir = ARGV.shift
  abort "usage: #{File.basename $0} new-directory-to-save [version ...]"
end
FileUtils.mkpath(destdir)
destdir = File.expand_path(destdir)
revisions = ARGV.empty? ? ["trunk"] : ARGV
tmp = Dir.mktmpdir("ruby-snapshot")
FileUtils.mkpath(tmp)
at_exit {
  Dir.chdir "/"
  FileUtils.rm_rf(tmp)
}
Dir.chdir tmp

def package(rev, destdir)
  patchlevel = false
  case rev
  when /\Atrunk\z/, /\Abranches\//, /\Atags\//
    url = SVNURL + rev
  when /\Astable\z/
    url = SVNURL + "branches/"
    url = url + `svn ls #{url}`[/.*^(ruby_\d+_\d+)\//m, 1]
  when /\A\(.*\..*\..*\)-/
    patchlevel = true
    url = SVNURL + "tags/v#{rev.sub(/-p?/, '_').tr('.', '_')}"
  when /\./
    url = SVNURL + "branches/ruby_#{rev.tr('.', '_')}"
  else
    warn "#{$0}: unknown version - #{rev}"
    return
  end
  revision = `svn info #{url} 2>&1`[/Last Changed Rev: (\d+)/, 1]
  version = nil
  unless revision
    url = SVNURL + "trunk"
    version = `svn cat #{url + "version.h"}`[RUBY_VERSION_PATTERN, 1]
    unless rev == version
      warn "#{$0}: #{rev} not found"
      return
    end
    revision = `svn info #{url}`[/Last Changed Rev: (\d+)/, 1]
  end
  puts "Exporting #{rev}@#{revision}"
  IO.popen("svn export #{url} ruby") do |pipe|
    pipe.each {|line| /^A/ =~ line or print line}
  end
  unless $?.success?
    warn("Export failed")
    return
  end
  open("ruby/revision.h", "wb") {|f| f.puts "#define RUBY_REVISION #{revision}"}
  version ||= (versionhdr = IO.read("ruby/version.h"))[RUBY_VERSION_PATTERN, 1]
  version or return
  if patchlevel
    versionhdr ||= IO.read("ruby/version.h")
    patchlevel = versionhdr[/^\#define\s+RUBY_PATCHLEVEL\s+(\d+)/, 1]
    tag = (patchlevel ? "p#{patchlevel}" : "r#{revision}")
  else
    tag = "r#{revision}"
  end
  v = "ruby-#{version}-#{tag}"
  File.rename "ruby", v
  Dir.chdir(v) do
    print "creating configure..."
    unless system("autoconf")
      puts " failed"
      return
    end
    puts " done"
    FileUtils.rm_rf("autom4te.cache")
    print "creating prerequisites..."
    if File.file?("common.mk") && /^prereq/ =~ commonmk = IO.read("common.mk")
      IO.popen("make -f - prereq srcdir=. IFCHANGE=tool/ifchange", "w") do |f|
        f.puts(IO.read("Makefile.in")[/^lex\.c.*?^$/m])
        f.puts(commonmk.gsub(/\{[^{}]*\}/, ""))
      end
    else
      system("#{YACC} -o parse.c parse.y")
    end
    unless $?.success?
      puts " failed"
      return
    end
    puts " done"
  end

  return [["bzip tarball", ".tar.bz2", %w"tar cjf"],
          ["gzip tarball", ".tar.gz", %w"tar czf"],
          ["zip archive", ".zip", %w"zip -qr"]
         ].collect do |mesg, ext, cmd|
    file = "#{destdir}/#{v}#{ext}"
    print "creating #{mesg}... #{file}"
    if system(*(cmd + [file, v]))
      puts " done"
      file
    else
      puts " failed"
      nil
    end
  end.compact
ensure
  FileUtils.rm_rf(v) if v
end

revisions.collect {|rev| package(rev, destdir)}.flatten.each do |name|
  str = open(name, "rb") {|f| f.read}
  md5 = Digest::MD5.hexdigest str
  sha = Digest::SHA256.hexdigest str
  puts "MD5(#{name})= #{md5}"
  puts "SHA256(#{name})= #{sha}"
  puts "SIZE(name)= #{str.size}"
  puts
end