summaryrefslogtreecommitdiff
path: root/test/rubygems/test_gem_commands_rebuild_command.rb
blob: 5e8c797e2d11add25b1042672b3521edede316ba (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
144
145
# frozen_string_literal: true

require_relative "helper"
require "rubygems/commands/build_command"
require "rubygems/commands/rebuild_command"
require "rubygems/package"

class TestGemCommandsRebuildCommand < Gem::TestCase
  def setup
    super

    readme_file = File.join(@tempdir, "README.md")

    begin
      umask_orig = File.umask(2)
      File.open readme_file, "w" do |f|
        f.write "My awesome gem"
      end
    ensure
      File.umask(umask_orig)
    end

    @gem_name = "rebuild_test_gem"
    @gem_version = "1.0.0"
    @gem = util_spec @gem_name do |s|
      s.version = @gem_version
      s.license = "AGPL-3.0"
      s.files = ["README.md"]
    end
  end

  def util_test_build_gem(gem, args)
    @ui = Gem::MockGemUi.new

    cmd = Gem::Commands::BuildCommand.new

    cmd.options[:args] = args
    cmd.options[:build_path] = @tempdir
    use_ui @ui do
      cmd.execute
    end
    gem_file = "#{@gem_name}-#{@gem_version}.gem"
    output = @ui.output.split "\n"
    assert_equal "  Successfully built RubyGem", output.shift
    assert_equal "  Name: #{@gem_name}", output.shift
    assert_equal "  Version: #{@gem_version}", output.shift
    assert_equal "  File: #{gem_file}", output.shift
    assert_equal [], output

    gem_file = File.join(@tempdir, gem_file)
    assert File.exist?(gem_file)

    spec = Gem::Package.new(gem_file).spec

    assert_equal @gem_name, spec.name
    assert_equal "this is a summary", spec.summary
    gem_file
  end

  def util_test_rebuild_gem(gem, args, original_gem_file, gemspec_file, timestamp)
    @ui = Gem::MockGemUi.new

    cmd = Gem::Commands::RebuildCommand.new

    cmd.options[:args] = args
    cmd.options[:original_gem_file] = original_gem_file
    cmd.options[:build_path] = @tempdir
    cmd.options[:gemspec_file] = gemspec_file
    use_ui @ui do
      cmd.execute
    end
    gem_file = "#{@gem_name}-#{@gem_version}.gem"
    output = @ui.output.split "\n"

    assert_equal "  Successfully built RubyGem", output.shift
    assert_equal "  Name: #{@gem_name}", output.shift
    assert_equal "  Version: #{@gem_version}", output.shift
    assert_equal "  File: #{gem_file}", output.shift
    assert_empty output.shift
    assert_match(/^Built at: .+ \(#{timestamp}\)/, output.shift)
    original_line = output.shift
    original = original_line.split(" ")[-1]
    assert_match(/^Original build saved to:   /, original_line)
    reproduced_line = output.shift
    reproduced = reproduced_line.split(" ")[-1]
    assert_match(/^Reproduced build saved to: /, reproduced_line)
    assert_equal "Working directory: #{@tempdir}", output.shift
    assert_equal "", output.shift
    assert_equal "Hash comparison:", output.shift
    output.shift # "  #{old_hash}\t#{old_file}"
    output.shift # "  #{new_hash}\t#{new_file}"
    assert_empty output.shift
    assert_equal "SUCCESS - original and rebuild hashes matched", output.shift
    assert_equal [], output

    assert File.exist?(original)
    assert File.exist?(reproduced)

    old_spec = Gem::Package.new(original).spec
    new_spec = Gem::Package.new(reproduced).spec

    assert_equal @gem_name, old_spec.name
    assert_equal "this is a summary", old_spec.summary

    assert_equal old_spec.name, new_spec.name
    assert_equal old_spec.summary, new_spec.summary

    reproduced
  end

  def test_build_is_reproducible
    # Back up SOURCE_DATE_EPOCH to restore later.
    epoch = ENV["SOURCE_DATE_EPOCH"]

    gemspec_file = File.join(@tempdir, @gem.spec_name)

    # Initial Build

    # Set SOURCE_DATE_EPOCH to 2001-02-03 04:05:06 -0500.
    ENV["SOURCE_DATE_EPOCH"] = timestamp = Time.new(2001, 2, 3, 4, 5, 6).to_i.to_s
    File.write(gemspec_file, @gem.to_ruby)
    gem_file = util_test_build_gem @gem, [gemspec_file]

    build_contents = File.read(gem_file)

    gem_file_dir = File.dirname(gem_file)
    gem_file_name = File.basename(gem_file)
    original_gem_file = File.join(gem_file_dir, "original-" + gem_file_name)
    File.rename(gem_file, original_gem_file)

    # Rebuild

    # Set SOURCE_DATE_EPOCH to a different value, meaning we are
    # also testing that `gem rebuild` overrides the value.
    ENV["SOURCE_DATE_EPOCH"] = Time.new(2007, 8, 9, 10, 11, 12).to_s

    rebuild_gem_file = util_test_rebuild_gem(@gem, [@gem_name, @gem_version], original_gem_file, gemspec_file, timestamp)

    rebuild_contents = File.read(rebuild_gem_file)

    assert_equal build_contents, rebuild_contents
  ensure
    ENV["SOURCE_DATE_EPOCH"] = epoch
  end
end