reap 6.0.2 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/CHANGES +6 -0
  2. data/COPYING +666 -395
  3. data/MANIFEST +139 -0
  4. data/NOTES +12 -0
  5. data/README +19 -163
  6. data/bin/reap-announce +7 -0
  7. data/bin/reap-check-load +8 -0
  8. data/bin/reap-check-syntax +7 -0
  9. data/bin/reap-clean +7 -0
  10. data/bin/reap-clobber +7 -0
  11. data/bin/reap-doc +7 -0
  12. data/bin/reap-doc-rdoc +7 -0
  13. data/bin/reap-doc-ri +7 -0
  14. data/bin/reap-init +69 -0
  15. data/bin/reap-inspect +7 -0
  16. data/bin/reap-install +8 -0
  17. data/bin/reap-install-gem +8 -0
  18. data/bin/reap-log +7 -0
  19. data/bin/reap-log-changes +8 -0
  20. data/bin/reap-log-notes +8 -0
  21. data/bin/reap-make +7 -0
  22. data/bin/reap-make-clean +7 -0
  23. data/bin/reap-make-distclean +7 -0
  24. data/bin/reap-make-extconf +7 -0
  25. data/bin/reap-make-static +8 -0
  26. data/bin/reap-package +8 -0
  27. data/bin/reap-package-gem +7 -0
  28. data/bin/reap-package-tgz +7 -0
  29. data/bin/reap-package-zip +7 -0
  30. data/bin/reap-prepare +7 -0
  31. data/bin/reap-publish +7 -0
  32. data/bin/reap-release +7 -0
  33. data/bin/reap-scaffold +8 -0
  34. data/bin/reap-scm-branch +7 -0
  35. data/bin/reap-scm-tag +7 -0
  36. data/bin/reap-spec +7 -0
  37. data/bin/reap-spec-doc +8 -0
  38. data/bin/reap-stamp +7 -0
  39. data/bin/reap-stats +7 -0
  40. data/bin/reap-test +7 -0
  41. data/bin/reap-test-cross +7 -0
  42. data/bin/reap-test-load +9 -0
  43. data/bin/reap-test-solo +7 -0
  44. data/bin/reap-uninstall +7 -0
  45. data/bin/reap-uninstall-gem +7 -0
  46. data/data/reap/base/CHANGES +19 -0
  47. data/data/reap/base/COPYING +674 -0
  48. data/data/reap/base/NOTES +12 -0
  49. data/data/reap/base/README +8 -0
  50. data/data/reap/build/rake/Rakefile +130 -0
  51. data/{forge/reference/installers → data/reap/build/rake}/setup.rb +155 -97
  52. data/data/reap/build/rake-lite/install.rb +79 -0
  53. data/data/reap/build/tasks/task/rdoc +211 -0
  54. data/data/reap/{setup.rb → build/tasks/task/setup} +248 -200
  55. data/data/reap/build/tasks/task/test +38 -0
  56. data/data/reap/init/meta/project.yaml +21 -0
  57. data/demo/README +15 -0
  58. data/demo/lib/foo/foo.rb +7 -0
  59. data/demo/meta/VERSION +1 -0
  60. data/demo/meta/project.yaml +21 -0
  61. data/lib/reap/application.rb +80 -0
  62. data/lib/reap/default.yaml +77 -0
  63. data/lib/reap/extensions/array.rb +50 -0
  64. data/lib/reap/extensions/hash.rb +63 -0
  65. data/lib/reap/extensions/string.rb +31 -0
  66. data/lib/reap/extensions.rb +6 -0
  67. data/lib/reap/iobject.rb +264 -0
  68. data/lib/reap/manager/announce.rb +193 -0
  69. data/lib/reap/manager/check.rb +109 -0
  70. data/lib/reap/manager/clean.rb +58 -0
  71. data/lib/reap/manager/gem.rb +200 -0
  72. data/lib/reap/manager/html.rb +69 -0
  73. data/lib/reap/manager/log.rb +214 -0
  74. data/lib/reap/manager/make.rb +109 -0
  75. data/lib/reap/manager/pack.rb +232 -0
  76. data/lib/reap/manager/publish.rb +72 -0
  77. data/lib/reap/manager/rdoc.rb +194 -0
  78. data/lib/reap/manager/release.rb +78 -0
  79. data/lib/reap/manager/rubyforge.rb +44 -0
  80. data/lib/reap/manager/scaffold.rb +138 -0
  81. data/lib/reap/manager/scm.rb +66 -0
  82. data/lib/reap/manager/site.rb +27 -0
  83. data/lib/reap/manager/spec.rb +94 -0
  84. data/lib/reap/manager/stats.rb +145 -0
  85. data/lib/reap/manager/svn.rb +76 -0
  86. data/lib/reap/manager/test.rb +389 -0
  87. data/lib/reap/manager.rb +74 -0
  88. data/lib/reap/metadata.rb +603 -0
  89. data/lib/reap/project.rb +165 -0
  90. data/lib/reap/settings.rb +67 -0
  91. data/lib/reap/systems/rubyforge.rb +737 -0
  92. data/lib/reap/systems/subversion.rb +333 -0
  93. data/lib/reap/utilities/fileutils.rb +304 -0
  94. data/lib/reap/utilities/netutils.rb +221 -0
  95. data/lib/reap/utilities/setuputils.rb +124 -0
  96. data/lib/reap/utilities/shellutils.rb +175 -0
  97. data/log/Changelog.txt +107 -0
  98. data/log/FIXME.txt +25 -0
  99. data/log/TODO.txt +72 -0
  100. data/meta/VERSION +1 -0
  101. data/meta/description +4 -0
  102. data/meta/project.yaml +20 -0
  103. data/task/man +14 -0
  104. data/task/rdoc +20 -0
  105. data/{data/reap/scaffold/standard/setup.rb → task/setup} +248 -200
  106. metadata +225 -153
  107. data/ProjectInfo +0 -105
  108. data/bin/reap +0 -5
  109. data/bin/rubytest +0 -5
  110. data/data/reap/install.rb +0 -62
  111. data/data/reap/scaffold/standard/COPYING +0 -403
  112. data/data/reap/scaffold/standard/ChangeLog +0 -0
  113. data/data/reap/scaffold/standard/INSTALL +0 -14
  114. data/data/reap/scaffold/standard/ProjectInfo +0 -77
  115. data/data/reap/scaffold/standard/README +0 -3
  116. data/data/reap/scaffold/standard/Rakefile +0 -10
  117. data/data/reap/scaffold/standard/TODO +0 -0
  118. data/data/reap/scaffold/subversion/trunk/COPYING +0 -403
  119. data/data/reap/scaffold/subversion/trunk/ChangeLog +0 -0
  120. data/data/reap/scaffold/subversion/trunk/INSTALL +0 -14
  121. data/data/reap/scaffold/subversion/trunk/ProjectInfo +0 -76
  122. data/data/reap/scaffold/subversion/trunk/README +0 -3
  123. data/data/reap/scaffold/subversion/trunk/Rakefile +0 -10
  124. data/data/reap/scaffold/subversion/trunk/TODO +0 -0
  125. data/data/reap/scaffold/subversion/trunk/setup.rb +0 -1568
  126. data/forge/ProjectInfo +0 -38
  127. data/forge/ProjectInfo.rb +0 -76
  128. data/forge/TODO +0 -10
  129. data/forge/installer.rb +0 -250
  130. data/forge/reference/Rakefile +0 -124
  131. data/forge/reference/Rakefile.htm +0 -69
  132. data/forge/reference/aRakefile +0 -60
  133. data/forge/reference/compositepublisher.rb +0 -24
  134. data/forge/reference/ftptools.rb +0 -139
  135. data/forge/reference/installers/package.rb +0 -629
  136. data/forge/reference/license-each.rb +0 -85
  137. data/forge/reference/publisher.rb +0 -75
  138. data/forge/reference/rubyforge.rb +0 -247
  139. data/forge/reference/rubyforgepublisher.rb +0 -18
  140. data/forge/reference/sshpublisher.rb +0 -47
  141. data/forge/reference/suby-cvs.rb +0 -46
  142. data/forge/scaffold.rb +0 -126
  143. data/forge/unit_runner/README +0 -6
  144. data/forge/unit_runner/commentrunner.rb +0 -62
  145. data/forge/unit_runner/cunit.rb +0 -17
  146. data/forge/unit_runner/forkedrunner.rb +0 -91
  147. data/forge/unit_runner/sample.rb +0 -16
  148. data/lib/reap/bin/reap.rb +0 -230
  149. data/lib/reap/bin/rubytest.rb +0 -53
  150. data/lib/reap/class/announce.rb +0 -220
  151. data/lib/reap/class/doap.rb +0 -80
  152. data/lib/reap/class/extest.rb +0 -146
  153. data/lib/reap/class/filer.rb +0 -62
  154. data/lib/reap/class/manifest.rb +0 -68
  155. data/lib/reap/class/package.rb +0 -576
  156. data/lib/reap/class/publish.rb +0 -152
  157. data/lib/reap/class/rdoc.rb +0 -123
  158. data/lib/reap/class/test.rb +0 -264
  159. data/lib/reap/projectinfo.rb +0 -208
  160. data/lib/reap/rake.rb +0 -42
  161. data/lib/reap/reap.rb +0 -89
  162. data/lib/reap/tasks.rb +0 -756
  163. data/lib/reap/taskutils.rb +0 -122
  164. data/note/LATEST +0 -44
  165. data/note/doap.xml +0 -28
  166. data/note/history/Rakefile-0.1 +0 -308
  167. data/sample/ProjectInfo +0 -96
  168. data/sample/Rakefile +0 -9
  169. data/sample/Reapfile +0 -11
  170. data/sample/task/demo.rb +0 -15
  171. data/setup.rb +0 -1568
  172. data/web/ProjectInfo.html +0 -75
  173. data/web/images/grape.jpg +0 -0
  174. data/web/index.html +0 -312
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Run unit tests
4
+
5
+ def test
6
+ live = ARGV.include?('--live')
7
+
8
+ unless live
9
+ $LOAD_PATH.unshift(File.expand_path('lib/core'))
10
+ $LOAD_PATH.unshift(File.expand_path('lib/more'))
11
+ end
12
+
13
+ puts "Ruby Version: #{RUBY_VERSION}"
14
+
15
+ if find = ARGV.select{|e| e !~ /^[-]/ }[0]
16
+ unless file?(find)
17
+ find = File.join(find, '**', 'test_*.rb')
18
+ end
19
+ else
20
+ find = 'test/**/test_*.rb'
21
+ end
22
+
23
+ files = Dir.glob(find)
24
+ files.each do |file|
25
+ next if File.directory?(file)
26
+ begin
27
+ puts "Loading: #{file}" if $DEBUG
28
+ load(file)
29
+ rescue LoadError
30
+ puts "Error loading: #{file}"
31
+ end
32
+ end
33
+ end
34
+
35
+ # Go!
36
+ if $0 == __FILE__
37
+ test
38
+ end
@@ -0,0 +1,21 @@
1
+ ---
2
+ title : Reap
3
+ summary : Ruby Project Assistant
4
+ description: >
5
+ Reap is a Ruby project management system.
6
+
7
+ project : reap
8
+ author : Thomas Sawyer <transfire@gmail.com>
9
+ created : "2005-08-09"
10
+ homepage : "http://reap.rubyforge.org"
11
+ repository : "http://reap.rubyforge.org/svn"
12
+ slogan : Reap Your Rewards
13
+
14
+ exclude : [ pkg, work, doc, ri ]
15
+
16
+ dependency :
17
+ - [facets, ">= 2.1.0"]
18
+
19
+ loadpath: lib/reap
20
+
21
+
data/demo/README ADDED
@@ -0,0 +1,15 @@
1
+ = Foo Demo of Reap
2
+
3
+ This is a demonstration project for playing with reap.
4
+
5
+ == On Testing
6
+
7
+ At this point Reap does not have unit tests. Reap is so predominatly
8
+ FileIO as well as configurable that it can be tricky to get strong
9
+ test coverage. So for now at least, I'm using the old fashion method
10
+ of beta testers.
11
+
12
+ To facilitate this, we have this demo project that can by played with,
13
+ and the trust --dryrun option. Always use the --dryrun option first,
14
+ until one is confident in an reap's action.
15
+
@@ -0,0 +1,7 @@
1
+
2
+ # Say hello, Gracy.
3
+
4
+ def hello
5
+ "Hello, Gracy"
6
+ end
7
+
data/demo/meta/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1 alpha (2008-02-07)
@@ -0,0 +1,21 @@
1
+ ---
2
+ project : foo
3
+
4
+ title : Foo
5
+ brief : A Very Fooy Project
6
+ description: >
7
+ Foo foo went hopping thru the forest.
8
+
9
+ author : Thomas Sawyer <transfire@gmail.com>
10
+ created : "2008-02-09"
11
+ homepage : "http://orphans.rubyforge.org"
12
+ repository : "http://orphans.rubyforge.org/svn"
13
+ slogan : Footastic
14
+
15
+ exclude : [ pkg, work, doc, ri ]
16
+
17
+ dependency :
18
+ - [facets, ">= 2.1.0"]
19
+
20
+ libpath: lib/foo
21
+
@@ -0,0 +1,80 @@
1
+ #require 'facets/ansicode'
2
+
3
+ module Reap
4
+ require 'reap/project'
5
+
6
+ # Application is the commandline interface.
7
+
8
+ class Application
9
+
10
+ attr_reader :manager
11
+
12
+ def initialize
13
+ #vector = ArgVector.new
14
+ #arguments = vector.arguments
15
+ #options = vector.options
16
+
17
+ opts = {}
18
+ opts['dryrun'] = options.delete('dryrun')
19
+ opts['trace'] = options.delete('trace')
20
+ opts['force'] = options.delete('force')
21
+ opts['verbose'] = options.delete('verbose')
22
+ opts['debug'] = options.delete('debug')
23
+ opts
24
+
25
+ @manager = Project.new(opts)
26
+
27
+ #@arguments = arguments
28
+ #@options = options
29
+ end
30
+
31
+ def argv
32
+ @argv ||= ARGV.dup
33
+ end
34
+
35
+ def arguments
36
+ @arguments ||= argv.select{ |e| e !~ /^-/ && e !~ /=/ }
37
+ end
38
+
39
+ def options
40
+ @options ||= (
41
+ pms = {}
42
+ argv.select{ |e| /[=]/ =~ e }.each do |e|
43
+ k,v = e.split('=')
44
+ k = k.sub(/^[-]{1,2}/,'')
45
+ pms.store(k,v)
46
+ end
47
+ argv.select{ |e| e =~ /^-/ && e !~ /=/ }.each do |k|
48
+ k = k.sub(/^[-]{1,2}/,'')
49
+ pms.store(k,true)
50
+ end
51
+ pms
52
+ )
53
+ end
54
+
55
+ #
56
+
57
+ def method_missing(cmd, *args)
58
+ opts = options.dup
59
+ opts['arguments'] = arguments unless arguments.empty?
60
+ args << opts
61
+ manager.invoke(cmd, *args)
62
+ end
63
+
64
+ # # TODO: Collect reap bin commands and give short descriptions.
65
+ #
66
+ # def display_commands
67
+ # cmds = Application.commands
68
+ # #cmds.sort!{ |a,b| a[0] <=> b[0] }
69
+ # size = cmds.collect{ |(k,m,v)| k.to_s.size }.max + 2
70
+ # cmds.each do |(k,m,v)|
71
+ # next unless v
72
+ # next if k.index(':') or k.index('-') unless task?
73
+ # puts " %-#{size}s # %s" % [k, v]
74
+ # end
75
+ # end
76
+ # end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,77 @@
1
+ ---
2
+ announce:
3
+ template: '{ANNOUNCE,README}{,.txt}' # Announcement template file glob.
4
+ mail_to: rubytalk@ruby-lange.org # Email address(es) to send announcemnt.
5
+ mail_from: #{metadata.email} # Message FROM address.
6
+ subject: "ANN: %s %s" # Subject of email message. Sprintf'd against name and version.
7
+ account: #{metadata.email} # Email account name [email].
8
+ domain: rubyforge.org # Your domain. (Not sure why one needs this for an email.)
9
+ server: smtp.goolge.com # Email server to route message.
10
+ port: 25 # Email server's port, if not secure.
11
+ port_secure: 465 # Email server's port, if secure.
12
+ secure: false # Uses TLS security, true or false?
13
+ login: plain # Login type: plain, cram_md5 or login.
14
+ cutoff: 30 # How many lines of changelog to provide.
15
+ check:
16
+ loadpath: #{metadata.loadpath}
17
+ exclude: []
18
+ check-syntax:
19
+ loadpath: #{metadata.loadpath}
20
+ exclude: [ext]
21
+ check-load:
22
+ loadpath: #{metadata.loadpath}
23
+ exclude: []
24
+ clean:
25
+ remove: [**/*~, **/*.bak]
26
+ log:
27
+ policy: [cap, ext] # How to save log files. (cap=capitialize, up=uppercase, low=lowercase, ext=extension)
28
+ output: log
29
+ log-notes:
30
+ loadpath: #{metadata.loadpath} # Files to search for notes.
31
+ labels: [TODO, FIXME, OPTIMIZE]
32
+ make:
33
+ extensions: #{metadata.extensions} # Defaults to ext/**/extconf.rb (NOT USED YET)
34
+ package:
35
+ formats: [zip, gem]
36
+ publish:
37
+ source: doc
38
+ webdir: ~
39
+ username: #{ENV['RUBYFORGE_USERNAME']}
40
+ protect: [usage, statcvs, statsvn, robot.txt, wiki] # Used as defaults for creating .rsync-filter (after that edit .rsync-filter)
41
+ exclude: [.svn, scrap] # Used as defaults for creating .rsync-filter (after that edit .rsync-filter)
42
+ rdoc:
43
+ template: html
44
+ output: doc/rdoc
45
+ main: 'README{,.txt}'
46
+ inline: true
47
+ merge: true
48
+ exclude: []
49
+ include: ['lib', '[A-Z]*']
50
+ adfile: doc/ads/rdoc.html
51
+ targets: ~
52
+ ri:
53
+ output: ri
54
+ exclude: []
55
+ include: #{metadata.loadpath}
56
+ release:
57
+ username: #{ENV['RUBYFORGE_USERNAME']}
58
+ changelog: 'CHANGES{,.txt}'
59
+ notelog: 'NOTES{,.txt}'
60
+ spec:
61
+ specs: [spec/**/*_spec.rb, spec/**/spec_*.rb]
62
+ loadpath: #{metadata.loadpath}
63
+ require: []
64
+ warning: false
65
+ command: spec
66
+ live: false
67
+ stats:
68
+ loadpath: #{metadata.loadpath}
69
+ exclude: ['ext']
70
+ test:
71
+ tests: test/**/{test,tc}_*.rb
72
+ loadpath: #{metadata.loadpath}
73
+ require: []
74
+ exclude: ext
75
+ command: testrb
76
+ live: false
77
+
@@ -0,0 +1,50 @@
1
+ module Reap
2
+ module Extensions
3
+
4
+ # Array Extensions
5
+
6
+ module Array
7
+
8
+ # Not empty?
9
+
10
+ def not_empty?
11
+ !empty?
12
+ end
13
+
14
+ # Convert an array into command line parameters.
15
+ # The array is accepted in the format of Ruby
16
+ # method arguments --ie. [arg1, arg2, ..., hash]
17
+
18
+ def to_console
19
+ flags = (Hash===last ? pop : {})
20
+ flags = flags.to_console
21
+ flags + ' ' + join(" ")
22
+ end
23
+ alias_method :to_params, :to_console
24
+
25
+ # def to_console
26
+ # flags = (Hash===last ? pop : {})
27
+ # flags = flags.collect do |f,v|
28
+ # m = f.to_s.size == 1 ? '-' : '--'
29
+ # case v
30
+ # when Array
31
+ # v.collect{ |e| "#{m}#{f} '#{e}'" }.join(' ')
32
+ # when true
33
+ # "#{m}#{f}"
34
+ # when false, nil
35
+ # ''
36
+ # else
37
+ # "#{m}#{f} '#{v}'"
38
+ # end
39
+ # end
40
+ # return (flags + self).join(" ")
41
+ # end
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ class Array #:nodoc:
49
+ include Reap::Extensions::Array
50
+ end
@@ -0,0 +1,63 @@
1
+ require 'ostruct'
2
+
3
+ module Reap
4
+ module Extensions
5
+
6
+ #
7
+
8
+ module Hash
9
+
10
+ # Convert an array into command line parameters.
11
+ # The array is accepted in the format of Ruby
12
+ # method arguments --ie. [arg1, arg2, ..., hash]
13
+
14
+ def to_console
15
+ flags = collect do |f,v|
16
+ m = f.to_s.size == 1 ? '-' : '--'
17
+ case v
18
+ when Array
19
+ v.collect{ |e| "#{m}#{f}='#{e}'" }.join(' ')
20
+ when true
21
+ "#{m}#{f}"
22
+ when false, nil
23
+ ''
24
+ else
25
+ "#{m}#{f}='#{v}'"
26
+ end
27
+ end
28
+ flags.join(" ")
29
+ end
30
+
31
+ # Turn a hash into arguments.
32
+ #
33
+ # h = { :list => [1,2], :base => "HI" }
34
+ # h.argumentize #=> [ [], { :list => [1,2], :base => "HI" } ]
35
+ # h.argumentize(:list) #=> [ [1,2], { :base => "HI" } ]
36
+ #
37
+ def argumentize(args_field=nil)
38
+ config = dup
39
+ if args_field
40
+ args = [config.delete(args_field)].flatten.compact
41
+ else
42
+ args = []
43
+ end
44
+ args << config
45
+ return args
46
+ end
47
+
48
+ alias_method :command_vector, :argumentize
49
+
50
+ #
51
+
52
+ def to_ostruct
53
+ OpenStruct.new(self)
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+
61
+ class Hash #:nodoc:
62
+ include Reap::Extensions::Hash
63
+ end
@@ -0,0 +1,31 @@
1
+ module Reap
2
+ module Extensions
3
+
4
+ # String Extensions
5
+
6
+ module String
7
+
8
+ # Find actual filename (casefolding) and returns it.
9
+ # Returns nil if no file is found.
10
+
11
+ def to_actual_filename
12
+ Dir.glob(self, File::FNM_CASEFOLD).first
13
+ end
14
+
15
+ # Find actual filename (casefolding) and replace string with it.
16
+ # If file not found, string remains the same and method returns nil.
17
+
18
+ def to_actual_filename!
19
+ filename = to_actual_filename
20
+ replace(filename) if filename
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ class String #:nodoc:
29
+ include Reap::Extensions::String
30
+ end
31
+
@@ -0,0 +1,6 @@
1
+ require 'facets/dir/multiglob'
2
+
3
+ require 'reap/extensions/array'
4
+ require 'reap/extensions/hash'
5
+ require 'reap/extensions/string'
6
+
@@ -0,0 +1,264 @@
1
+ # = TITLE:
2
+ #
3
+ # Information
4
+ #
5
+ # = COPYING:
6
+ #
7
+ # Copyright (c) 2007 Psi T Corp.
8
+ #
9
+ # This file is part of the ProUtils' Ratch program.
10
+ #
11
+ # Ratch is free software: you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation, either version 3 of the License, or
14
+ # (at your option) any later version.
15
+ #
16
+ # Ratch is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with Ratch. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ require 'yaml'
25
+ require 'facets/hash/rekey'
26
+
27
+
28
+ module Reap
29
+
30
+ #
31
+
32
+ class InfoObject
33
+
34
+ class << self
35
+
36
+ def instance_attributes
37
+ @attributes ||= []
38
+ end
39
+
40
+ # Define an attribute.
41
+
42
+ def attr_accessor(name, *aliases, &blk)
43
+ instance_attributes << name.to_s
44
+ instance_attributes.uniq!
45
+ if blk
46
+ define_method(name, &blk)
47
+ attr_writer(name)
48
+ else
49
+ super(name)
50
+ end
51
+ aliases.each{ |aliaz| alias_accessor(aliaz, name) }
52
+ end
53
+
54
+ # Define an attribute alias.
55
+
56
+ def alias_accessor(aliaz, name)
57
+ alias_method aliaz, name
58
+ alias_method "#{aliaz}=", "#{name}="
59
+ end
60
+
61
+ #
62
+
63
+ def alias_method(aliaz, name)
64
+ super
65
+ if method_defined?("#{name}=")
66
+ super("#{aliaz}=", "#{name}=")
67
+ end
68
+ end
69
+
70
+
71
+ def validation
72
+ @validation ||= []
73
+ end
74
+
75
+ def validate(message, &block)
76
+ validation << [message, block]
77
+ end
78
+
79
+ # Does this class provide open access?
80
+ #
81
+ #def open_access?
82
+ # false
83
+ #end
84
+
85
+ end
86
+
87
+
88
+ def instance_data
89
+ @instance_data ||= {}
90
+ end
91
+
92
+ # List attributes. (Needed?)
93
+
94
+ def attributes
95
+ self.class.instance_attributes
96
+ end
97
+
98
+
99
+ # Initialize
100
+ ####################
101
+
102
+ def initialize(data={})
103
+ update(data)
104
+ end
105
+
106
+ def update(data)
107
+ instance_data.update(data.rekey(:to_s))
108
+
109
+ data.each do |k,v|
110
+ send("#{k}=", v) rescue nil
111
+ end
112
+
113
+ # TODO Could add yield(self) via:
114
+ #yld.to_h.each do |k,v|
115
+ # send( "#{k}=", v ) rescue nil
116
+ #end
117
+ end
118
+
119
+
120
+ # Access
121
+ ####################
122
+
123
+ # Fetch attribute value, but return nil if it doesn't exist.
124
+ #--
125
+ # TODO Use in method missing instead?
126
+ #++
127
+
128
+ def [](name)
129
+ begin
130
+ h = send(name)
131
+ rescue NoMethodError
132
+ h = nil
133
+ end
134
+ end
135
+
136
+ # Gathers a group of info hash entries into a merged hash.
137
+ # The +names+ are taken in most to least significant order.
138
+ #
139
+ # gather(:package)
140
+ #
141
+ # TODO Change name of this method to something better?
142
+
143
+ def gather( *names )
144
+ result = names.inject({}) do |hash,name|
145
+ attributes.each do |n|
146
+ if n.to_s =~ /^#{name}_(.*?)$/
147
+ hash[$1] = self[n.to_s] if self[n.to_s]
148
+ end
149
+ end
150
+ hash
151
+ end
152
+ result
153
+ end
154
+
155
+ # Collects a group of info entries into a hash.
156
+ # Arguments are a list of info entry names and/or
157
+ # a hash or new name to info entry name.
158
+ #
159
+ # select(:name, :version, :date => :released)
160
+ #
161
+ # This is used to collect info to pass to tools.
162
+
163
+ def select( *args )
164
+ maps = (Hash === args.last ? args.pop : {})
165
+ h = {}
166
+ args.each{ |k| h[k.to_s] = self[k] }
167
+ maps.each{ |k, i| h[k.to_s] = self[i] }
168
+ h
169
+ end
170
+
171
+
172
+ # Validation
173
+ ######################
174
+
175
+ #
176
+ def valid?
177
+ begin
178
+ validate
179
+ return true
180
+ rescue TypeError
181
+ return false
182
+ end
183
+ end
184
+
185
+ #
186
+ def validate
187
+ self.class.validation.each do |message, block|
188
+ raise(TypeError, message) unless instance_eval(&block)
189
+ end
190
+ end
191
+
192
+ alias_method :assert_valid, :validate
193
+
194
+
195
+ # Conversion
196
+ #################
197
+
198
+ # Order of attributes for yaml conversion.
199
+
200
+ def to_yaml_properties
201
+ attributes.collect{ |a| "@#{a}" }
202
+ end
203
+
204
+ # Use YAML format.
205
+
206
+ def to_yaml( opts={} )
207
+ require 'yaml'
208
+ super
209
+ end
210
+
211
+ # For yaml conversion, no tag.
212
+
213
+ def taguri; nil; end
214
+
215
+ # Convert to hash.
216
+
217
+ def to_hash
218
+ attributes.inject({}) do |h, a|
219
+ v = self[a.to_s] #send(a)
220
+ h[a] = v unless v.nil?
221
+ h
222
+ end
223
+ end
224
+ alias_method :to_h, :to_hash
225
+
226
+ # Use generic XML format.
227
+
228
+ def to_xml( opts={} )
229
+ raise "not yet implemented"
230
+ end
231
+
232
+ # # Use XOXO microformat.
233
+ #
234
+ # def to_xoxo( opts={} )
235
+ # begin
236
+ # require 'blow/xoxo' # EXTERNAL DEPENDENCY!
237
+ # rescue LoadError
238
+ # puts 'Blow (http://blow.rubyforge.org) is required to use XOXO format'
239
+ # end
240
+ # XOXO.dump(self.to_hash, opts)
241
+ # end
242
+
243
+
244
+ # Arbitrary information
245
+ ############################
246
+
247
+ # # TODO Perhaps not define this at all if open_access? is false.
248
+ #
249
+ # def method_missing( s, *a, &b )
250
+ # super unless self.class.open_access?
251
+ # s = s.to_s
252
+ # if s[-1,1] == '='
253
+ # (class << self; self; end).class_eval do
254
+ # attr_accessor s.chomp('=')
255
+ # end
256
+ # send(s,*a,&b)
257
+ # else
258
+ # nil #super
259
+ # end
260
+ # end
261
+
262
+ end
263
+
264
+ end