reap 6.0.2 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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