indexer 0.1.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 (47) hide show
  1. data/.index +54 -0
  2. data/HISTORY.md +9 -0
  3. data/README.md +145 -0
  4. data/bin/index +7 -0
  5. data/data/indexer/r2013/index.kwalify +175 -0
  6. data/data/indexer/r2013/index.yes +172 -0
  7. data/data/indexer/r2013/index.yesi +67 -0
  8. data/data/indexer/r2013/ruby.txt +35 -0
  9. data/data/indexer/r2013/yaml.txt +30 -0
  10. data/lib/indexer.rb +65 -0
  11. data/lib/indexer/attributes.rb +171 -0
  12. data/lib/indexer/command.rb +260 -0
  13. data/lib/indexer/components.rb +8 -0
  14. data/lib/indexer/components/author.rb +140 -0
  15. data/lib/indexer/components/conflict.rb +78 -0
  16. data/lib/indexer/components/copyright.rb +95 -0
  17. data/lib/indexer/components/dependency.rb +18 -0
  18. data/lib/indexer/components/organization.rb +133 -0
  19. data/lib/indexer/components/repository.rb +140 -0
  20. data/lib/indexer/components/requirement.rb +360 -0
  21. data/lib/indexer/components/resource.rb +209 -0
  22. data/lib/indexer/conversion.rb +14 -0
  23. data/lib/indexer/conversion/gemfile.rb +44 -0
  24. data/lib/indexer/conversion/gemspec.rb +114 -0
  25. data/lib/indexer/conversion/gemspec_exporter.rb +304 -0
  26. data/lib/indexer/core_ext.rb +4 -0
  27. data/lib/indexer/error.rb +23 -0
  28. data/lib/indexer/gemfile.rb +75 -0
  29. data/lib/indexer/importer.rb +144 -0
  30. data/lib/indexer/importer/file.rb +94 -0
  31. data/lib/indexer/importer/gemfile.rb +27 -0
  32. data/lib/indexer/importer/gemspec.rb +43 -0
  33. data/lib/indexer/importer/html.rb +289 -0
  34. data/lib/indexer/importer/markdown.rb +45 -0
  35. data/lib/indexer/importer/ruby.rb +47 -0
  36. data/lib/indexer/importer/version.rb +38 -0
  37. data/lib/indexer/importer/yaml.rb +46 -0
  38. data/lib/indexer/loadable.rb +159 -0
  39. data/lib/indexer/metadata.rb +879 -0
  40. data/lib/indexer/model.rb +237 -0
  41. data/lib/indexer/revision.rb +43 -0
  42. data/lib/indexer/valid.rb +287 -0
  43. data/lib/indexer/validator.rb +313 -0
  44. data/lib/indexer/version/constraint.rb +124 -0
  45. data/lib/indexer/version/exceptions.rb +11 -0
  46. data/lib/indexer/version/number.rb +497 -0
  47. metadata +141 -0
@@ -0,0 +1,67 @@
1
+ ---
2
+ HEADER-DIVISION:
3
+ apply-tag: "!http://rubyworks.github.org/dotruby"
4
+ description:
5
+ Specification for canonical .ruby files.
6
+ author: trans <transfire@gmail.com>
7
+
8
+ TEMPLATE-DIVISION:
9
+ revision : PIC ZZ9; TAG !!int; REQ true
10
+ name : PIC AW[29]; REQ true
11
+ version : PIC ZZ9{.ZZ9}[5]; REX semver
12
+ codename : PIC X[30]
13
+ title : PIC X[30]
14
+ date : PIC 9999-99-99{_99:99:99}[0,1]
15
+ created : PIC 9999-99-99{_99:99:99}[0,1]
16
+ summary : PIC X[79]
17
+ description: PIC X[1000]
18
+ authors:
19
+ - name : PIC X[30]
20
+ email : REX email
21
+ url : REX url
22
+ roles :
23
+ - PIC X[30]
24
+ suite: PIC X[30]
25
+ organization: PIC X[30]
26
+ copyrights:
27
+ - holder : PIC X[30]
28
+ year : PIC 9999{-9999}[0,1]
29
+ license : PIC W[30]
30
+ requirements: &r
31
+ - name: PIC W[30]
32
+ version: REX //
33
+ groups:
34
+ - PIC W[30]
35
+ development: TAG !!bool
36
+ optional: TAG !!bool
37
+ engine:
38
+ - name: PIC W[30]
39
+ version: PIC W[30]
40
+ platform:
41
+ - PIC W[30]
42
+ repository:
43
+ name: PIC W[30]
44
+ uri: REX uri
45
+ scm: PIC W[15]
46
+ dependencies: *r
47
+ conflicts:
48
+ - name: PIC W[30]
49
+ version: PIC X[30]
50
+ substitues:
51
+ - PIC W[30]
52
+ replaces:
53
+ - PIC W[30]
54
+ resources:
55
+ - name: PIC X[30]
56
+ uri: REX uri
57
+ repositories:
58
+ - name: PIC X[30]
59
+ uri: REX uri
60
+ scm: PIC W[30]
61
+ load_path:
62
+ - REX file; DEF 'lib'
63
+ install_message: PIC X[1000]
64
+ extra: {}
65
+
66
+ CONSTRAINTS-DIVISION: {}
67
+
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ name <%= name.inspect %>
4
+ version <%= version.inspect %>
5
+ title <%= title.inspect %>
6
+ summary <%= summary.inspect %>
7
+
8
+ description \
9
+ <% description.inspect %>
10
+
11
+ authors [
12
+ 'you <you@foomail.com>'
13
+ ]
14
+
15
+ requirements [
16
+ 'foo 1.0~',
17
+ 'rake (build)',
18
+ 'test (test)'
19
+ ]
20
+
21
+ repositories {
22
+ 'upstream' => 'http://github.com/organization/app_name/<%= name %>.git'
23
+ }
24
+
25
+ resources {
26
+ 'home' => 'http://organization.github.org/<%= name %>',
27
+ 'code' => 'http://github.com/organization/<%= name %>'
28
+ }
29
+
30
+ categories ['foo']
31
+
32
+ copyrights: [
33
+ '2012 Your Name (MIT)'
34
+ ]
35
+
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: <%= name %>
3
+ version: <%= version %>
4
+ title: <%= title %>
5
+ summary: <%= summary %>
6
+
7
+ description:
8
+ <%= description %>
9
+
10
+ authors:
11
+ - you <you@foomail.com>
12
+
13
+ requirements:
14
+ - dependency 1.0~
15
+ - rake (build)
16
+ - test (test)
17
+
18
+ repositories:
19
+ upstream: http://github.com/organization/app_name/app_name.git
20
+
21
+ resources:
22
+ home: http://organization.github.org/app_name
23
+ code: http://github.com/organization/app_name
24
+
25
+ categories:
26
+ - foo
27
+
28
+ copyrights:
29
+ - 2012 Your Name (MIT)
30
+
@@ -0,0 +1,65 @@
1
+ module Indexer
2
+ # Name of this program.
3
+ NAME = 'indexer'
4
+
5
+ # Current stable revision of the specification (by year).
6
+ REVISION = 2013
7
+
8
+ # File name of locked metadata file.
9
+ LOCK_FILE = '.index'
10
+
11
+ # Default metadata file name for use by end-developer.
12
+ USER_FILES = '{Indexfile,Indexfile.rb,Metadata,Metadata.yml,Metadata.yaml}'
13
+
14
+ # Indexer library directory.
15
+ LIBDIR = File.dirname(__FILE__) + '/indexer'
16
+
17
+ # Indexer library directory.
18
+ DATADIR = File.dirname(__FILE__) + '/../data/indexer'
19
+
20
+ # Metadata from the project's `indexer.yml` index file.
21
+ # This is used as a fallback for #const_missing.
22
+ #
23
+ # Returns [Hash] of metadata.
24
+ def self.index
25
+ @index ||= (
26
+ require 'yaml'
27
+ dir = File.dirname(__FILE__)
28
+ file = Dir[File.join(dir, "{#{NAME}.yml,../.index}")].first
29
+ file ? YAML.load_file(file) : {}
30
+ )
31
+ end
32
+
33
+ # Project metadata via RubyGems, fallback to index file.
34
+ #
35
+ # TODO: The #to_s on the gemspec return value is a bit too simplistic. But how to fix?
36
+ # The goal is reduce the value to a basic type (String, Hash, Array, Numeric).
37
+ #
38
+ def self.const_missing(const_name)
39
+ name = const_name.to_s.downcase
40
+ begin
41
+ Gem.loaded_specs[NAME].send(name).to_s
42
+ rescue StandardError
43
+ index[name] || super(const_name)
44
+ end
45
+ end
46
+ end
47
+
48
+ require 'yaml'
49
+ require 'time'
50
+
51
+ require 'indexer/version/exceptions'
52
+ require 'indexer/version/number'
53
+ require 'indexer/version/constraint'
54
+
55
+ require 'indexer/core_ext'
56
+ require 'indexer/command'
57
+ require 'indexer/error'
58
+ require 'indexer/valid'
59
+ require 'indexer/revision'
60
+
61
+ require 'indexer/model'
62
+ require 'indexer/components'
63
+ require 'indexer/metadata'
64
+ require 'indexer/importer'
65
+
@@ -0,0 +1,171 @@
1
+ module Indexer
2
+
3
+ # Tracks supported attributes.
4
+ def self.attributes
5
+ @attributes ||= []
6
+ end
7
+
8
+ # The Attributes module defines all of the accepted metadata fields.
9
+ module Attributes
10
+
11
+ # Define attribute, plus track it.
12
+ def self.attr_accessor(name)
13
+ Indexer.attributes << name.to_sym
14
+
15
+ class_eval %{
16
+ def #{name}
17
+ @data[:#{name}]
18
+ end
19
+ def #{name}=(val)
20
+ @data[:#{name}] = val
21
+ end
22
+ }
23
+ end
24
+
25
+ #
26
+ def attributes
27
+ Indexer.attributes
28
+ end
29
+
30
+ # The revision of ruby meta specification.
31
+ attr_accessor :revision
32
+
33
+ #def revision
34
+ # REVISION
35
+ #end
36
+
37
+ # The type of ruby meta specification.
38
+ attr_accessor :type
39
+
40
+ # Files from which to import metadata.
41
+ attr_accessor :sources
42
+
43
+ # The name of the project
44
+ attr_accessor :name
45
+
46
+ # The version of the project
47
+ attr_accessor :version
48
+
49
+ # The nick name for the particular version, e.g. "Lucid Lynx".
50
+ attr_accessor :codename
51
+
52
+ # The date of this version.
53
+ attr_accessor :date
54
+
55
+ # The project title
56
+ attr_accessor :title
57
+
58
+ # The project summary
59
+ attr_accessor :summary
60
+
61
+ # The project description
62
+ attr_accessor :description
63
+
64
+ # The suite to which the project belongs.
65
+ attr_accessor :suite
66
+
67
+ # The copyrights and licenses of the project.
68
+ attr_accessor :copyrights
69
+
70
+ # The authors of the project
71
+ # The first author should be the primary contact.
72
+ attr_accessor :authors
73
+
74
+ # The organizations involved with the project.
75
+ attr_accessor :organizations
76
+
77
+ # The resource locators for the project.
78
+ attr_accessor :resources
79
+
80
+ # The repository URLs for the project.
81
+ attr_accessor :repositories
82
+
83
+ # TODO: Might webcvs simply be taken from the first repository instead?
84
+
85
+ # URI for linking to source code.
86
+ attr_accessor :webcvs
87
+
88
+ # The directories to search within the project when requiring files
89
+ attr_accessor :load_path # :loadpath or :require_paths ?
90
+
91
+ # List of language engine/version family supported.
92
+ attr_accessor :engines
93
+
94
+ # List of platforms supported.
95
+ attr_accessor :platforms
96
+
97
+ # The names of the executable scripts
98
+ # NOTE: Do not need, executable should alwasy by in bin/, right?
99
+ #attr_accessor :executables
100
+
101
+ # The packages this package requires to function.
102
+ attr_accessor :requirements #:dependencies
103
+
104
+ # A list of packages that provide more or less the same functionality.
105
+ # A good example is for a markdown library.
106
+ #
107
+ # alternatives:
108
+ # - rdiscount
109
+ # - redcarpet
110
+ # - BlueCloth
111
+ #
112
+ attr_accessor :alternatives
113
+
114
+ # The packages with which this project cannot function.
115
+ attr_accessor :conflicts
116
+
117
+ #
118
+ # NOTE: This is a Debian concept. Is it useful?
119
+ #attr_accessor :provides
120
+
121
+ # Categories can be used to help clarify the purpose of
122
+ # a project, e.g. `testing` or `rest`. There are no standard
123
+ # categories, just use common sense. Categories must be single-line
124
+ # strings. When comparisons are made they will be downcased.
125
+ attr_accessor :categories
126
+
127
+ # The version of Ruby required by the project
128
+ # NOTE: is it possible to to makes this a part of ordinary requirements?
129
+ #attr_accessor :required_ruby_version
130
+
131
+ # The post-installation message.
132
+ attr_accessor :install_message
133
+
134
+ # The date the project was started.
135
+ attr_accessor :created
136
+
137
+ # The toplevel namespace of API, e.g. `module Foo` or `class Bar`.
138
+ # NOTE: how to best handle this?
139
+ attr_accessor :namespace
140
+
141
+ # Any user-defined extraneous metadata.
142
+ #attr_accessor :extra
143
+
144
+ protected
145
+
146
+ #
147
+ # Initializes the {Metadata} attributes.
148
+ #
149
+ # @todo Is it okay to default type to `ruby`?
150
+ #
151
+ def initialize_attributes
152
+ @data = {
153
+ :revision => REVISION,
154
+ :type => 'ruby',
155
+ :sources => [],
156
+ :authors => [],
157
+ :organizations => [],
158
+ :copyrights => [],
159
+ :alternatives => [],
160
+ :requirements => [],
161
+ :conflicts => [],
162
+ :repositories => [],
163
+ :resources => [],
164
+ :categories => [],
165
+ :load_path => ['lib']
166
+ }
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,260 @@
1
+ module Indexer
2
+
3
+ # Command line interface.
4
+ #
5
+ class Command
6
+
7
+ #
8
+ # Shortcut to `new.run(argv)`.
9
+ #
10
+ def self.run(argv=ARGV)
11
+ new.run(argv)
12
+ end
13
+
14
+ #
15
+ #
16
+ #
17
+ def initialize
18
+ @force = false
19
+ @stdout = false
20
+ @static = false
21
+ end
22
+
23
+ #
24
+ #
25
+ #
26
+ def run(argv=ARGV)
27
+ cmd = nil
28
+ args = cli(argv,
29
+ '-d --debug' => lambda{ $DEBUG = true },
30
+ '-w --warn' => lambda{ $VERBOSE = true },
31
+ '-f --force' => lambda{ @force = true },
32
+ '-o --stdout' => lambda{ @stdout = true },
33
+ '-s --static' => lambda{ @static = true },
34
+ '-u --using' => lambda{ no_cmd!(cmd); cmd = :using },
35
+ '-a --adding' => lambda{ no_cmd!(cmd); cmd = :adding },
36
+ '-g --generate' => lambda{ no_cmd!(cmd); cmd = :generate },
37
+ '-h --help' => lambda{ no_cmd!(cmd); cmd = :help }
38
+ )
39
+ send(cmd || :show, *args)
40
+ rescue => error
41
+ raise error if $DEBUG
42
+ $stderr.puts "#{File.basename($0)} error: #{error}"
43
+ exit -1
44
+ end
45
+
46
+ #
47
+ # Show returns information from the `.index` file. Before doing so
48
+ # it always ensures the `.index` file is up to date. To suppress
49
+ # this update use the `-S/--static` option.
50
+ #
51
+ def show(*fields)
52
+ if @static
53
+ if Metadata.exists?
54
+ metadata = Metadata.open
55
+ puts metadata.about(*fields)
56
+ else
57
+ raise Error.exception(".index file not found", IOError)
58
+ end
59
+ else
60
+ Metadata.lock!(:force=>@force)
61
+ unless fields.empty?
62
+ metadata = Metadata.open
63
+ puts metadata.about(*fields)
64
+ end
65
+ end
66
+ end
67
+
68
+ #
69
+ def using(*sources)
70
+ raise Error.exception("no sources given") if sources.empty?
71
+ metadata = Metadata.lock(sources, :force=>true)
72
+ if @stdout
73
+ puts metadata.to_yaml
74
+ else
75
+ metadata.save!
76
+ end
77
+ end
78
+
79
+ #
80
+ def adding(*sources)
81
+ raise Error.exception("no sources given") if sources.empty?
82
+ metadata = Metadata.open
83
+ metadata = Metadata.lock((metadata.sources & sources), :force=>true)
84
+ if @stdout
85
+ puts metadata.to_yaml
86
+ else
87
+ metadata.save!
88
+ end
89
+ end
90
+
91
+ #
92
+ def generate(type, outfile=nil)
93
+ case type.downcase
94
+ when 'gemspec'
95
+ create_gemspec(outfile)
96
+ when 'ruby', 'index.rb', 'indexfile'
97
+ create_ruby(outfile)
98
+ when 'yaml', 'index.yml', 'index.yaml'
99
+ create_yaml(outfile)
100
+ else
101
+ raise Error.exception("unknown file type")
102
+ end
103
+ end
104
+
105
+ #
106
+ def help
107
+ puts <<-END
108
+ index [command-option] [options...] [arguments...]
109
+
110
+ (none) [fields...] update index and provide information from index
111
+ -u --using <sources...> create index using given information sources
112
+ -a --adding <sources...> update index appending additional information sources
113
+ -r --remove <sources...> update index removing given information sources
114
+ -g --generate <type> [fname] generate a file (gemspec, indexfile, metadata)
115
+ -h --help show this help message
116
+
117
+ -o --stdout output to console instead of saving to file
118
+ -f --force force protected file overwrite if file already exists or is up to date
119
+ -s --static keep index as is or generate static format if generator supports it
120
+ END
121
+ end
122
+
123
+ private
124
+
125
+ #
126
+ def create_ruby(outfile=nil)
127
+ require 'erb'
128
+
129
+ outfile = "Indexfile" unless outfile
130
+
131
+ if File.exist?(outfile) && !(@stdout or @force)
132
+ raise Error.exception("#{outfile} file already exists", IOError)
133
+ end
134
+
135
+ template_dir = File.join(DATADIR, "r#{REVISION}")
136
+ template_file = File.join(template_dir, 'ruby.txt')
137
+
138
+ if Metadata.exists?
139
+ metadata = Metadata.open
140
+ else
141
+ metadata = Metadata.new
142
+ end
143
+
144
+ # this is a little weak, but...
145
+ if gemspec = Dir['{,pkg/}*.gemspec'].first
146
+ metadata.import_gemspec(gemspec)
147
+ end
148
+
149
+ template = ERB.new(File.read(template_file))
150
+ result = template.result(Form.new(metadata).get_binding)
151
+
152
+ if @stdout
153
+ puts result
154
+ else
155
+ File.open(outfile, 'w') do |f|
156
+ f << result
157
+ end
158
+ end
159
+ end
160
+
161
+ #
162
+ def create_yaml(outfile)
163
+ require 'erb'
164
+
165
+ outfile = "Index.yml" unless outfile
166
+
167
+ if File.exist?(outfile) && !(@stdout or @force)
168
+ raise Error.exception("#{outfile} file already exists", IOError)
169
+ end
170
+
171
+ template_dir = File.join(DATADIR, "r#{REVISION}")
172
+ template_file = File.join(template_dir, 'yaml.txt')
173
+
174
+ if Metadata.exists?
175
+ metadata = Metadata.open
176
+ else
177
+ metadata = Metadata.new
178
+ end
179
+
180
+ # this is a little weak, but...
181
+ if gemspec = Dir['{,pkg/}*.gemspec'].first
182
+ metadata.import_gemspec(gemspec)
183
+ end
184
+
185
+ template = ERB.new(File.read(template_file))
186
+ result = template.result(Form.new(metadata).get_binding)
187
+
188
+ if @stdout
189
+ puts result
190
+ else
191
+ File.open(outfile, 'w') do |f|
192
+ f << result
193
+ end
194
+ end
195
+ end
196
+
197
+ #
198
+ # Create a .gemspec file for use with indexer. Or a static one if `--static` option is used.
199
+ #
200
+ def create_gemspec(file=nil)
201
+ if file
202
+ if File.extname(file) != '.gemspec'
203
+ warn "gemspec file without .gemspec extension"
204
+ end
205
+ else
206
+ # TODO: look for pre-existent gemspec, but to do that right we should get
207
+ # the name from the .index file if it eixts.
208
+ file = Dir['{,*,pkg/*}.gemspec'].first || '.gemspec'
209
+ end
210
+
211
+ #lib_file = File.join(DIR, "v#{which}", "gemspec.rb")
212
+
213
+ if file && File.exist?(file) && !@force && !@stdout
214
+ raise Error.exception("`#{file}' already exists, use -f/--force to overwrite.")
215
+ end
216
+
217
+ text = GemspecExporter.source_code + "\nIndexer::GemspecExporter.gemspec"
218
+
219
+ if @static
220
+ spec = eval(text, CleanBinding.new, file)
221
+ text = spec.to_yaml
222
+ end
223
+
224
+ if @stdout
225
+ puts text
226
+ else
227
+ File.open(file, 'w') do |f|
228
+ f << text
229
+ end
230
+ end
231
+ end
232
+
233
+ #
234
+ def no_cmd!(cmd)
235
+ raise Error.exception("more than one command flag") if cmd
236
+ end
237
+
238
+ # Helper class for generating template.
239
+ #
240
+ class Form
241
+ def initialize(metadata)
242
+ @metadata = metadata
243
+ end
244
+ def method_missing(s, *a, &b)
245
+ @metadata.public_send(s, *a, &b) || '<fill-out #{s}>'
246
+ end
247
+ def get_binding; binding; end
248
+ end
249
+
250
+ #
251
+ #
252
+ module CleanBinding
253
+ def self.new
254
+ binding
255
+ end
256
+ end
257
+
258
+ end
259
+
260
+ end