deb822 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4d5b7765d6312156bdb4820387131595ad8c771f9b1ac016d14bba4bc1145210
4
+ data.tar.gz: f77ff567e85b3ed139a9f22bbd3a33f2409bad5b04f2326186e7254dc002be7d
5
+ SHA512:
6
+ metadata.gz: 5f4ea00dd8a05cdd2a787e7c13407c7058ce804fd1d80d9da492da69e93793db4eabcc8f3433a1734434862f979f879089a4b9f1f65cae25a976c9c7e5532006
7
+ data.tar.gz: 9144a441e5eb32eff725dd48473027a8e8a18502b10b9cc71b6f90e5ad21215abc990227f3008248afb0593a3fcca0af3ef4b185d0f479ac0b4c664db86b07dc
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake', '~> 12.0'
6
+ gem 'rspec', '~> 3.0'
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ deb822 (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.3)
10
+ rake (12.3.3)
11
+ rspec (3.9.0)
12
+ rspec-core (~> 3.9.0)
13
+ rspec-expectations (~> 3.9.0)
14
+ rspec-mocks (~> 3.9.0)
15
+ rspec-core (3.9.0)
16
+ rspec-support (~> 3.9.0)
17
+ rspec-expectations (3.9.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.9.0)
20
+ rspec-mocks (3.9.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.9.0)
23
+ rspec-support (3.9.0)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ deb822!
30
+ rake (~> 12.0)
31
+ rspec (~> 3.0)
32
+
33
+ BUNDLED WITH
34
+ 2.0.2
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Kasumi Hanazuki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # Deb822
2
+
3
+ Parser and generator for [deb822(5)](https://manpages.debian.org/unstable/dpkg-dev/deb822.5.en.html).
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'deb822'
3
+ spec.version = '0.1.0'
4
+ spec.authors = ['Kasumi Hanazuki']
5
+ spec.email = ['kasumi@rollingapple.net']
6
+
7
+ spec.summary = %q{deb822 parser}
8
+ spec.description = %q{Parser for Debian control files}
9
+ spec.homepage = 'https://github.com/hanazuki/ruby-deb822'
10
+ spec.license = 'MIT'
11
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
12
+
13
+ spec.metadata['homepage_uri'] = spec.homepage
14
+ spec.metadata['source_code_uri'] = spec.homepage
15
+
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split(?\0).reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+ end
@@ -0,0 +1,106 @@
1
+ require 'forwardable'
2
+
3
+ module Deb822
4
+ class Error < StandardError; end
5
+ class FormatError < Deb822::Error; end
6
+ class InvalidFieldName < FormatError; end
7
+
8
+ singleton_class.define_method(:FieldName) do |name|
9
+ if name.is_a?(FieldName)
10
+ name
11
+ else
12
+ FieldName.new(name)
13
+ end
14
+ end
15
+
16
+ class FieldName
17
+
18
+ # > The field name is composed of US-ASCII characters excluding control characters, space, and colon
19
+ # > (i.e., characters in the ranges U+0021 ‘!’ through U+0039 ‘9’, and U+003B ‘;’ through U+007E ‘~’, inclusive).
20
+ # > Field names must not begin with the comment character (U+0023 ‘#’), nor with the hyphen character (U+002D ‘-’).
21
+ PATTERN = /[!"$-,.-9;-~][!-9;-~]*/
22
+
23
+ def initialize(name)
24
+ name = name.to_s unless name.is_a?(String)
25
+
26
+ unless /\A#{PATTERN}\z/o.match?(name)
27
+ raise InvalidFieldName, "Invalid field name: #{name.inspect}"
28
+ end
29
+
30
+ @sym = FieldName.canonicalize(name).to_sym
31
+ end
32
+
33
+ def to_sym
34
+ @sym
35
+ end
36
+
37
+ def to_s
38
+ @sym.to_s
39
+ end
40
+
41
+ def hash
42
+ @sym.hash
43
+ end
44
+
45
+ def eql?(other)
46
+ to_sym == Deb822::FieldName(other).to_sym
47
+ end
48
+
49
+ def ==(other)
50
+ eql?(other)
51
+ end
52
+
53
+ def !=(other)
54
+ !eql?(other)
55
+ end
56
+
57
+ def inspect
58
+ @sym
59
+ end
60
+
61
+ def self.canonicalize(str)
62
+ str.split(?-).each {|s| s.capitalize!(:ascii) }.join(?-)
63
+ end
64
+ end
65
+
66
+ # Hash-like structure whose keys are FieldName.
67
+ class Paragraph
68
+ extend Enumerable
69
+ extend Forwardable
70
+
71
+ def initialize(hash = nil)
72
+ @hash = {}
73
+ update(hash) if hash
74
+ end
75
+
76
+ def [](key)
77
+ @hash[Deb822::FieldName(key)]
78
+ end
79
+
80
+ def []=(key, value)
81
+ @hash[Deb822::FieldName(key)] = value.to_s
82
+ end
83
+ alias :store :[]=
84
+
85
+ def fetch(key, *default, &block)
86
+ @hash.fetch(Deb822::FieldName(key), *default, &block)
87
+ end
88
+
89
+ def update(other)
90
+ other.each do |k, v|
91
+ store(k, v)
92
+ end
93
+ end
94
+
95
+ def slice(*keys)
96
+ Paragraph.new(@hash.slice(*keys.map(&Deb822.method(:FieldName))))
97
+ end
98
+
99
+ def_delegators :@hash,
100
+ :each, :each_pair, :each_key, :each_value,
101
+ :empty?, :length, :size,
102
+ :keys, :has_key?, :include?, :key?, :member?,
103
+ :values, :values_at, :has_value?, :value?,
104
+ :inspect, :to_h, :to_hash, :to_proc
105
+ end
106
+ end
@@ -0,0 +1,67 @@
1
+ require 'deb822'
2
+
3
+ module Deb822
4
+ # Low-level generator for deb822 document
5
+ class Emitter
6
+ def initialize(output)
7
+ @output = output
8
+
9
+ @at_beginning = true
10
+ @in_paragraph = false
11
+ end
12
+
13
+ def emit_field(name, value)
14
+ name = Deb822.FieldName(name)
15
+
16
+ if value.respond_to?(:each_line)
17
+ enum = value.each_line
18
+ else
19
+ enum = value.to_s.each_line
20
+ end
21
+
22
+ if !@at_beginning && !@in_paragraph
23
+ @output << "\n"
24
+ end
25
+ @at_beginning = false
26
+ @in_paragraph = true
27
+
28
+ @output << name.to_s << ': '
29
+
30
+ begin
31
+ line = enum.next
32
+ @output << line
33
+ @output << "\n" unless line.end_with?("\n")
34
+ rescue StopIteration
35
+ # nop
36
+ else
37
+ loop do
38
+ emit_continuation_line(enum.next)
39
+ end
40
+ end
41
+
42
+ self
43
+ end
44
+
45
+ def emit_fields(pairs)
46
+ pairs.each_pair do |name, value|
47
+ emit_field(name, value)
48
+ end
49
+ end
50
+
51
+ def emit_continuation_line(line)
52
+ if /\A(?:\.|\Z)/.match?(line)
53
+ @output << ' .' << line
54
+ else
55
+ @output << ' ' << line
56
+ end
57
+ @output << "\n" unless line.end_with?("\n")
58
+ self
59
+ end
60
+
61
+ def start_paragraph
62
+ @in_paragraph = false
63
+ self
64
+ end
65
+ alias :end_paragraph :start_paragraph
66
+ end
67
+ end
@@ -0,0 +1,38 @@
1
+ require 'deb822'
2
+ require 'deb822/scanner'
3
+
4
+ module Deb822
5
+ # High-level parser for deb822 documents
6
+ class Parser
7
+ def initialize(input)
8
+ @scanner = Scanner.new(input)
9
+ end
10
+
11
+ def each_paragraph
12
+ return to_enum(:each_paragraph) unless block_given?
13
+
14
+ last_par = last_val = nil
15
+
16
+ @scanner.each_line do |l|
17
+ case l[0]
18
+ when :paragraph_separator
19
+ yield last_par if last_par
20
+ last_par = last_val = nil
21
+ when :comment
22
+ next
23
+ when :field
24
+ last_par ||= Paragraph.new
25
+ last_par[l[1]] = last_val = l[2]
26
+ when :continuation
27
+ last_val << "\n" unless last_val.end_with?("\n")
28
+ last_val << l[1]
29
+ else
30
+ fail "BUG: unreachable code: #{l.inspect}"
31
+ end
32
+ end
33
+
34
+ yield last_par if last_par
35
+ end
36
+ alias :paragraphs :each_paragraph
37
+ end
38
+ end
@@ -0,0 +1,64 @@
1
+ require 'deb822'
2
+ require 'stringio'
3
+
4
+ module Deb822
5
+ # Low-level parser for deb822 documents
6
+ class Scanner
7
+ def initialize(input)
8
+ @input = input.is_a?(String) ? StringIO.new(input) : input
9
+
10
+ @in_paragraph = false
11
+ end
12
+
13
+ WS = /[ \t]/
14
+
15
+ def next_line
16
+ loop do
17
+ begin
18
+ line = @input.readline
19
+ rescue EOFError
20
+ break
21
+ end
22
+
23
+ case line
24
+ when /\A#{WS}*\Z/o
25
+ # > The paragraphs are separated by empty lines.
26
+ # > Parsers may accept lines consisting solely of U+0020 SPACE and U+0009 TAB as paragraph separators
27
+ if @in_paragraph
28
+ @in_paragraph = false
29
+ break [:paragraph_separator]
30
+ else
31
+ next
32
+ end
33
+ when /\A#/
34
+ # > Lines starting with U+0023 ‘#’, without any preceding whitespace are comments lines
35
+ break [:comment, $']
36
+ when /\A(#{FieldName::PATTERN}):#{WS}*/o
37
+ name = $1
38
+ value = $'.chomp
39
+ @in_paragraph = true
40
+ break [:field, name, value]
41
+ when /\A#{WS}\.?/o
42
+ # > The lines after the first are called continuation lines and must start with a U+0020 SPACE or a U+0009 TAB.
43
+ # > Empty lines in field values are usually escaped by representing them by a U+0020 SPACE followed
44
+ # > by a dot (U+002E ‘.’).
45
+ raise FormatError, "Unexpected continuation line: #{line.inspect}" unless @in_paragraph
46
+ break [:continuation, $']
47
+ else
48
+ raise FormatError, "Ill-formed line: #{line.inspect}"
49
+ end
50
+
51
+ return nil
52
+ end
53
+ end
54
+
55
+ def each_line
56
+ return to_enum(:each_line) unless block_given?
57
+
58
+ while l = next_line
59
+ yield l
60
+ end
61
+ end
62
+ alias :lines :each_line
63
+ end
64
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deb822
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kasumi Hanazuki
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-12-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Parser for Debian control files
14
+ email:
15
+ - kasumi@rollingapple.net
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - deb822.gemspec
28
+ - lib/deb822.rb
29
+ - lib/deb822/emitter.rb
30
+ - lib/deb822/parser.rb
31
+ - lib/deb822/scanner.rb
32
+ homepage: https://github.com/hanazuki/ruby-deb822
33
+ licenses:
34
+ - MIT
35
+ metadata:
36
+ homepage_uri: https://github.com/hanazuki/ruby-deb822
37
+ source_code_uri: https://github.com/hanazuki/ruby-deb822
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.3.0
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubygems_version: 3.0.3
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: deb822 parser
57
+ test_files: []