summaryrefslogtreecommitdiff
path: root/lib/rubygems/builder.rb
blob: f7f07e86bf1e89119d163d6a0b8a256570cd983f (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
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

module Gem

  ##
  # The Builder class processes RubyGem specification files
  # to produce a .gem file.
  #
  class Builder
  
    include UserInteraction
    ##
    # Constructs a builder instance for the provided specification
    #
    # spec:: [Gem::Specification] The specification instance
    #
    def initialize(spec)
      require "yaml"
      require "rubygems/package"
      require "rubygems/security"

      @spec = spec
    end

    ##
    # Builds the gem from the specification.  Returns the name of the file
    # written.
    #
    def build
      @spec.mark_version
      @spec.validate
      @signer = sign
      write_package
      say success
      @spec.file_name
    end
    
    def success
      <<-EOM
  Successfully built RubyGem
  Name: #{@spec.name}
  Version: #{@spec.version}
  File: #{@spec.full_name+'.gem'}
EOM
    end

    private

    def sign
      # if the signing key was specified, then load the file, and swap
      # to the public key (TODO: we should probably just omit the
      # signing key in favor of the signing certificate, but that's for
      # the future, also the signature algorithm should be configurable)
      signer = nil
      if @spec.respond_to?(:signing_key) && @spec.signing_key
        signer = Gem::Security::Signer.new(@spec.signing_key, @spec.cert_chain)
        @spec.signing_key = nil
        @spec.cert_chain = signer.cert_chain.map { |cert| cert.to_s }
      end
      signer
    end

    def write_package
      Package.open(@spec.file_name, "w", @signer) do |pkg|
        pkg.metadata = @spec.to_yaml
        @spec.files.each do |file|
          next if File.directory? file
          pkg.add_file_simple(file, File.stat(@spec.file_name).mode & 0777,
                              File.size(file)) do |os|
              os.write File.open(file, "rb"){|f|f.read}
          end
        end
      end
    end
  end
end