reapack-index 1.0 → 1.1beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/reapack/index.rb +10 -13
- data/lib/reapack/index/cli.rb +6 -3
- data/lib/reapack/index/cli/options.rb +22 -12
- data/lib/reapack/index/gem_version.rb +1 -1
- data/lib/reapack/index/git.rb +1 -1
- data/lib/reapack/index/metadata.rb +46 -6
- data/lib/reapack/index/package.rb +31 -6
- data/lib/reapack/index/scanner.rb +54 -13
- data/lib/reapack/index/version.rb +3 -4
- data/reapack-index.gemspec +1 -1
- data/setup/reapack-index.nsi +2 -2
- data/test/cli/test_metadata.rb +13 -0
- data/test/cli/test_scan.rb +14 -0
- data/test/data/index.xml +1 -1
- data/test/index/test_metadata.rb +5 -5
- data/test/index/test_scan.rb +31 -103
- data/test/scanner/test_makeurl.rb +102 -0
- data/test/scanner/test_validation.rb +126 -0
- data/test/test_git.rb +10 -0
- data/test/test_index.rb +35 -25
- data/test/test_metadata.rb +115 -19
- data/test/test_package.rb +55 -5
- data/test/test_scanner.rb +113 -140
- data/test/test_source.rb +16 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74ff4d70819b98251948bbe5a7e7767e7b9e3b0c
|
4
|
+
data.tar.gz: 1887659545c7d20019c17e740a1aaa48f078ae6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f47b75ad09e4f08962a52b6ea2ac13e94778086fd7107d9fe550d48516e19553417ddbf281796143c83d64a78c5afa198375abba74419fd30ecf749b638c341
|
7
|
+
data.tar.gz: 11f2b3596583affdc178428867a03a8bf094ae2701c84f2db4cca1d96d6bad479dda5adc6a368df7d1e31b8841efced68cfa16fa420524616951e89bcdea5e82
|
data/README.md
CHANGED
@@ -34,11 +34,13 @@ Modes:
|
|
34
34
|
Indexer options:
|
35
35
|
-a, --[no-]amend Reindex existing versions
|
36
36
|
-i, --ignore PATH Don't check or index any file starting with PATH
|
37
|
-
-U, --url-template TEMPLATE=auto Set the template for implicit download links
|
38
37
|
-o, --output FILE=./index.xml Set the output filename and path for the index
|
38
|
+
--[no-]strict Enable strict validation mode
|
39
|
+
-U, --url-template TEMPLATE=auto Set the template for implicit download links
|
39
40
|
Repository metadata:
|
40
41
|
-n, --name NAME Set the name shown in ReaPack for this repository
|
41
42
|
-l, --link LINK Add or remove a website link
|
43
|
+
--screenshot-link LINK Add or remove a screenshot link
|
42
44
|
--donation-link LINK Add or remove a donation link
|
43
45
|
--ls-links Display the link list then exit
|
44
46
|
-A, --about=FILE Set the about content from a file
|
data/lib/reapack/index.rb
CHANGED
@@ -36,12 +36,13 @@ class ReaPack::Index
|
|
36
36
|
extension: %w{ext},
|
37
37
|
effect: %w{jsfx},
|
38
38
|
data: %w{data},
|
39
|
+
theme: %w{theme},
|
39
40
|
}.freeze
|
40
41
|
|
41
42
|
FS_ROOT = File.expand_path('/').freeze
|
42
43
|
|
43
44
|
attr_reader :path, :url_template, :cdetector
|
44
|
-
attr_accessor :amend, :commit, :files, :time
|
45
|
+
attr_accessor :amend, :commit, :files, :time, :strict
|
45
46
|
|
46
47
|
class << self
|
47
48
|
def is_type?(input)
|
@@ -107,6 +108,7 @@ class ReaPack::Index
|
|
107
108
|
return unless type
|
108
109
|
|
109
110
|
mh = MetaHeader.parse contents
|
111
|
+
mh.strict = @strict
|
110
112
|
|
111
113
|
if mh[:noindex]
|
112
114
|
remove path
|
@@ -171,12 +173,7 @@ class ReaPack::Index
|
|
171
173
|
return
|
172
174
|
end
|
173
175
|
|
174
|
-
|
175
|
-
if separator&.< input.index('://')
|
176
|
-
input = [input[0...separator], input[separator+1..-1]]
|
177
|
-
end
|
178
|
-
|
179
|
-
link = @metadata.push_link type, *input
|
176
|
+
link = @metadata.push_link type, *Link.split(input)
|
180
177
|
|
181
178
|
if link.is_new?
|
182
179
|
log_change "new #{type} link"
|
@@ -185,15 +182,15 @@ class ReaPack::Index
|
|
185
182
|
end
|
186
183
|
end
|
187
184
|
|
188
|
-
def
|
189
|
-
@metadata.
|
185
|
+
def about
|
186
|
+
@metadata.about
|
190
187
|
end
|
191
188
|
|
192
|
-
def
|
193
|
-
old = @metadata.
|
194
|
-
@metadata.
|
189
|
+
def about=(content)
|
190
|
+
old = @metadata.about
|
191
|
+
@metadata.about = content
|
195
192
|
|
196
|
-
log_change 'modified metadata' if old != @metadata.
|
193
|
+
log_change 'modified metadata' if old != @metadata.about
|
197
194
|
end
|
198
195
|
|
199
196
|
def url_template=(tpl)
|
data/lib/reapack/index/cli.rb
CHANGED
@@ -17,6 +17,7 @@ class ReaPack::Index::CLI
|
|
17
17
|
|
18
18
|
@index = ReaPack::Index.new expand_path(@opts[:output])
|
19
19
|
@index.amend = @opts[:amend]
|
20
|
+
@index.strict = @opts[:strict]
|
20
21
|
set_url_template
|
21
22
|
rescue Rugged::OSError, Rugged::RepositoryError, ReaPack::Index::Error => e
|
22
23
|
$stderr.puts e.message
|
@@ -36,7 +37,7 @@ class ReaPack::Index::CLI
|
|
36
37
|
end
|
37
38
|
|
38
39
|
if @opts[:dump_about]
|
39
|
-
print @index.
|
40
|
+
print @index.about
|
40
41
|
return true
|
41
42
|
end
|
42
43
|
|
@@ -145,6 +146,8 @@ private
|
|
145
146
|
'--link'
|
146
147
|
when :donation
|
147
148
|
'--donation-link'
|
149
|
+
when :screenshot
|
150
|
+
'--screenshot-link'
|
148
151
|
end
|
149
152
|
|
150
153
|
warn "#{opt}: " + e.message
|
@@ -181,14 +184,14 @@ private
|
|
181
184
|
path = @opts[:about]
|
182
185
|
|
183
186
|
unless path
|
184
|
-
@index.
|
187
|
+
@index.about = String.new if @opts[:rmabout]
|
185
188
|
return
|
186
189
|
end
|
187
190
|
|
188
191
|
log "converting #{path} into RTF..."
|
189
192
|
|
190
193
|
# look for the file in the working directory, not on the repository root
|
191
|
-
@index.
|
194
|
+
@index.about = File.read(path)
|
192
195
|
rescue Errno::ENOENT => e
|
193
196
|
warn '--about: ' + e.message.sub(' @ rb_sysopen', '')
|
194
197
|
rescue ReaPack::Index::Error => e
|
@@ -8,16 +8,17 @@ class ReaPack::Index::CLI
|
|
8
8
|
|
9
9
|
DEFAULTS = {
|
10
10
|
check: false,
|
11
|
-
scan: [],
|
12
|
-
rebuild: false,
|
13
|
-
verbose: false,
|
14
|
-
warnings: true,
|
15
|
-
progress: true,
|
16
|
-
quiet: false,
|
17
11
|
commit: nil,
|
18
|
-
output: './index.xml',
|
19
12
|
ignore: [],
|
13
|
+
output: './index.xml',
|
14
|
+
progress: true,
|
15
|
+
quiet: false,
|
16
|
+
rebuild: false,
|
17
|
+
scan: [],
|
18
|
+
strict: false,
|
20
19
|
url_template: 'auto',
|
20
|
+
verbose: false,
|
21
|
+
warnings: true,
|
21
22
|
}.freeze
|
22
23
|
|
23
24
|
def read_config
|
@@ -80,16 +81,20 @@ class ReaPack::Index::CLI
|
|
80
81
|
opts[:ignore] << expand_path(path)
|
81
82
|
end
|
82
83
|
|
83
|
-
op.on '-U', "--url-template TEMPLATE=#{DEFAULTS[:url_template]}",
|
84
|
-
'Set the template for implicit download links' do |tpl|
|
85
|
-
opts[:url_template] = tpl.strip
|
86
|
-
end
|
87
|
-
|
88
84
|
op.on '-o', "--output FILE=#{DEFAULTS[:output]}",
|
89
85
|
'Set the output filename and path for the index' do |file|
|
90
86
|
opts[:output] = file.strip
|
91
87
|
end
|
92
88
|
|
89
|
+
op.on '--[no-]strict', 'Enable strict validation mode' do |bool|
|
90
|
+
opts[:strict] = bool
|
91
|
+
end
|
92
|
+
|
93
|
+
op.on '-U', "--url-template TEMPLATE=#{DEFAULTS[:url_template]}",
|
94
|
+
'Set the template for implicit download links' do |tpl|
|
95
|
+
opts[:url_template] = tpl.strip
|
96
|
+
end
|
97
|
+
|
93
98
|
op.separator 'Repository metadata:'
|
94
99
|
|
95
100
|
op.on '-n', '--name NAME', 'Set the name shown in ReaPack for this repository' do |name|
|
@@ -101,6 +106,11 @@ class ReaPack::Index::CLI
|
|
101
106
|
opts[:links] << [:website, link.strip]
|
102
107
|
end
|
103
108
|
|
109
|
+
op.on '--screenshot-link LINK', 'Add or remove a screenshot link' do |link|
|
110
|
+
opts[:links] ||= Array.new
|
111
|
+
opts[:links] << [:screenshot, link.strip]
|
112
|
+
end
|
113
|
+
|
104
114
|
op.on '--donation-link LINK', 'Add or remove a donation link' do |link|
|
105
115
|
opts[:links] ||= Array.new
|
106
116
|
opts[:links] << [:donation, link.strip]
|
data/lib/reapack/index/git.rb
CHANGED
@@ -9,6 +9,10 @@ class ReaPack::Index
|
|
9
9
|
@root = parent.element_children.find {|node| node.name == TAG }
|
10
10
|
end
|
11
11
|
|
12
|
+
def modified?
|
13
|
+
!!@dirty
|
14
|
+
end
|
15
|
+
|
12
16
|
def links(type)
|
13
17
|
Link.find_all(type, @root).map {|node| Link.from_node node }
|
14
18
|
.select {|link| link.url.index('http') == 0 }
|
@@ -54,6 +58,8 @@ class ReaPack::Index
|
|
54
58
|
node.content = url
|
55
59
|
end
|
56
60
|
|
61
|
+
@dirty = true if link.modified?
|
62
|
+
|
57
63
|
link
|
58
64
|
end
|
59
65
|
|
@@ -64,9 +70,23 @@ class ReaPack::Index
|
|
64
70
|
|
65
71
|
node.remove
|
66
72
|
auto_remove
|
73
|
+
|
74
|
+
@dirty = true
|
75
|
+
end
|
76
|
+
|
77
|
+
def replace_links(type)
|
78
|
+
was_dirty = @dirty
|
79
|
+
|
80
|
+
old_links = hash_links Link.find_all(type, @root)
|
81
|
+
.each {|node| node.remove }
|
82
|
+
|
83
|
+
yield
|
84
|
+
|
85
|
+
new_links = hash_links Link.find_all(type, @root)
|
86
|
+
@dirty = old_links != new_links unless was_dirty
|
67
87
|
end
|
68
88
|
|
69
|
-
def
|
89
|
+
def about
|
70
90
|
cdata = nil
|
71
91
|
|
72
92
|
if @root
|
@@ -77,18 +97,24 @@ class ReaPack::Index
|
|
77
97
|
cdata ? cdata.content : String.new
|
78
98
|
end
|
79
99
|
|
80
|
-
def
|
81
|
-
|
100
|
+
def about=(content)
|
101
|
+
content = content.to_s
|
102
|
+
|
103
|
+
if !content.empty? && !content.start_with?("{\\rtf")
|
104
|
+
content = make_rtf content
|
105
|
+
end
|
106
|
+
|
107
|
+
return if content == self.about
|
82
108
|
|
83
109
|
make_root
|
84
110
|
desc = @root.element_children.find {|node| node.name == DESC }
|
85
111
|
|
112
|
+
@dirty = true
|
113
|
+
|
86
114
|
if content.empty?
|
87
115
|
desc.remove
|
88
116
|
auto_remove
|
89
117
|
return
|
90
|
-
elsif content.index("{\\rtf") != 0
|
91
|
-
content = make_rtf content
|
92
118
|
end
|
93
119
|
|
94
120
|
if desc
|
@@ -125,6 +151,10 @@ class ReaPack::Index
|
|
125
151
|
"Try again after installing pandoc from <http://pandoc.org/>."
|
126
152
|
].join("\n")
|
127
153
|
end
|
154
|
+
|
155
|
+
def hash_links(nodes)
|
156
|
+
nodes.map {|node| [node[Link::REL], node[Link::URL]] }
|
157
|
+
end
|
128
158
|
end
|
129
159
|
|
130
160
|
class Link
|
@@ -133,7 +163,17 @@ class ReaPack::Index
|
|
133
163
|
URL = 'href'.freeze
|
134
164
|
|
135
165
|
# the first type will be the default one
|
136
|
-
VALID_TYPES = [:website, :donation].freeze
|
166
|
+
VALID_TYPES = [:website, :screenshot, :donation].freeze
|
167
|
+
|
168
|
+
LINK_REGEX = /\A(.+?)(?:\s|=)(\w+?:\/\/.+)\Z/.freeze
|
169
|
+
|
170
|
+
def self.split(input)
|
171
|
+
if input =~ LINK_REGEX
|
172
|
+
[$1, $2]
|
173
|
+
else
|
174
|
+
[input]
|
175
|
+
end
|
176
|
+
end
|
137
177
|
|
138
178
|
def self.from_node(node)
|
139
179
|
name, url = node.text.to_s, node[URL].to_s
|
@@ -7,14 +7,17 @@ class ReaPack::Index
|
|
7
7
|
@tag = 'reapack'.freeze
|
8
8
|
|
9
9
|
TYPE_ATTR = 'type'.freeze
|
10
|
+
DESC_ATTR = 'desc'.freeze
|
10
11
|
|
11
12
|
def initialize(node)
|
12
13
|
super
|
13
|
-
|
14
|
+
@metadata = Metadata.new node
|
14
15
|
end
|
15
16
|
|
17
|
+
attr_reader :metadata
|
18
|
+
|
16
19
|
def modified?
|
17
|
-
super ||
|
20
|
+
super || versions.any? {|ver| ver.modified? } || @metadata.modified?
|
18
21
|
end
|
19
22
|
|
20
23
|
def category
|
@@ -38,11 +41,31 @@ class ReaPack::Index
|
|
38
41
|
@dirty = true
|
39
42
|
end
|
40
43
|
|
44
|
+
def description
|
45
|
+
@node[DESC_ATTR].to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def description=(new_desc)
|
49
|
+
new_desc ||= String.new
|
50
|
+
|
51
|
+
return if description == new_desc
|
52
|
+
|
53
|
+
if new_desc.empty?
|
54
|
+
@node.remove_attribute DESC_ATTR
|
55
|
+
else
|
56
|
+
@node[DESC_ATTR] = new_desc
|
57
|
+
end
|
58
|
+
|
59
|
+
@dirty = true
|
60
|
+
end
|
61
|
+
|
41
62
|
def has_version?(name)
|
63
|
+
read_versions
|
42
64
|
@versions.has_key? name
|
43
65
|
end
|
44
66
|
|
45
67
|
def versions
|
68
|
+
read_versions
|
46
69
|
@versions.values
|
47
70
|
end
|
48
71
|
|
@@ -62,11 +85,13 @@ class ReaPack::Index
|
|
62
85
|
|
63
86
|
private
|
64
87
|
def read_versions
|
65
|
-
@versions
|
88
|
+
@versions || begin
|
89
|
+
@versions = {}
|
66
90
|
|
67
|
-
|
68
|
-
|
69
|
-
|
91
|
+
Version.find_all(@node).each {|ver|
|
92
|
+
@versions[ver.name] = ver
|
93
|
+
}
|
94
|
+
end
|
70
95
|
end
|
71
96
|
end
|
72
97
|
end
|
@@ -8,34 +8,58 @@ class ReaPack::Index
|
|
8
8
|
end
|
9
9
|
}
|
10
10
|
|
11
|
+
VERSION_SEGMENT_MAX = (2 ** 16) - 1
|
12
|
+
|
13
|
+
SIMPLE_TAG = [MetaHeader::VALUE, MetaHeader::SINGLELINE].freeze
|
14
|
+
|
11
15
|
HEADER_RULES = {
|
12
16
|
# package-wide tags
|
13
|
-
:
|
14
|
-
MetaHeader::REQUIRED, MetaHeader::VALUE, MetaHeader::SINGLELINE, /\A\d
|
17
|
+
version: [
|
18
|
+
MetaHeader::REQUIRED, MetaHeader::VALUE, MetaHeader::SINGLELINE, /\A\d/,
|
19
|
+
proc {|v|
|
20
|
+
s = v.scan(/\d+/).find {|s| s.to_i > VERSION_SEGMENT_MAX }
|
21
|
+
'segment overflow (%d > %d)' % [s, VERSION_SEGMENT_MAX] if s
|
22
|
+
}
|
23
|
+
],
|
24
|
+
description: SIMPLE_TAG,
|
25
|
+
about: MetaHeader::VALUE,
|
26
|
+
website: MetaHeader::VALUE,
|
27
|
+
screenshot: MetaHeader::VALUE,
|
28
|
+
donation: MetaHeader::VALUE,
|
15
29
|
|
16
30
|
# version-specific tags
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
31
|
+
author: SIMPLE_TAG,
|
32
|
+
changelog: MetaHeader::VALUE,
|
33
|
+
provides: [MetaHeader::VALUE, PROVIDES_VALIDATOR],
|
34
|
+
noindex: MetaHeader::BOOLEAN,
|
35
|
+
metapackage: MetaHeader::BOOLEAN,
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
HEADER_ALIASES = {
|
39
|
+
[:reascript_name, :desc] => :description,
|
22
40
|
}.freeze
|
23
41
|
|
24
|
-
META_TYPES = [:extension, :data].freeze
|
42
|
+
META_TYPES = [:extension, :data, :theme].freeze
|
25
43
|
|
26
44
|
def initialize(cat, pkg, mh, index)
|
27
45
|
@cat, @pkg, @mh, @index = cat, pkg, mh, index
|
28
|
-
|
29
|
-
@mh[:metapackage] = META_TYPES.include?(pkg.type) if mh[:metapackage].nil?
|
30
|
-
|
31
46
|
@cselector = @index.cdetector[pkg.path]
|
32
47
|
end
|
33
48
|
|
34
49
|
def run
|
50
|
+
@mh.alias HEADER_ALIASES
|
51
|
+
|
35
52
|
if errors = @mh.validate(HEADER_RULES)
|
36
53
|
raise Error, errors.join("\n")
|
37
54
|
end
|
38
55
|
|
56
|
+
@pkg.description = @mh[:description]
|
57
|
+
@pkg.metadata.about = @mh[:about]
|
58
|
+
|
59
|
+
eval_links :website
|
60
|
+
eval_links :screenshot
|
61
|
+
eval_links :donation
|
62
|
+
|
39
63
|
@pkg.version @mh[:version] do |ver|
|
40
64
|
next unless ver.is_new? || @index.amend
|
41
65
|
|
@@ -49,7 +73,7 @@ class ReaPack::Index
|
|
49
73
|
@cselector.clear
|
50
74
|
sources = parse_provides @mh[:provides]
|
51
75
|
|
52
|
-
if
|
76
|
+
if !metapackage? && sources.none? {|src| src.file.nil? }
|
53
77
|
# add the package itself as a main source
|
54
78
|
src = Source.new make_url(@pkg.path), true
|
55
79
|
sources.unshift src
|
@@ -114,7 +138,7 @@ class ReaPack::Index
|
|
114
138
|
line.url_template ? expanded : file
|
115
139
|
|
116
140
|
if file == @pkg.path
|
117
|
-
src.main =
|
141
|
+
src.main = !metapackage? if line.main.nil?
|
118
142
|
else
|
119
143
|
if line.url_template
|
120
144
|
src.file = file
|
@@ -127,5 +151,22 @@ class ReaPack::Index
|
|
127
151
|
}
|
128
152
|
}.flatten
|
129
153
|
end
|
154
|
+
|
155
|
+
def eval_links(type)
|
156
|
+
@pkg.metadata.replace_links type do
|
157
|
+
@mh[type].to_s.lines {|l|
|
158
|
+
l.chomp!
|
159
|
+
@pkg.metadata.push_link type, *Link.split(l)
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def metapackage?
|
165
|
+
@metapackage ||= if @mh[:metapackage].nil?
|
166
|
+
META_TYPES.include? @pkg.type
|
167
|
+
else
|
168
|
+
@mh[:metapackage]
|
169
|
+
end
|
170
|
+
end
|
130
171
|
end
|
131
172
|
end
|