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.
- data/.index +54 -0
- data/HISTORY.md +9 -0
- data/README.md +145 -0
- data/bin/index +7 -0
- data/data/indexer/r2013/index.kwalify +175 -0
- data/data/indexer/r2013/index.yes +172 -0
- data/data/indexer/r2013/index.yesi +67 -0
- data/data/indexer/r2013/ruby.txt +35 -0
- data/data/indexer/r2013/yaml.txt +30 -0
- data/lib/indexer.rb +65 -0
- data/lib/indexer/attributes.rb +171 -0
- data/lib/indexer/command.rb +260 -0
- data/lib/indexer/components.rb +8 -0
- data/lib/indexer/components/author.rb +140 -0
- data/lib/indexer/components/conflict.rb +78 -0
- data/lib/indexer/components/copyright.rb +95 -0
- data/lib/indexer/components/dependency.rb +18 -0
- data/lib/indexer/components/organization.rb +133 -0
- data/lib/indexer/components/repository.rb +140 -0
- data/lib/indexer/components/requirement.rb +360 -0
- data/lib/indexer/components/resource.rb +209 -0
- data/lib/indexer/conversion.rb +14 -0
- data/lib/indexer/conversion/gemfile.rb +44 -0
- data/lib/indexer/conversion/gemspec.rb +114 -0
- data/lib/indexer/conversion/gemspec_exporter.rb +304 -0
- data/lib/indexer/core_ext.rb +4 -0
- data/lib/indexer/error.rb +23 -0
- data/lib/indexer/gemfile.rb +75 -0
- data/lib/indexer/importer.rb +144 -0
- data/lib/indexer/importer/file.rb +94 -0
- data/lib/indexer/importer/gemfile.rb +27 -0
- data/lib/indexer/importer/gemspec.rb +43 -0
- data/lib/indexer/importer/html.rb +289 -0
- data/lib/indexer/importer/markdown.rb +45 -0
- data/lib/indexer/importer/ruby.rb +47 -0
- data/lib/indexer/importer/version.rb +38 -0
- data/lib/indexer/importer/yaml.rb +46 -0
- data/lib/indexer/loadable.rb +159 -0
- data/lib/indexer/metadata.rb +879 -0
- data/lib/indexer/model.rb +237 -0
- data/lib/indexer/revision.rb +43 -0
- data/lib/indexer/valid.rb +287 -0
- data/lib/indexer/validator.rb +313 -0
- data/lib/indexer/version/constraint.rb +124 -0
- data/lib/indexer/version/exceptions.rb +11 -0
- data/lib/indexer/version/number.rb +497 -0
- metadata +141 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
require_relative 'components/author'
|
2
|
+
require_relative 'components/organization'
|
3
|
+
require_relative 'components/copyright'
|
4
|
+
require_relative 'components/conflict'
|
5
|
+
require_relative 'components/resource'
|
6
|
+
require_relative 'components/repository'
|
7
|
+
require_relative 'components/requirement'
|
8
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Indexer
|
2
|
+
|
3
|
+
# Author is used to model Authors and Maintainers.
|
4
|
+
#
|
5
|
+
# TODO: Should Author have an `organization` field. If so
|
6
|
+
# is it a map with `name` and `website` fields?
|
7
|
+
#
|
8
|
+
# TODO: Should we have `team` field (think Github)?
|
9
|
+
#
|
10
|
+
class Author < Model
|
11
|
+
|
12
|
+
# Parse `entry` and create Author object.
|
13
|
+
def self.parse(entry)
|
14
|
+
case entry
|
15
|
+
when Author
|
16
|
+
entry
|
17
|
+
when String
|
18
|
+
parse_string(entry)
|
19
|
+
when Array
|
20
|
+
parse_array(entry)
|
21
|
+
when Hash
|
22
|
+
new(entry)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
def self.parse_array(array)
|
28
|
+
data = {}
|
29
|
+
array.each do |value|
|
30
|
+
v = value.strip
|
31
|
+
case v
|
32
|
+
when /^(.*?)\s*\<(.*?@.*?)\>/
|
33
|
+
data[:name] = $1 unless $1.empty?
|
34
|
+
data[:email] = $2
|
35
|
+
when /^(http|https)\:/
|
36
|
+
data[:website] = v
|
37
|
+
when /\@/
|
38
|
+
data[:email] = v
|
39
|
+
else
|
40
|
+
data[:name] = v
|
41
|
+
end
|
42
|
+
end
|
43
|
+
new(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
def self.parse_string(string)
|
48
|
+
if md = /(.*?)\s*\<(.*?)\>/.match(string)
|
49
|
+
new(:name=>md[1], :email=>md[2])
|
50
|
+
else
|
51
|
+
new(:name=>string)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
def initialize(data)
|
57
|
+
super(data)
|
58
|
+
#raise ArgumentError, "person must have a name" unless name
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
def initialize_attributes
|
63
|
+
@data = {
|
64
|
+
:roles => []
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
attr :name
|
70
|
+
|
71
|
+
#
|
72
|
+
def name=(name)
|
73
|
+
Valid.oneline!(name, :name)
|
74
|
+
@data[:name] = name
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
attr :email
|
79
|
+
|
80
|
+
#
|
81
|
+
def email=(email)
|
82
|
+
Valid.email!(email, :email)
|
83
|
+
@data[:email] = email
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
attr :website
|
88
|
+
|
89
|
+
#
|
90
|
+
def website=(website)
|
91
|
+
Valid.url!(website, :website)
|
92
|
+
@data[:website] = website
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
attr :team
|
97
|
+
|
98
|
+
# TODO: validate team
|
99
|
+
def team=(team)
|
100
|
+
@data[:team] = team
|
101
|
+
end
|
102
|
+
|
103
|
+
# List of roles the person plays in the project.
|
104
|
+
# This can be any string or array of strings.
|
105
|
+
attr :roles
|
106
|
+
|
107
|
+
#
|
108
|
+
def roles=(role)
|
109
|
+
@data[:roles] = (
|
110
|
+
r = [role].flatten
|
111
|
+
r.each{ |x| Valid.oneline?(x) }
|
112
|
+
r
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
alias :role :roles
|
117
|
+
alias :role= :roles=
|
118
|
+
|
119
|
+
alias :group :roles
|
120
|
+
alias :group= :roles=
|
121
|
+
|
122
|
+
#
|
123
|
+
def to_h
|
124
|
+
h = {}
|
125
|
+
h['name'] = name
|
126
|
+
h['email'] = email if email
|
127
|
+
h['website'] = website if website
|
128
|
+
h['roles'] = roles if not roles.empty?
|
129
|
+
h
|
130
|
+
end
|
131
|
+
|
132
|
+
# CONSIDE: Only name has to be equal?
|
133
|
+
def ==(other)
|
134
|
+
return false unless Author === other
|
135
|
+
return false unless name == other.name
|
136
|
+
return true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Indexer
|
2
|
+
|
3
|
+
# The Conflict class models the name and versions of
|
4
|
+
# packages that have know incompatibilities.
|
5
|
+
#
|
6
|
+
class Conflict < Model
|
7
|
+
|
8
|
+
# Parse `data` into a Dependency instance.
|
9
|
+
#
|
10
|
+
# TODO: What about respond_to?(:to_str) for String, etc.
|
11
|
+
def self.parse(data)
|
12
|
+
case data
|
13
|
+
when String
|
14
|
+
parse_string(data)
|
15
|
+
when Array
|
16
|
+
parse_array(data)
|
17
|
+
when Hash
|
18
|
+
parse_hash(data)
|
19
|
+
else
|
20
|
+
raise(ValidationError, "Conflict")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
#
|
27
|
+
#
|
28
|
+
def self.parse_string(data)
|
29
|
+
name, version = data.split(/\s+/)
|
30
|
+
new(:name=>name, :version=>version)
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
#
|
35
|
+
def self.parse_array(data)
|
36
|
+
name, version = *data
|
37
|
+
new(:name=>name, :version=>version)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def self.parse_hash(data)
|
43
|
+
new(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
public
|
47
|
+
|
48
|
+
#
|
49
|
+
# The name of the package that causes the conflict.
|
50
|
+
#
|
51
|
+
# Yea it's *ALWAYS* THEIR fault ;-)
|
52
|
+
#
|
53
|
+
attr :name
|
54
|
+
|
55
|
+
#
|
56
|
+
# Set the name of the package.
|
57
|
+
#
|
58
|
+
def name=(name)
|
59
|
+
@data[:name] = name.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# The versions constraint of the conflicting package.
|
64
|
+
# This is used when only certain versions of the package
|
65
|
+
# are the problem.
|
66
|
+
#
|
67
|
+
attr_reader :version
|
68
|
+
|
69
|
+
#
|
70
|
+
# Set the version constraint.
|
71
|
+
#
|
72
|
+
def version=(version)
|
73
|
+
@data[:version] = Version::Constraint.parse(version)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Indexer
|
2
|
+
|
3
|
+
# Copyright class models a copyright holer, the year of copyright
|
4
|
+
# and the accosiated license.
|
5
|
+
#
|
6
|
+
class Copyright < Model
|
7
|
+
|
8
|
+
# Parse copyright entry.
|
9
|
+
#
|
10
|
+
def self.parse(copyright, default_license=nil)
|
11
|
+
case copyright
|
12
|
+
when Array
|
13
|
+
year, holder, license = *copyright
|
14
|
+
when Hash
|
15
|
+
year = copyright['year'] || copyright[:year]
|
16
|
+
holder = copyright['holder'] || copyright[:holder]
|
17
|
+
license = copyright['license'] || copyright[:license]
|
18
|
+
when String
|
19
|
+
case copyright
|
20
|
+
when /(\d\d\d\d)\s+(.*?)\s*\((.*?)\)$/
|
21
|
+
year, holder, license = $1, $2, $3
|
22
|
+
when /(\d\d\d\d)\s+(.*?)\s*$/
|
23
|
+
year, holder, license = $1, $2, nil
|
24
|
+
when /(opyright|\(c\))(.*?)\s*\((.*?)\)$/
|
25
|
+
year, holder, license = nil, $1, $2
|
26
|
+
when /(opyright|\(c\))(.*?)\s*$/
|
27
|
+
year, holder, license = nil, $1, nil
|
28
|
+
end
|
29
|
+
else
|
30
|
+
raise ValidationError, "copyright"
|
31
|
+
end
|
32
|
+
license = license || default_license
|
33
|
+
new(:holder=>holder, :year=>year, :license=>license)
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
def initialize(data)
|
38
|
+
super(data)
|
39
|
+
raise(ValidationError, "copyright must have a holder") unless holder
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
attr :year
|
44
|
+
|
45
|
+
#
|
46
|
+
attr :holder
|
47
|
+
|
48
|
+
#
|
49
|
+
attr :license
|
50
|
+
|
51
|
+
#
|
52
|
+
def year=(year)
|
53
|
+
Valid.copyright_year!(year, "copyright.year")
|
54
|
+
@data[:year] = year
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
def holder=(holder)
|
59
|
+
Valid.oneline!(holder, "copyright.holder")
|
60
|
+
@data[:holder] = holder
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
def license=(license)
|
65
|
+
if license.nil?
|
66
|
+
@data.delete(:license)
|
67
|
+
else
|
68
|
+
Valid.oneline!(license, "copyright.license")
|
69
|
+
@data[:license] = license
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Standard copyright stamp.
|
75
|
+
#
|
76
|
+
def to_s
|
77
|
+
s = ["Copyright (c)"]
|
78
|
+
s << year if year
|
79
|
+
s << holder
|
80
|
+
s << "(#{license})" if license
|
81
|
+
s.join(' ') + ". All Rights Reserved."
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
def to_h
|
86
|
+
h = {}
|
87
|
+
h['holder'] = holder
|
88
|
+
h['year'] = year if year
|
89
|
+
h['license'] = license if license
|
90
|
+
h
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Indexer
|
2
|
+
|
3
|
+
# Dependency class is essentially the same as {Requirement}, but
|
4
|
+
# a dependency represents a binary package requirement that would
|
5
|
+
# need to be installed using an operating systems own package
|
6
|
+
# management system, or installed manually.
|
7
|
+
#
|
8
|
+
# Dependency is a sublcass of {Requirement}. It only exists as a separate
|
9
|
+
# class becuase an OS package managers MIGHT require some additional
|
10
|
+
# information --but as of yet that's not the case.
|
11
|
+
#
|
12
|
+
# TODO: Why not merge the two and add a field to distinguish them?
|
13
|
+
#
|
14
|
+
class Dependency < Requirement
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Indexer
|
2
|
+
|
3
|
+
# Organization is used to model companies involved in project.
|
4
|
+
#
|
5
|
+
class Organization < Model
|
6
|
+
|
7
|
+
# Parse `entry` and create Organization object.
|
8
|
+
def self.parse(entry)
|
9
|
+
case entry
|
10
|
+
when Organization
|
11
|
+
entry
|
12
|
+
when String
|
13
|
+
parse_string(entry)
|
14
|
+
when Array
|
15
|
+
parse_array(entry)
|
16
|
+
when Hash
|
17
|
+
new(entry)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def self.parse_array(array)
|
23
|
+
data = {}
|
24
|
+
array.each do |value|
|
25
|
+
v = value.strip
|
26
|
+
case v
|
27
|
+
when /^(.*?)\s*\<(.*?@.*?)\>/
|
28
|
+
data[:name] = $1 unless $1.empty?
|
29
|
+
data[:email] = $2
|
30
|
+
when /^(http|https)\:/
|
31
|
+
data[:website] = v
|
32
|
+
when /\@/
|
33
|
+
data[:email] = v
|
34
|
+
else
|
35
|
+
data[:name] = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
new(data)
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
def self.parse_string(string)
|
43
|
+
if md = /(.*?)\s*\<(.*?)\>/.match(string)
|
44
|
+
new(:name=>md[1], :email=>md[2])
|
45
|
+
else
|
46
|
+
new(:name=>string)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
def initialize(data)
|
52
|
+
super(data)
|
53
|
+
#raise ArgumentError, "person must have a name" unless name
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
def initialize_attributes
|
58
|
+
@data = {
|
59
|
+
:roles => []
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
attr :name
|
65
|
+
|
66
|
+
#
|
67
|
+
def name=(name)
|
68
|
+
Valid.oneline!(name, :name)
|
69
|
+
@data[:name] = name
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
attr :email
|
74
|
+
|
75
|
+
#
|
76
|
+
def email=(email)
|
77
|
+
Valid.email!(email, :email)
|
78
|
+
@data[:email] = email
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
attr :website
|
83
|
+
|
84
|
+
#
|
85
|
+
def website=(website)
|
86
|
+
Valid.url!(website, :website)
|
87
|
+
@data[:website] = website
|
88
|
+
end
|
89
|
+
|
90
|
+
# List of roles the person plays in the project.
|
91
|
+
# This can be any string or array of strings.
|
92
|
+
attr :roles
|
93
|
+
|
94
|
+
#
|
95
|
+
def roles=(roles)
|
96
|
+
@data[:roles] = (
|
97
|
+
r = [roles].flatten
|
98
|
+
r.each{ |x| Valid.oneline?(x) }
|
99
|
+
r
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Signular term for #roles can be used as well.
|
104
|
+
alias :role :roles
|
105
|
+
alias :role= :roles=
|
106
|
+
|
107
|
+
# Group is a synonym for role.
|
108
|
+
alias :group :roles
|
109
|
+
alias :group= :roles=
|
110
|
+
|
111
|
+
# Team is a common synonym for role too.
|
112
|
+
alias :team :roles
|
113
|
+
alias :teams= :roles=
|
114
|
+
|
115
|
+
# Convert to simple Hash represepentation.
|
116
|
+
def to_h
|
117
|
+
h = {}
|
118
|
+
h['name'] = name
|
119
|
+
h['email'] = email if email
|
120
|
+
h['website'] = website if website
|
121
|
+
h['roles'] = roles if not roles.empty?
|
122
|
+
h
|
123
|
+
end
|
124
|
+
|
125
|
+
# CONSIDER: Only name has to be equal?
|
126
|
+
def ==(other)
|
127
|
+
return false unless Organization === other
|
128
|
+
return false unless name == other.name
|
129
|
+
return true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|