Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Query doc update and license update

git-svn-id: http://stonecode.svnrepository.com/svn/ruport/ruport/trunk@865 bb2e8eb0-7117-0410-aac4-c024b40ed5f7
  • Loading branch information...
commit 690784a924b9503eef3ecbcef506c5bd44c60ea6 1 parent dfd7bbf
authored
64  LICENSE
... ...
@@ -1,13 +1,59 @@
1  
-= License Terms
  1
+Ruport is copyrighted free software originally produced by Gregory Brown 
  2
+<gregory.t.brown@gmail.com> which now contains a number of community
  3
+contributions and is actively developed by Michael Milner <mikem836@gmail.com>.
2 4
 
3  
-Distributed by Gregory Brown under the user's choice* of the 
4  
-{GPL version 2}[http://www.gnu.org/copyleft/gpl.html] (see COPYING for details)
5  
-or the {Ruby software license}[http://www.ruby-lang.org/en/LICENSE.txt].
  5
+See the AUTHORS file for a complete list of contributors.  
6 6
 
7  
-Please email Greg[mailto:gregory.t.brown_AT_gmail.com] with any questions.
  7
+Licensing terms follow (License of Ruby 1.8):
8 8
 
9  
-*Note:  This license refers specifically to GPLv2.
10  
-Distributing under other versions of the GPL require explicit permission from
11  
-Gregory Brown.  Though we will most likely adopt the GPLv3 when the final draft
12  
-is published, we want to be able to make that decision for ourselves.
  9
+You can redistribute Ruport and/or modify it under either the terms of the GPL
  10
+(see COPYING file), or the conditions below:
13 11
 
  12
+  1. You may make and give away verbatim copies of the source form of the
  13
+     software without restriction, provided that you duplicate all of the
  14
+     original copyright notices and associated disclaimers.
  15
+
  16
+  2. You may modify your copy of the software in any way, provided that
  17
+     you do at least ONE of the following:
  18
+
  19
+       a) place your modifications in the Public Domain or otherwise
  20
+          make them Freely Available, such as by posting said
  21
+    modifications to Usenet or an equivalent medium, or by allowing
  22
+    the author to include your modifications in the software.
  23
+
  24
+       b) use the modified software only within your corporation or
  25
+          organization.
  26
+
  27
+       c) rename any non-standard executables so the names do not conflict
  28
+    with standard executables, which must also be provided.
  29
+
  30
+       d) make other distribution arrangements with the author.
  31
+
  32
+  3. You may distribute the software in object code or executable
  33
+     form, provided that you do at least ONE of the following:
  34
+
  35
+       a) distribute the executables and library files of the software,
  36
+    together with instructions (in the manual page or equivalent)
  37
+    on where to get the original distribution.
  38
+
  39
+       b) accompany the distribution with the machine-readable source of
  40
+    the software.
  41
+
  42
+       c) give non-standard executables non-standard names, with
  43
+          instructions on where to get the original software distribution.
  44
+
  45
+       d) make other distribution arrangements with the author.
  46
+
  47
+  4. You may modify and include the part of the software into any other
  48
+     software (possibly commercial). 
  49
+
  50
+  5. The scripts and library files supplied as input to or produced as 
  51
+     output from the software do not automatically fall under the
  52
+     copyright of the software, but belong to whomever generated them, 
  53
+     and may be sold commercially, and may be aggregated with this
  54
+     software.
  55
+
  56
+  6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  57
+     IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  58
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  59
+     PURPOSE.
95  lib/ruport/query.rb
... ...
@@ -1,3 +1,15 @@
  1
+# Ruport : Extensible Reporting System                                
  2
+#
  3
+# query.rb provides a basic wrapper around RubyDBI for SQL interaction
  4
+#
  5
+# Original work began by Gregory Brown based on ideas from James Edward Gray II
  6
+# in August, 2005.
  7
+#
  8
+# Copyright (C) 2005-2007, Gregory Brown
  9
+# All Rights Reserved.   
  10
+#
  11
+# This is free software distributed under the same terms as Ruby 1.8
  12
+# See LICENSE and COPYING for details.
1 13
 require "generator"
2 14
 require "ruport/query/sql_split"
3 15
 
@@ -5,17 +17,18 @@ module Ruport
5 17
   
6 18
   # === Overview
7 19
   # 
8  
-  # Query offers a way to interact with databases via DBI. It supports
9  
-  # returning result sets in either Ruport's native Data::Table, or in their 
  20
+  # Query offers a way to interact with databases via RubyDBI. It supports
  21
+  # returning result sets in either Ruport's Data::Table, or in their 
10 22
   # raw form as DBI::Rows.
11 23
   #
12  
-  # It offers basic caching support, the ability to instantiate a generator 
13  
-  # for a result set, and the ability to quickly and easily swap between data
14  
-  # sources.
  24
+  # Query allows you to treat your result sets as an Enumerable data structure
  25
+  # that plays well with the rest of Ruport.
  26
+  #
  27
+  # If you are using ActiveRecord, you might prefer our acts_as_reportable
  28
+  # extension.       
15 29
   #
16 30
   class Query 
17  
-    
18  
-    
  31
+       
19 32
     include Enumerable
20 33
     
21 34
     # Ruport::Query provides an interface for dealing with raw SQL queries.
@@ -34,11 +47,7 @@ class Query
34 47
     # <b><tt>:password</tt></b>::       If a DSN is specified, the password 
35 48
     #                                   can be set with this option.
36 49
     # <b><tt>:raw_data</tt></b>::       When set to true, DBI::Rows will be 
37  
-    #                                   returned instead of a Data::Table.
38  
-    # <b><tt>:cache_enabled</tt></b>::  When set to true, Query will download 
39  
-    #                                   results only once, and then return 
40  
-    #                                   cached values until the cache has been 
41  
-    #                                   cleared.
  50
+    #                                   returned instead of a Data::Table
42 51
     #
43 52
     # Examples:
44 53
     #   
@@ -76,28 +85,43 @@ def initialize(sql, options={})
76 85
       @raw_data = options[:row_type].eql?(:raw)
77 86
       @params = options[:params]
78 87
     end
79  
-
  88
+     
  89
+    # Returns an OpenStruct with the configuration options for the default
  90
+    # database source.
  91
+    #
80 92
     def self.default_source
81 93
       sources[:default]
82 94
     end
83  
-
  95
+     
  96
+    # Returns a hash of database sources, keyed by label.
84 97
     def self.sources
85 98
       @sources ||= {}
86 99
     end
87  
-
  100
+    
  101
+    # Allows you to add a labeled DBI source configuration. 
  102
+    #
  103
+    # Query objects will use the source labeled <tt>:default</tt>,
  104
+    # unless another source is specified.
  105
+    #
  106
+    # Examples:
  107
+    #
  108
+    #   # a connection to a MySQL database foo with user root, pass chunkybacon
  109
+    #   Query.add_source :default, :dsn => "dbi:mysql:foo", 
  110
+    #                              :user => "root",
  111
+    #                              :password => "chunkybacon"
  112
+    #
  113
+    #
  114
+    #   # a second connection to a MySQL database bar
  115
+    #   Query.add_source :test, :dsn => "dbi:mysql:bar",
  116
+    #                           :user => "tester",
  117
+    #                           :password => "blinky" 
  118
+    #
  119
+    # 
88 120
     def self.add_source(name,options={})
89 121
       sources[name] = OpenStruct.new(options)
90 122
       check_source(sources[name],name)
91 123
     end
92 124
 
93  
-    private
94  
-
95  
-    def self.check_source(settings,label) # :nodoc:
96  
-      raise ArgumentError unless settings.dsn
97  
-    end
98  
-
99  
-    public
100  
-
101 125
     attr_accessor :raw_data
102 126
     
103 127
     # The original SQL for the Query object
@@ -112,20 +136,20 @@ def select_source(label)
112 136
       @password = Ruport::Query.sources[label].password
113 137
     end 
114 138
     
  139
+    # Yields result set by row.
115 140
     def each(&action)
116 141
       raise(LocalJumpError, "No block given!") unless action
117 142
       fetch(&action)
118 143
       self
119 144
     end
120 145
     
  146
+    # Runs the SQL query and returns the result set 
121 147
     def result; fetch; end
122 148
     
123 149
     # Runs the query without returning its results.
124 150
     def execute; fetch; nil; end
125 151
     
126 152
     # Returns a Data::Table, even if in <tt>raw_data</tt> mode.
127  
-    # This doesn't work with raw data if the cache is enabled and filled.
128  
-    #
129 153
     def to_table
130 154
       data_flag, @raw_data = @raw_data, false
131 155
       data = fetch; @raw_data = data_flag; return data
@@ -176,14 +200,6 @@ def get_query(type,query)
176 200
       type.eql?(:file) ? load_file( query ) : query
177 201
     end
178 202
     
179  
-    def load_file(query_file)
180  
-      begin
181  
-        File.read( query_file ).strip
182  
-      rescue
183  
-        raise LoadError, "Could not open #{query_file}"
184  
-      end
185  
-    end
186  
-    
187 203
     def fetch(&block)
188 204
       data = nil
189 205
       final = @statements.size - 1
@@ -192,5 +208,18 @@ def fetch(&block)
192 208
       end
193 209
       return data
194 210
     end
  211
+    
  212
+    def load_file(query_file)
  213
+      begin
  214
+        File.read( query_file ).strip
  215
+      rescue
  216
+        raise LoadError, "Could not open #{query_file}"
  217
+      end
  218
+    end
  219
+
  220
+    def self.check_source(settings,label) # :nodoc:
  221
+      raise ArgumentError unless settings.dsn
  222
+    end
  223
+    
195 224
   end
196 225
 end
4  lib/ruport/renderer/grouping.rb
@@ -40,8 +40,8 @@ class Renderer::Group < Renderer
40 40
   #
41 41
   # == Default layout options 
42 42
   #
43  
-  # * <tt>show_group_headers</tt> #=> true
44  
-  # * <tt>style</tt> #=> :inline
  43
+  # * <tt>show_group_headers</tt> #=> true    
  44
+  # * <tt>style</tt> #=> :inline  
45 45
   #
46 46
   # == Formatter hooks called (in order)
47 47
   #
1,585  setup.rb
... ...
@@ -1,1585 +0,0 @@
1  
-#
2  
-# setup.rb
3  
-#
4  
-# Copyright (c) 2000-2005 Minero Aoki
5  
-#
6  
-# This program is free software.
7  
-# You can distribute/modify this program under the terms of
8  
-# the GNU LGPL, Lesser General Public License version 2.1.
9  
-#
10  
-
11  
-unless Enumerable.method_defined?(:map)   # Ruby 1.4.6
12  
-  module Enumerable
13  
-    alias map collect
14  
-  end
15  
-end
16  
-
17  
-unless File.respond_to?(:read)   # Ruby 1.6
18  
-  def File.read(fname)
19  
-    open(fname) {|f|
20  
-      return f.read
21  
-    }
22  
-  end
23  
-end
24  
-
25  
-unless Errno.const_defined?(:ENOTEMPTY)   # Windows?
26  
-  module Errno
27  
-    class ENOTEMPTY
28  
-      # We do not raise this exception, implementation is not needed.
29  
-    end
30  
-  end
31  
-end
32  
-
33  
-def File.binread(fname)
34  
-  open(fname, 'rb') {|f|
35  
-    return f.read
36  
-  }
37  
-end
38  
-
39  
-# for corrupted Windows' stat(2)
40  
-def File.dir?(path)
41  
-  File.directory?((path[-1,1] == '/') ? path : path + '/')
42  
-end
43  
-
44  
-
45  
-class ConfigTable
46  
-
47  
-  include Enumerable
48  
-
49  
-  def initialize(rbconfig)
50  
-    @rbconfig = rbconfig
51  
-    @items = []
52  
-    @table = {}
53  
-    # options
54  
-    @install_prefix = nil
55  
-    @config_opt = nil
56  
-    @verbose = true
57  
-    @no_harm = false
58  
-  end
59  
-
60  
-  attr_accessor :install_prefix
61  
-  attr_accessor :config_opt
62  
-
63  
-  attr_writer :verbose
64  
-
65  
-  def verbose?
66  
-    @verbose
67  
-  end
68  
-
69  
-  attr_writer :no_harm
70  
-
71  
-  def no_harm?
72  
-    @no_harm
73  
-  end
74  
-
75  
-  def [](key)
76  
-    lookup(key).resolve(self)
77  
-  end
78  
-
79  
-  def []=(key, val)
80  
-    lookup(key).set val
81  
-  end
82  
-
83  
-  def names
84  
-    @items.map {|i| i.name }
85  
-  end
86  
-
87  
-  def each(&block)
88  
-    @items.each(&block)
89  
-  end
90  
-
91  
-  def key?(name)
92  
-    @table.key?(name)
93  
-  end
94  
-
95  
-  def lookup(name)
96  
-    @table[name] or setup_rb_error "no such config item: #{name}"
97  
-  end
98  
-
99  
-  def add(item)
100  
-    @items.push item
101  
-    @table[item.name] = item
102  
-  end
103  
-
104  
-  def remove(name)
105  
-    item = lookup(name)
106  
-    @items.delete_if {|i| i.name == name }
107  
-    @table.delete_if {|name, i| i.name == name }
108  
-    item
109  
-  end
110  
-
111  
-  def load_script(path, inst = nil)
112  
-    if File.file?(path)
113  
-      MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
114  
-    end
115  
-  end
116  
-
117  
-  def savefile
118  
-    '.config'
119  
-  end
120  
-
121  
-  def load_savefile
122  
-    begin
123  
-      File.foreach(savefile()) do |line|
124  
-        k, v = *line.split(/=/, 2)
125  
-        self[k] = v.strip
126  
-      end
127  
-    rescue Errno::ENOENT
128  
-      setup_rb_error $!.message + "\n#{File.basename($0)} config first"
129  
-    end
130  
-  end
131  
-
132  
-  def save
133  
-    @items.each {|i| i.value }
134  
-    File.open(savefile(), 'w') {|f|
135  
-      @items.each do |i|
136  
-        f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
137  
-      end
138  
-    }
139  
-  end
140  
-
141  
-  def load_standard_entries
142  
-    standard_entries(@rbconfig).each do |ent|
143  
-      add ent
144  
-    end
145  
-  end
146  
-
147  
-  def standard_entries(rbconfig)
148  
-    c = rbconfig
149  
-
150  
-    rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
151  
-
152  
-    major = c['MAJOR'].to_i
153  
-    minor = c['MINOR'].to_i
154  
-    teeny = c['TEENY'].to_i
155  
-    version = "#{major}.#{minor}"
156  
-
157  
-    # ruby ver. >= 1.4.4?
158  
-    newpath_p = ((major >= 2) or
159  
-                 ((major == 1) and
160  
-                  ((minor >= 5) or
161  
-                   ((minor == 4) and (teeny >= 4)))))
162  
-
163  
-    if c['rubylibdir']
164  
-      # V > 1.6.3
165  
-      libruby         = "#{c['prefix']}/lib/ruby"
166  
-      librubyver      = c['rubylibdir']
167  
-      librubyverarch  = c['archdir']
168  
-      siteruby        = c['sitedir']
169  
-      siterubyver     = c['sitelibdir']
170  
-      siterubyverarch = c['sitearchdir']
171  
-    elsif newpath_p
172  
-      # 1.4.4 <= V <= 1.6.3
173  
-      libruby         = "#{c['prefix']}/lib/ruby"
174  
-      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
175  
-      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
176  
-      siteruby        = c['sitedir']
177  
-      siterubyver     = "$siteruby/#{version}"
178  
-      siterubyverarch = "$siterubyver/#{c['arch']}"
179  
-    else
180  
-      # V < 1.4.4
181  
-      libruby         = "#{c['prefix']}/lib/ruby"
182  
-      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
183  
-      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
184  
-      siteruby        = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
185  
-      siterubyver     = siteruby
186  
-      siterubyverarch = "$siterubyver/#{c['arch']}"
187  
-    end
188  
-    parameterize = lambda {|path|
189  
-      path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
190  
-    }
191  
-
192  
-    if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
193  
-      makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
194  
-    else
195  
-      makeprog = 'make'
196  
-    end
197  
-
198  
-    [
199  
-      ExecItem.new('installdirs', 'std/site/home',
200  
-                   'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
201  
-          {|val, table|
202  
-            case val
203  
-            when 'std'
204  
-              table['rbdir'] = '$librubyver'
205  
-              table['sodir'] = '$librubyverarch'
206  
-            when 'site'
207  
-              table['rbdir'] = '$siterubyver'
208  
-              table['sodir'] = '$siterubyverarch'
209  
-            when 'home'
210  
-              setup_rb_error '$HOME was not set' unless ENV['HOME']
211  
-              table['prefix'] = ENV['HOME']
212  
-              table['rbdir'] = '$libdir/ruby'
213  
-              table['sodir'] = '$libdir/ruby'
214  
-            end
215  
-          },
216  
-      PathItem.new('prefix', 'path', c['prefix'],
217  
-                   'path prefix of target environment'),
218  
-      PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
219  
-                   'the directory for commands'),
220  
-      PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
221  
-                   'the directory for libraries'),
222  
-      PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
223  
-                   'the directory for shared data'),
224  
-      PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
225  
-                   'the directory for man pages'),
226  
-      PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
227  
-                   'the directory for system configuration files'),
228  
-      PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
229  
-                   'the directory for local state data'),
230  
-      PathItem.new('libruby', 'path', libruby,
231  
-                   'the directory for ruby libraries'),
232  
-      PathItem.new('librubyver', 'path', librubyver,
233  
-                   'the directory for standard ruby libraries'),
234  
-      PathItem.new('librubyverarch', 'path', librubyverarch,
235  
-                   'the directory for standard ruby extensions'),
236  
-      PathItem.new('siteruby', 'path', siteruby,
237  
-          'the directory for version-independent aux ruby libraries'),
238  
-      PathItem.new('siterubyver', 'path', siterubyver,
239  
-                   'the directory for aux ruby libraries'),
240  
-      PathItem.new('siterubyverarch', 'path', siterubyverarch,
241  
-                   'the directory for aux ruby binaries'),
242  
-      PathItem.new('rbdir', 'path', '$siterubyver',
243  
-                   'the directory for ruby scripts'),
244  
-      PathItem.new('sodir', 'path', '$siterubyverarch',
245  
-                   'the directory for ruby extentions'),
246  
-      PathItem.new('rubypath', 'path', rubypath,
247  
-                   'the path to set to #! line'),
248  
-      ProgramItem.new('rubyprog', 'name', rubypath,
249  
-                      'the ruby program using for installation'),
250  
-      ProgramItem.new('makeprog', 'name', makeprog,
251  
-                      'the make program to compile ruby extentions'),
252  
-      SelectItem.new('shebang', 'all/ruby/never', 'ruby',
253  
-                     'shebang line (#!) editing mode'),
254  
-      BoolItem.new('without-ext', 'yes/no', 'no',
255  
-                   'does not compile/install ruby extentions')
256  
-    ]
257  
-  end
258  
-  private :standard_entries
259  
-
260  
-  def load_multipackage_entries
261  
-    multipackage_entries().each do |ent|
262  
-      add ent
263  
-    end
264  
-  end
265  
-
266  
-  def multipackage_entries
267  
-    [
268  
-      PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
269  
-                               'package names that you want to install'),
270  
-      PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
271  
-                               'package names that you do not want to install')
272  
-    ]
273  
-  end
274  
-  private :multipackage_entries
275  
-
276  
-  ALIASES = {
277  
-    'std-ruby'         => 'librubyver',
278  
-    'stdruby'          => 'librubyver',
279  
-    'rubylibdir'       => 'librubyver',
280  
-    'archdir'          => 'librubyverarch',
281  
-    'site-ruby-common' => 'siteruby',     # For backward compatibility
282  
-    'site-ruby'        => 'siterubyver',  # For backward compatibility
283  
-    'bin-dir'          => 'bindir',
284  
-    'bin-dir'          => 'bindir',
285  
-    'rb-dir'           => 'rbdir',
286  
-    'so-dir'           => 'sodir',
287  
-    'data-dir'         => 'datadir',
288  
-    'ruby-path'        => 'rubypath',
289  
-    'ruby-prog'        => 'rubyprog',
290  
-    'ruby'             => 'rubyprog',
291  
-    'make-prog'        => 'makeprog',
292  
-    'make'             => 'makeprog'
293  
-  }
294  
-
295  
-  def fixup
296  
-    ALIASES.each do |ali, name|
297  
-      @table[ali] = @table[name]
298  
-    end
299  
-    @items.freeze
300  
-    @table.freeze
301  
-    @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
302  
-  end
303  
-
304  
-  def parse_opt(opt)
305  
-    m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
306  
-    m.to_a[1,2]
307  
-  end
308  
-
309  
-  def dllext
310  
-    @rbconfig['DLEXT']
311  
-  end
312  
-
313  
-  def value_config?(name)
314  
-    lookup(name).value?
315  
-  end
316  
-
317  
-  class Item
318  
-    def initialize(name, template, default, desc)
319  
-      @name = name.freeze
320  
-      @template = template
321  
-      @value = default
322  
-      @default = default
323  
-      @description = desc
324  
-    end
325  
-
326  
-    attr_reader :name
327  
-    attr_reader :description
328  
-
329  
-    attr_accessor :default
330  
-    alias help_default default
331  
-
332  
-    def help_opt
333  
-      "--#{@name}=#{@template}"
334  
-    end
335  
-
336  
-    def value?
337  
-      true
338  
-    end
339  
-
340  
-    def value
341  
-      @value
342  
-    end
343  
-
344  
-    def resolve(table)
345  
-      @value.gsub(%r<\$([^/]+)>) { table[$1] }
346  
-    end
347  
-
348  
-    def set(val)
349  
-      @value = check(val)
350  
-    end
351  
-
352  
-    private
353  
-
354  
-    def check(val)
355  
-      setup_rb_error "config: --#{name} requires argument" unless val
356  
-      val
357  
-    end
358  
-  end
359  
-
360  
-  class BoolItem < Item
361  
-    def config_type
362  
-      'bool'
363  
-    end
364  
-
365  
-    def help_opt
366  
-      "--#{@name}"
367  
-    end
368  
-
369  
-    private
370  
-
371  
-    def check(val)
372  
-      return 'yes' unless val
373  
-      case val
374  
-      when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
375  
-      when /\An(o)?\z/i, /\Af(alse)\z/i  then 'no'
376  
-      else
377  
-        setup_rb_error "config: --#{@name} accepts only yes/no for argument"
378  
-      end
379  
-    end
380  
-  end
381  
-
382  
-  class PathItem < Item
383  
-    def config_type
384  
-      'path'
385  
-    end
386  
-
387  
-    private
388  
-
389  
-    def check(path)
390  
-      setup_rb_error "config: --#{@name} requires argument"  unless path
391  
-      path[0,1] == '$' ? path : File.expand_path(path)
392  
-    end
393  
-  end
394  
-
395  
-  class ProgramItem < Item
396  
-    def config_type
397  
-      'program'
398  
-    end
399  
-  end
400  
-
401  
-  class SelectItem < Item
402  
-    def initialize(name, selection, default, desc)
403  
-      super
404  
-      @ok = selection.split('/')
405  
-    end
406  
-
407  
-    def config_type
408  
-      'select'
409  
-    end
410  
-
411  
-    private
412  
-
413  
-    def check(val)
414  
-      unless @ok.include?(val.strip)
415  
-        setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
416  
-      end
417  
-      val.strip
418  
-    end
419  
-  end
420  
-
421  
-  class ExecItem < Item
422  
-    def initialize(name, selection, desc, &block)
423  
-      super name, selection, nil, desc
424  
-      @ok = selection.split('/')
425  
-      @action = block
426  
-    end
427  
-
428  
-    def config_type
429  
-      'exec'
430  
-    end
431  
-
432  
-    def value?
433  
-      false
434  
-    end
435  
-
436  
-    def resolve(table)
437  
-      setup_rb_error "$#{name()} wrongly used as option value"
438  
-    end
439  
-
440  
-    undef set
441  
-
442  
-    def evaluate(val, table)
443  
-      v = val.strip.downcase
444  
-      unless @ok.include?(v)
445  
-        setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
446  
-      end
447  
-      @action.call v, table
448  
-    end
449  
-  end
450  
-
451  
-  class PackageSelectionItem < Item
452  
-    def initialize(name, template, default, help_default, desc)
453  
-      super name, template, default, desc
454  
-      @help_default = help_default
455  
-    end
456  
-
457  
-    attr_reader :help_default
458  
-
459  
-    def config_type
460  
-      'package'
461  
-    end
462  
-
463  
-    private
464  
-
465  
-    def check(val)
466  
-      unless File.dir?("packages/#{val}")
467  
-        setup_rb_error "config: no such package: #{val}"
468  
-      end
469  
-      val
470  
-    end
471  
-  end
472  
-
473  
-  class MetaConfigEnvironment
474  
-    def initialize(config, installer)
475  
-      @config = config
476  
-      @installer = installer
477  
-    end
478  
-
479  
-    def config_names
480  
-      @config.names
481  
-    end
482  
-
483  
-    def config?(name)
484  
-      @config.key?(name)
485  
-    end
486  
-
487  
-    def bool_config?(name)
488  
-      @config.lookup(name).config_type == 'bool'
489  
-    end
490  
-
491  
-    def path_config?(name)
492  
-      @config.lookup(name).config_type == 'path'
493  
-    end
494  
-
495  
-    def value_config?(name)
496  
-      @config.lookup(name).config_type != 'exec'
497  
-    end
498  
-
499  
-    def add_config(item)
500  
-      @config.add item
501  
-    end
502  
-
503  
-    def add_bool_config(name, default, desc)
504  
-      @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
505  
-    end
506  
-
507  
-    def add_path_config(name, default, desc)
508  
-      @config.add PathItem.new(name, 'path', default, desc)
509  
-    end
510  
-
511  
-    def set_config_default(name, default)
512  
-      @config.lookup(name).default = default
513  
-    end
514  
-
515  
-    def remove_config(name)
516  
-      @config.remove(name)
517  
-    end
518  
-
519  
-    # For only multipackage
520  
-    def packages
521  
-      raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
522  
-      @installer.packages
523  
-    end
524  
-
525  
-    # For only multipackage
526  
-    def declare_packages(list)
527  
-      raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
528  
-      @installer.packages = list
529  
-    end
530  
-  end
531  
-
532  
-end   # class ConfigTable
533  
-
534  
-
535  
-# This module requires: #verbose?, #no_harm?
536  
-module FileOperations
537  
-
538  
-  def mkdir_p(dirname, prefix = nil)
539  
-    dirname = prefix + File.expand_path(dirname) if prefix
540  
-    $stderr.puts "mkdir -p #{dirname}" if verbose?
541  
-    return if no_harm?
542  
-
543  
-    # Does not check '/', it's too abnormal.
544  
-    dirs = File.expand_path(dirname).split(%r<(?=/)>)
545  
-    if /\A[a-z]:\z/i =~ dirs[0]
546  
-      disk = dirs.shift
547  
-      dirs[0] = disk + dirs[0]
548  
-    end
549  
-    dirs.each_index do |idx|
550  
-      path = dirs[0..idx].join('')
551  
-      Dir.mkdir path unless File.dir?(path)
552  
-    end
553  
-  end
554  
-
555  
-  def rm_f(path)
556  
-    $stderr.puts "rm -f #{path}" if verbose?
557  
-    return if no_harm?
558  
-    force_remove_file path
559  
-  end
560  
-
561  
-  def rm_rf(path)
562  
-    $stderr.puts "rm -rf #{path}" if verbose?
563  
-    return if no_harm?
564  
-    remove_tree path
565  
-  end
566  
-
567  
-  def remove_tree(path)
568  
-    if File.symlink?(path)
569  
-      remove_file path
570  
-    elsif File.dir?(path)
571  
-      remove_tree0 path
572  
-    else
573  
-      force_remove_file path
574  
-    end
575  
-  end
576  
-
577  
-  def remove_tree0(path)
578  
-    Dir.foreach(path) do |ent|
579  
-      next if ent == '.'
580  
-      next if ent == '..'
581  
-      entpath = "#{path}/#{ent}"
582  
-      if File.symlink?(entpath)
583  
-        remove_file entpath
584  
-      elsif File.dir?(entpath)
585  
-        remove_tree0 entpath
586  
-      else
587  
-        force_remove_file entpath
588  
-      end
589  
-    end
590  
-    begin
591  
-      Dir.rmdir path
592  
-    rescue Errno::ENOTEMPTY
593  
-      # directory may not be empty
594  
-    end
595  
-  end
596  
-
597  
-  def move_file(src, dest)
598  
-    force_remove_file dest
599  
-    begin
600  
-      File.rename src, dest
601  
-    rescue
602  
-      File.open(dest, 'wb') {|f|
603  
-        f.write File.binread(src)
604  
-      }
605  
-      File.chmod File.stat(src).mode, dest
606  
-      File.unlink src
607  
-    end
608  
-  end
609  
-
610  
-  def force_remove_file(path)
611  
-    begin
612  
-      remove_file path
613  
-    rescue
614  
-    end
615  
-  end
616  
-
617  
-  def remove_file(path)
618  
-    File.chmod 0777, path
619  
-    File.unlink path
620  
-  end
621  
-
622  
-  def install(from, dest, mode, prefix = nil)
623  
-    $stderr.puts "install #{from} #{dest}" if verbose?
624  
-    return if no_harm?
625  
-
626  
-    realdest = prefix ? prefix + File.expand_path(dest) : dest
627  
-    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
628  
-    str = File.binread(from)
629  
-    if diff?(str, realdest)
630  
-      verbose_off {
631  
-        rm_f realdest if File.exist?(realdest)
632  
-      }
633  
-      File.open(realdest, 'wb') {|f|
634  
-        f.write str
635  
-      }
636  
-      File.chmod mode, realdest
637  
-
638  
-      File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
639  
-        if prefix
640  
-          f.puts realdest.sub(prefix, '')
641  
-        else
642  
-          f.puts realdest
643  
-        end
644  
-      }
645  
-    end
646  
-  end
647  
-
648  
-  def diff?(new_content, path)
649  
-    return true unless File.exist?(path)
650  
-    new_content != File.binread(path)
651  
-  end
652  
-
653  
-  def command(*args)
654  
-    $stderr.puts args.join(' ') if verbose?
655  
-    system(*args) or raise RuntimeError,
656  
-        "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
657  
-  end
658  
-
659  
-  def ruby(*args)
660  
-    command config('rubyprog'), *args
661  
-  end
662  
-  
663  
-  def make(task = nil)
664  
-    command(*[config('makeprog'), task].compact)
665  
-  end
666  
-
667  
-  def extdir?(dir)
668  
-    File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
669  
-  end
670  
-
671  
-  def files_of(dir)
672  
-    Dir.open(dir) {|d|
673  
-      return d.select {|ent| File.file?("#{dir}/#{ent}") }
674  
-    }
675  
-  end
676  
-
677  
-  DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
678  
-
679  
-  def directories_of(dir)
680  
-    Dir.open(dir) {|d|
681  
-      return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
682  
-    }
683  
-  end
684  
-
685  
-end
686  
-
687  
-
688  
-# This module requires: #srcdir_root, #objdir_root, #relpath
689  
-module HookScriptAPI
690  
-
691  
-  def get_config(key)
692  
-    @config[key]
693  
-  end
694  
-
695  
-  alias config get_config
696  
-
697  
-  # obsolete: use metaconfig to change configuration
698  
-  def set_config(key, val)
699  
-    @config[key] = val
700  
-  end
701  
-
702  
-  #
703  
-  # srcdir/objdir (works only in the package directory)
704  
-  #
705  
-
706  
-  def curr_srcdir
707  
-    "#{srcdir_root()}/#{relpath()}"
708  
-  end
709  
-
710  
-  def curr_objdir
711  
-    "#{objdir_root()}/#{relpath()}"
712  
-  end
713  
-
714  
-  def srcfile(path)
715  
-    "#{curr_srcdir()}/#{path}"
716  
-  end
717  
-
718  
-  def srcexist?(path)
719  
-    File.exist?(srcfile(path))
720  
-  end
721  
-
722  
-  def srcdirectory?(path)
723  
-    File.dir?(srcfile(path))
724  
-  end
725  
-  
726  
-  def srcfile?(path)
727  
-    File.file?(srcfile(path))
728  
-  end
729  
-
730  
-  def srcentries(path = '.')
731  
-    Dir.open("#{curr_srcdir()}/#{path}") {|d|
732  
-      return d.to_a - %w(. ..)
733  
-    }
734  
-  end
735  
-
736  
-  def srcfiles(path = '.')
737  
-    srcentries(path).select {|fname|
738  
-      File.file?(File.join(curr_srcdir(), path, fname))
739  
-    }
740  
-  end
741  
-
742  
-  def srcdirectories(path = '.')
743  
-    srcentries(path).select {|fname|
744  
-      File.dir?(File.join(curr_srcdir(), path, fname))
745  
-    }
746  
-  end
747  
-
748  
-end
749  
-
750  
-
751  
-class ToplevelInstaller
752  
-
753  
-  Version   = '3.4.1'
754  
-  Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
755  
-
756  
-  TASKS = [
757  
-    [ 'all',      'do config, setup, then install' ],
758  
-    [ 'config',   'saves your configurations' ],
759  
-    [ 'show',     'shows current configuration' ],
760  
-    [ 'setup',    'compiles ruby extentions and others' ],
761  
-    [ 'install',  'installs files' ],
762  
-    [ 'test',     'run all tests in test/' ],
763  
-    [ 'clean',    "does `make clean' for each extention" ],
764  
-    [ 'distclean',"does `make distclean' for each extention" ]
765  
-  ]
766  
-
767  
-  def ToplevelInstaller.invoke
768  
-    config = ConfigTable.new(load_rbconfig())
769  
-    config.load_standard_entries
770  
-    config.load_multipackage_entries if multipackage?
771  
-    config.fixup
772  
-    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
773  
-    klass.new(File.dirname($0), config).invoke
774  
-  end
775  
-
776  
-  def ToplevelInstaller.multipackage?
777  
-    File.dir?(File.dirname($0) + '/packages')
778  
-  end
779  
-
780  
-  def ToplevelInstaller.load_rbconfig
781  
-    if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
782  
-      ARGV.delete(arg)
783  
-      load File.expand_path(arg.split(/=/, 2)[1])
784  
-      $".push 'rbconfig.rb'
785  
-    else
786  
-      require 'rbconfig'
787  
-    end
788  
-    ::Config::CONFIG
789  
-  end
790  
-
791  
-  def initialize(ardir_root, config)
792  
-    @ardir = File.expand_path(ardir_root)
793  
-    @config = config
794  
-    # cache
795  
-    @valid_task_re = nil
796  
-  end
797  
-
798  
-  def config(key)
799  
-    @config[key]
800  
-  end
801  
-
802  
-  def inspect
803  
-    "#<#{self.class} #{__id__()}>"
804  
-  end
805  
-
806  
-  def invoke
807  
-    run_metaconfigs
808  
-    case task = parsearg_global()
809  
-    when nil, 'all'
810  
-      parsearg_config
811  
-      init_installers
812  
-      exec_config
813  
-      exec_setup
814  
-      exec_install
815  
-    else
816  
-      case task
817  
-      when 'config', 'test'
818  
-        ;
819  
-      when 'clean', 'distclean'
820  
-        @config.load_savefile if File.exist?(@config.savefile)
821  
-      else
822  
-        @config.load_savefile
823  
-      end
824  
-      __send__ "parsearg_#{task}"
825  
-      init_installers
826  
-      __send__ "exec_#{task}"
827  
-    end
828  
-  end
829  
-  
830  
-  def run_metaconfigs
831  
-    @config.load_script "#{@ardir}/metaconfig"
832  
-  end
833  
-
834  
-  def init_installers
835  
-    @installer = Installer.new(@config, @ardir, File.expand_path('.'))
836  
-  end
837  
-
838  
-  #
839  
-  # Hook Script API bases
840  
-  #
841  
-
842  
-  def srcdir_root
843  
-    @ardir
844  
-  end
845  
-
846  
-  def objdir_root
847  
-    '.'
848  
-  end
849  
-
850  
-  def relpath
851  
-    '.'
852  
-  end
853  
-
854  
-  #
855  
-  # Option Parsing
856  
-  #
857  
-
858  
-  def parsearg_global
859  
-    while arg = ARGV.shift
860  
-      case arg
861  
-      when /\A\w+\z/
862  
-        setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
863  
-        return arg
864  
-      when '-q', '--quiet'
865  
-        @config.verbose = false
866  
-      when '--verbose'
867  
-        @config.verbose = true
868  
-      when '--help'
869  
-        print_usage $stdout
870  
-        exit 0
871  
-      when '--version'
872  
-        puts "#{File.basename($0)} version #{Version}"
873  
-        exit 0
874  
-      when '--copyright'
875  
-        puts Copyright
876  
-        exit 0
877  
-      else
878  
-        setup_rb_error "unknown global option '#{arg}'"
879  
-      end
880  
-    end
881  
-    nil
882  
-  end
883  
-
884  
-  def valid_task?(t)
885  
-    valid_task_re() =~ t
886  
-  end
887  
-
888  
-  def valid_task_re
889  
-    @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
890  
-  end
891  
-
892  
-  def parsearg_no_options
893  
-    unless ARGV.empty?
894  
-      task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
895  
-      setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
896  
-    end
897  
-  end
898  
-
899  
-  alias parsearg_show       parsearg_no_options
900  
-  alias parsearg_setup      parsearg_no_options
901  
-  alias parsearg_test       parsearg_no_options
902  
-  alias parsearg_clean      parsearg_no_options
903  
-  alias parsearg_distclean  parsearg_no_options
904  
-
905  
-  def parsearg_config
906  
-    evalopt = []
907  
-    set = []
908  
-    @config.config_opt = []
909  
-    while i = ARGV.shift
910  
-      if /\A--?\z/ =~ i
911  
-        @config.config_opt = ARGV.dup
912  
-        break
913  
-      end
914  
-      name, value = *@config.parse_opt(i)
915  
-      if @config.value_config?(name)
916  
-        @config[name] = value
917  
-      else
918  
-        evalopt.push [name, value]
919  
-      end
920  
-      set.push name
921  
-    end
922  
-    evalopt.each do |name, value|
923  
-      @config.lookup(name).evaluate value, @config
924  
-    end
925  
-    # Check if configuration is valid
926  
-    set.each do |n|
927  
-      @config[n] if @config.value_config?(n)
928  
-    end
929  
-  end
930  
-
931  
-  def parsearg_install
932  
-    @config.no_harm = false
933  
-    @config.install_prefix = ''
934  
-    while a = ARGV.shift
935  
-      case a
936  
-      when '--no-harm'
937  
-        @config.no_harm = true
938  
-      when /\A--prefix=/
939  
-        path = a.split(/=/, 2)[1]
940  
-        path = File.expand_path(path) unless path[0,1] == '/'
941  
-        @config.install_prefix = path
942  
-      else
943  
-        setup_rb_error "install: unknown option #{a}"
944  
-      end
945  
-    end
946  
-  end
947  
-
948  
-  def print_usage(out)
949  
-    out.puts 'Typical Installation Procedure:'
950  
-    out.puts "  $ ruby #{File.basename $0} config"
951  
-    out.puts "  $ ruby #{File.basename $0} setup"
952  
-    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
953  
-    out.puts
954  
-    out.puts 'Detailed Usage:'
955  
-    out.puts "  ruby #{File.basename $0} <global option>"
956  
-    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
957  
-
958  
-    fmt = "  %-24s %s\n"
959  
-    out.puts
960  
-    out.puts 'Global options:'
961  
-    out.printf fmt, '-q,--quiet',   'suppress message outputs'
962  
-    out.printf fmt, '   --verbose', 'output messages verbosely'
963  
-    out.printf fmt, '   --help',    'print this message'
964  
-    out.printf fmt, '   --version', 'print version and quit'
965  
-    out.printf fmt, '   --copyright',  'print copyright and quit'
966  
-    out.puts
967  
-    out.puts 'Tasks:'
968  
-    TASKS.each do |name, desc|
969  
-      out.printf fmt, name, desc
970  
-    end
971  
-
972  
-    fmt = "  %-24s %s [%s]\n"
973  
-    out.puts
974  
-    out.puts 'Options for CONFIG or ALL:'
975  
-    @config.each do |item|
976  
-      out.printf fmt, item.help_opt, item.description, item.help_default
977  
-    end
978  
-    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
979  
-    out.puts
980  
-    out.puts 'Options for INSTALL:'
981  
-    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
982  
-    out.printf fmt, '--prefix=path',  'install path prefix', ''
983  
-    out.puts
984  
-  end
985  
-
986  
-  #
987  
-  # Task Handlers
988  
-  #
989  
-
990  
-  def exec_config
991  
-    @installer.exec_config
992  
-    @config.save   # must be final
993  
-  end
994  
-