summaryrefslogtreecommitdiff
path: root/trunk/lib/rubygems/doc_manager.rb
blob: 88d7964d8594f581a9d7c94f2fa32a904d7623cb (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

require 'fileutils'

module Gem

  class DocManager

    include UserInteraction

    # Create a document manager for the given gem spec.
    #
    # spec::      The Gem::Specification object representing the gem.
    # rdoc_args:: Optional arguments for RDoc (template etc.) as a String.
    #
    def initialize(spec, rdoc_args="")
      @spec = spec
      @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
      @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
    end

    # Is the RDoc documentation installed?
    def rdoc_installed?
      return File.exist?(File.join(@doc_dir, "rdoc"))
    end

    # Generate the RI documents for this gem spec.
    #
    # Note that if both RI and RDoc documents are generated from the
    # same process, the RI docs should be done first (a likely bug in
    # RDoc will cause RI docs generation to fail if run after RDoc).
    def generate_ri
      if @spec.has_rdoc then
        load_rdoc
        install_ri # RDoc bug, ri goes first
      end

      FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
    end

    # Generate the RDoc documents for this gem spec.
    #
    # Note that if both RI and RDoc documents are generated from the
    # same process, the RI docs should be done first (a likely bug in
    # RDoc will cause RI docs generation to fail if run after RDoc).
    def generate_rdoc
      if @spec.has_rdoc then
        load_rdoc
        install_rdoc
      end

      FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
    end

    # Load the RDoc documentation generator library.
    def load_rdoc
      if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
        raise Gem::FilePermissionError.new(@doc_dir)
      end

      FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)

      begin
        gem 'rdoc'
      rescue Gem::LoadError
        # use built-in RDoc
      end

      begin
        require 'rdoc/rdoc'
      rescue LoadError => e
        raise Gem::DocumentError,
          "ERROR: RDoc documentation generator not installed!"
      end
    end

    def install_rdoc
      rdoc_dir = File.join @doc_dir, 'rdoc'

      FileUtils.rm_rf rdoc_dir

      say "Installing RDoc documentation for #{@spec.full_name}..."
      run_rdoc '--op', rdoc_dir
    end

    def install_ri
      ri_dir = File.join @doc_dir, 'ri'

      FileUtils.rm_rf ri_dir

      say "Installing ri documentation for #{@spec.full_name}..."
      run_rdoc '--ri', '--op', ri_dir
    end

    def run_rdoc(*args)
      args << @spec.rdoc_options
      args << DocManager.configured_args
      args << '--quiet'
      args << @spec.require_paths.clone
      args << @spec.extra_rdoc_files
      args = args.flatten.map do |arg| arg.to_s end

      r = RDoc::RDoc.new

      old_pwd = Dir.pwd
      Dir.chdir(@spec.full_gem_path)
      begin
        r.document args
      rescue Errno::EACCES => e
        dirname = File.dirname e.message.split("-")[1].strip
        raise Gem::FilePermissionError.new(dirname)
      rescue RuntimeError => ex
        alert_error "While generating documentation for #{@spec.full_name}"
        ui.errs.puts "... MESSAGE:   #{ex}"
        ui.errs.puts "... RDOC args: #{args.join(' ')}"
        ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
          Gem.configuration.backtrace
        ui.errs.puts "(continuing with the rest of the installation)"
      ensure
        Dir.chdir(old_pwd)
      end
    end

    def uninstall_doc
      raise Gem::FilePermissionError.new(@spec.installation_path) unless
        File.writable? @spec.installation_path

      original_name = [
        @spec.name, @spec.version, @spec.original_platform].join '-'

      doc_dir = File.join @spec.installation_path, 'doc', @spec.full_name
      unless File.directory? doc_dir then
        doc_dir = File.join @spec.installation_path, 'doc', original_name
      end

      FileUtils.rm_rf doc_dir

      ri_dir = File.join @spec.installation_path, 'ri', @spec.full_name

      unless File.directory? ri_dir then
        ri_dir = File.join @spec.installation_path, 'ri', original_name
      end

      FileUtils.rm_rf ri_dir
    end

    class << self
      def configured_args
        @configured_args ||= []
      end

      def configured_args=(args)
        case args
        when Array
          @configured_args = args
        when String
          @configured_args = args.split
        end
      end
    end
    
  end
end