unpack 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +5 -0
- data/Gemfile +4 -0
- data/README.markdown +85 -0
- data/Rakefile +2 -0
- data/bin/unrar +0 -0
- data/lib/unpack.rb +146 -0
- data/lib/unpack/container.rb +15 -0
- data/spec/data/o_files/some_zip_files.zip +0 -0
- data/spec/data/o_files/test_package.rar +0 -0
- data/spec/data/rar/110_accessible_.rar +1 -0
- data/spec/data/rar/120_accessible_.rar +1 -0
- data/spec/data/rar/167_accessible_.rar +1 -0
- data/spec/data/rar/777_accessible_.rar +1 -0
- data/spec/data/rar/918_accessible_.rar +1 -0
- data/spec/data/rar/cd1/112_okey_.rar +1 -0
- data/spec/data/rar/cd1/129_okey_.rar +1 -0
- data/spec/data/rar/cd1/199_okey_.rar +1 -0
- data/spec/data/rar/cd1/228_okey_.rar +1 -0
- data/spec/data/rar/cd1/263_okey_.rar +1 -0
- data/spec/data/rar/cd1/325_okey_.rar +1 -0
- data/spec/data/rar/cd1/329_okey_.rar +1 -0
- data/spec/data/rar/cd1/333_okey_.rar +1 -0
- data/spec/data/rar/cd1/364_okey_.rar +1 -0
- data/spec/data/rar/cd1/390_okey_.rar +1 -0
- data/spec/data/rar/cd1/462_okey_.rar +1 -0
- data/spec/data/rar/cd1/515_okey_.rar +1 -0
- data/spec/data/rar/cd1/572_okey_.rar +1 -0
- data/spec/data/rar/cd1/573_okey_.rar +1 -0
- data/spec/data/rar/cd1/5_okey_.rar +1 -0
- data/spec/data/rar/cd1/627_okey_.rar +1 -0
- data/spec/data/rar/cd1/674_okey_.rar +1 -0
- data/spec/data/rar/cd1/682_okey_.rar +1 -0
- data/spec/data/rar/cd1/690_okey_.rar +1 -0
- data/spec/data/rar/cd1/698_okey_.rar +1 -0
- data/spec/data/rar/cd1/817_okey_.rar +1 -0
- data/spec/data/rar/cd1/828_okey_.rar +1 -0
- data/spec/data/rar/cd1/840_okey_.rar +1 -0
- data/spec/data/rar/cd1/920_okey_.rar +1 -0
- data/spec/data/rar/cd1/925_okey_.rar +1 -0
- data/spec/data/rar/cd1/974_okey_.rar +1 -0
- data/spec/data/rar/cd1/978_okey_.rar +1 -0
- data/spec/data/rar/cd1/982_okey_.rar +1 -0
- data/spec/data/rar/cd1/988_okey_.rar +1 -0
- data/spec/data/rar/cd1/998_okey_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/117_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/12_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/171_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/178_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/179_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/202_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/214_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/423_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/46_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/477_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/499_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/531_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/536_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/554_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/556_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/564_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/569_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/608_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/614_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/634_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/644_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/708_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/756_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/802_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/815_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/833_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/84_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/92_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/936_not_.rar +1 -0
- data/spec/data/rar/cd1/Unreachable/939_not_.rar +1 -0
- data/spec/data/rar/cd2/102_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/111_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/14_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/242_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/244_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/248_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/278_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/283_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/310_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/439_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/453_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/461_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/476_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/484_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/491_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/507_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/518_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/609_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/613_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/633_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/644_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/682_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/706_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/767_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/788_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/801_okey_without_.rar +1 -0
- data/spec/data/rar/cd2/808_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/837_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/919_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/93_okey_without_.strange +1 -0
- data/spec/data/rar/cd2/980_okey_without_.strange +1 -0
- data/spec/data/rar/subdir/133_subtitle_.rar +1 -0
- data/spec/data/rar/subdir/169_subtitle_.rar +1 -0
- data/spec/data/rar/subdir/22_subtitle_.rar +1 -0
- data/spec/data/rar/subdir/483_subtitle_.rar +1 -0
- data/spec/data/rar/subdir/639_subtitle_.rar +1 -0
- data/spec/data/rar_real/110_real_.file.rar +1 -0
- data/spec/data/rar_real/120_real_.file.rar +1 -0
- data/spec/data/rar_real/167_real_.file.rar +1 -0
- data/spec/data/rar_real/777_real_.file.rar +1 -0
- data/spec/data/rar_real/918_real_.file.rar +1 -0
- data/spec/data/zip_real/some_zip_files.zip +0 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/unpack_spec.rb +261 -0
- data/unpack.gemspec +21 -0
- metadata +321 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Unpack*(er)* - *run files, run*
|
2
|
+
|
3
|
+
## What is Unpack?
|
4
|
+
|
5
|
+
Unpack makes it possible to unarchive rar and zip files using ruby.
|
6
|
+
|
7
|
+
You pass a directory and it will find all your archive files, unpack and remove them (if you want to).
|
8
|
+
|
9
|
+
## So how do I use it?
|
10
|
+
|
11
|
+
### Start by installing the gem
|
12
|
+
|
13
|
+
sudo gem install unpack
|
14
|
+
|
15
|
+
Start `irb` and include the gem, `require 'unpack'`
|
16
|
+
|
17
|
+
### Unpack everything in the current directory
|
18
|
+
|
19
|
+
$ Unpack.runner!
|
20
|
+
=> [#<Container:0x000001010ab458 @files=["dmd-tsa-cd2.avi"], @directory="/Downloads/Some.Super.Movie/CD2">]
|
21
|
+
|
22
|
+
### Unpack everything in another directory
|
23
|
+
|
24
|
+
$ Unpack.runner!('/some/dir')
|
25
|
+
=> [#<Container:0x000001010ab458 @files=["some_files.mov"], @directory="/some/dir">]
|
26
|
+
|
27
|
+
### Unpack and delete archived file
|
28
|
+
|
29
|
+
$ Unpack.runner!('.', remove: true)
|
30
|
+
=> [#<Container:0x000001010ab458 @files=["dmd-tsa-cd2.avi"], @directory="/Downloads/Some.Super.Movie/CD2">]
|
31
|
+
$ Unpack.runner!('.', remove: true)
|
32
|
+
=> []
|
33
|
+
|
34
|
+
### Remove every archive file, even if nothing where unpacked
|
35
|
+
|
36
|
+
$ Unpack.runner!('.', remove: true, force_remove: true)
|
37
|
+
=> []
|
38
|
+
|
39
|
+
### Unpack all archived file, but not deeper 3 folders down
|
40
|
+
|
41
|
+
$ Unpack.runner!('.', depth: 3)
|
42
|
+
=> [#<Container:0x000001010ab458 @files=["dmd-tsa-cd2.avi"], @directory="/Downloads/Some.Super.Movie/CD2">]
|
43
|
+
|
44
|
+
### Unpack everything, even one file directories
|
45
|
+
|
46
|
+
To prevent you from unarchive files in folders that contains subtitles and other nonrelevant files, the folder must contain 5 archive files or more.
|
47
|
+
|
48
|
+
If you want to unpack everything, even subtitles directories, then you will have to specify the `min_files` option.
|
49
|
+
|
50
|
+
$ Unpack.runner!('.', min_files: 0)
|
51
|
+
=> [#<Container:0x000001010ab458 @files=["english.str"], @directory="/Downloads/Subtitle/">]
|
52
|
+
|
53
|
+
### Some configure alternatives
|
54
|
+
|
55
|
+
- ** :min_files ** (Integer) The minimum amount of files in the directory you want to archive the files in. *Default is 5*.
|
56
|
+
- ** :depth ** (Integer) The maximum folder depth. *Default is 2*.
|
57
|
+
- ** :debugger ** (Boolean) Prints some debug output into the console. *Default is false*.
|
58
|
+
- ** :force_remove ** (Boolean) Remove rarfiles, even if no files where unarchived. *Default is false*. **To get this to work you also have to set the `remove` option to true**.
|
59
|
+
- ** :remove ** (Boolean) Removes archived files after they have been used. *Default is false*.
|
60
|
+
- ** :absolute_path_to_unrar ** (String) The absolut path to the unrar binary. *Default is the [unrar](http://homepage.mac.com/pnoriega/unrar.html) binary that comes with the gem*.
|
61
|
+
|
62
|
+
## What is being returned?
|
63
|
+
|
64
|
+
The `runner!` method returns an `Array` of `Container` objects.
|
65
|
+
|
66
|
+
These are the accessors of the `Container` class.
|
67
|
+
|
68
|
+
- **files** (String) The absolut path to the files that where unarchived.
|
69
|
+
- **directory** (String) The absolut path to the folder containing the files.
|
70
|
+
|
71
|
+
## This sounds supr, how do I help?
|
72
|
+
|
73
|
+
- Start by copying the project or make your own branch.
|
74
|
+
- Navigate to the root path of the project and run `bundle`.
|
75
|
+
- Start by running all tests using rspec, `autotest`.
|
76
|
+
- Implement your own code, write some tests, commit and do a pull request.
|
77
|
+
|
78
|
+
## Requirements
|
79
|
+
|
80
|
+
The gem is tested in OS X 10.6.6 using Ruby 1.9.2
|
81
|
+
|
82
|
+
## Thanks to ...
|
83
|
+
|
84
|
+
- the [UnRarX](http://homepage.mac.com/pnoriega/unrar.html) team that provies the unrar binary.
|
85
|
+
- [NinoScript](https://github.com/NinoScript) that solved the console-escaping issue - [see this commit](https://github.com/oleander/Unpack/commit/dd7e46200a490c7af9fc5f770127291192a818f5).
|
data/Rakefile
ADDED
data/bin/unrar
ADDED
Binary file
|
data/lib/unpack.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'mimer_plus'
|
2
|
+
require 'unpack/container'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class Unpack
|
6
|
+
attr_accessor :files, :options
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
args.keys.each { |name| instance_variable_set "@" + name.to_s, args[name] }
|
10
|
+
|
11
|
+
@options = {
|
12
|
+
:min_files => 5,
|
13
|
+
:depth => 2,
|
14
|
+
:debugger => false,
|
15
|
+
:force_remove => false,
|
16
|
+
:remove => false,
|
17
|
+
:absolute_path_to_unrar => "#{File.dirname(__FILE__)}/../bin/unrar"
|
18
|
+
}
|
19
|
+
|
20
|
+
@removeable = {}
|
21
|
+
|
22
|
+
@options.merge!(args[:options]) if args[:options]
|
23
|
+
|
24
|
+
# If the path is relative
|
25
|
+
@directory = File.expand_path(@directory) unless @directory.match(/^\//)
|
26
|
+
|
27
|
+
# Makes shure that every directory structure looks the same
|
28
|
+
@directory = Dir.new(@directory).path rescue nil
|
29
|
+
|
30
|
+
raise Exception.new("You need to specify a valid path") if @directory.nil? or not Dir.exist?(@directory)
|
31
|
+
raise Exception.new("You need unzip to keep going") if %x{whereis unzip}.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.runner!(directory = '.', options = {})
|
35
|
+
unpack = Unpack.new(directory: directory, options: options) rescue nil
|
36
|
+
|
37
|
+
# If the initializer raised any excetions
|
38
|
+
return [] if unpack.nil?
|
39
|
+
unpack.prepare!
|
40
|
+
unpack.clean!
|
41
|
+
unpack.unpack!
|
42
|
+
unpack.wipe! if options[:remove]
|
43
|
+
unpack.diff
|
44
|
+
end
|
45
|
+
|
46
|
+
def prepare!
|
47
|
+
@directory.gsub!(/\s+/, '\ ')
|
48
|
+
@files = []
|
49
|
+
|
50
|
+
['zip', 'rar'].each do |type|
|
51
|
+
@files << find_file_type(type)
|
52
|
+
end
|
53
|
+
|
54
|
+
@files.flatten!.map! {|file| File.absolute_path(file)}
|
55
|
+
end
|
56
|
+
|
57
|
+
def clean!
|
58
|
+
# Removing all folders that have less then {@options[:lim]} files in them
|
59
|
+
# Those folders are offen subtitle folders
|
60
|
+
folders = @files.map {|file| File.dirname(file)}.uniq.reject {|folder| Dir.entries(folder).count <= (@options[:min_files] + 2)}
|
61
|
+
@files.reject!{|file| not folders.include?(File.dirname(file))}
|
62
|
+
results = []
|
63
|
+
|
64
|
+
# Finding one rar file for every folder
|
65
|
+
@files.group_by{|file| File.dirname(file) }.each_pair{|_,file| results << file.sort.first }
|
66
|
+
@files = results
|
67
|
+
end
|
68
|
+
|
69
|
+
def unpack!
|
70
|
+
@files.each do |file|
|
71
|
+
type = Mimer.identify(file)
|
72
|
+
path = File.dirname(file)
|
73
|
+
before = Dir.new(path).entries
|
74
|
+
|
75
|
+
if type.zip?
|
76
|
+
@removeable.merge!(path => {:file_type => 'zip'})
|
77
|
+
self.unzip(path: path, file: file)
|
78
|
+
elsif type.rar?
|
79
|
+
@removeable.merge!(path => {:file_type => 'rar'})
|
80
|
+
self.unrar(path: path, file: file)
|
81
|
+
else
|
82
|
+
puts "Something went wrong, the mime type does not match zip or rar" if @options[:debugger]
|
83
|
+
end
|
84
|
+
|
85
|
+
# What files/folders where unpacked?
|
86
|
+
diff = Dir.new(path).entries - before
|
87
|
+
|
88
|
+
@removeable[path] ? @removeable[path].merge!(:diff => diff) : @removeable.delete(path)
|
89
|
+
|
90
|
+
# Some debug info
|
91
|
+
if @options[:debugger] and diff.any? and @removeable[path]
|
92
|
+
puts "#{diff.count} where unpacked"
|
93
|
+
puts "The archive was of type #{@removeable[path][:file_type]}"
|
94
|
+
puts "The name of the file(s) are #{diff.join(', ')}"
|
95
|
+
puts "The path is #{path}"
|
96
|
+
STDOUT.flush
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Removes the old rar and zip files
|
102
|
+
def wipe!
|
103
|
+
@removeable.each do |value|
|
104
|
+
path = value.first
|
105
|
+
type = value.last[:file_type]
|
106
|
+
|
107
|
+
# Does not remove anything if nothing where unpacked
|
108
|
+
next if value.last[:diff].empty? and not @options[:force_remove]
|
109
|
+
|
110
|
+
puts "Removing files in #{path}" if @options[:debugger]
|
111
|
+
|
112
|
+
# Finding every file in this directory
|
113
|
+
Dir.glob(path + '/*').each do |file|
|
114
|
+
# Is the found file as the same type as the one that got unpacked?
|
115
|
+
FileUtils.rm(file) if Mimer.identify(file).send(:"#{type}?")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def diff
|
121
|
+
# The code below this line can only be called once
|
122
|
+
return @removeable if @removeable.first.class == Container
|
123
|
+
|
124
|
+
# Removing some non welcome data
|
125
|
+
@removeable.reject!{|item| @removeable[item][:diff].nil? or @removeable[item][:diff].empty?}
|
126
|
+
|
127
|
+
@removeable = @removeable.map do |value|
|
128
|
+
Container.new(files: value.last[:diff], directory: value.first)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Never return the hash
|
132
|
+
@removeable.empty? ? [] : @removeable
|
133
|
+
end
|
134
|
+
|
135
|
+
def unrar(args)
|
136
|
+
%x(cd '#{args[:path]}' && '#{@options[:absolute_path_to_unrar]}' e -y -o- '#{args[:file]}')
|
137
|
+
end
|
138
|
+
|
139
|
+
def unzip(args)
|
140
|
+
%x(unzip -n '#{args[:file]}' -d '#{args[:path]}')
|
141
|
+
end
|
142
|
+
|
143
|
+
def find_file_type(file_type)
|
144
|
+
%x{cd '#{@directory}' && find '#{@directory}' -type f -maxdepth '#{(@options[:depth])}' -name \"*.#{file_type}\"}.split(/\n/)
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Container
|
2
|
+
attr_accessor :files, :directory
|
3
|
+
|
4
|
+
def initialize(args)
|
5
|
+
args.keys.each { |name| instance_variable_set "@" + name.to_s, args[name] }
|
6
|
+
end
|
7
|
+
|
8
|
+
def files
|
9
|
+
return @files if @called
|
10
|
+
@files.map! {|file| "#{@directory}/#{file}"}
|
11
|
+
@called = true
|
12
|
+
@files
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
502
|
@@ -0,0 +1 @@
|
|
1
|
+
54
|
@@ -0,0 +1 @@
|
|
1
|
+
25
|
@@ -0,0 +1 @@
|
|
1
|
+
732
|
@@ -0,0 +1 @@
|
|
1
|
+
522
|
@@ -0,0 +1 @@
|
|
1
|
+
929
|
@@ -0,0 +1 @@
|
|
1
|
+
52
|
@@ -0,0 +1 @@
|
|
1
|
+
544
|
@@ -0,0 +1 @@
|
|
1
|
+
5
|
@@ -0,0 +1 @@
|
|
1
|
+
340
|
@@ -0,0 +1 @@
|
|
1
|
+
165
|
@@ -0,0 +1 @@
|
|
1
|
+
165
|
@@ -0,0 +1 @@
|
|
1
|
+
294
|
@@ -0,0 +1 @@
|
|
1
|
+
569
|
@@ -0,0 +1 @@
|
|
1
|
+
624
|
@@ -0,0 +1 @@
|
|
1
|
+
69
|
@@ -0,0 +1 @@
|
|
1
|
+
264
|
@@ -0,0 +1 @@
|
|
1
|
+
508
|
@@ -0,0 +1 @@
|
|
1
|
+
156
|
@@ -0,0 +1 @@
|
|
1
|
+
775
|
@@ -0,0 +1 @@
|
|
1
|
+
741
|
@@ -0,0 +1 @@
|
|
1
|
+
227
|
@@ -0,0 +1 @@
|
|
1
|
+
740
|
@@ -0,0 +1 @@
|
|
1
|
+
553
|
@@ -0,0 +1 @@
|
|
1
|
+
173
|
@@ -0,0 +1 @@
|
|
1
|
+
802
|
@@ -0,0 +1 @@
|
|
1
|
+
402
|
@@ -0,0 +1 @@
|
|
1
|
+
589
|
@@ -0,0 +1 @@
|
|
1
|
+
159
|
@@ -0,0 +1 @@
|
|
1
|
+
737
|
@@ -0,0 +1 @@
|
|
1
|
+
872
|
@@ -0,0 +1 @@
|
|
1
|
+
722
|
@@ -0,0 +1 @@
|
|
1
|
+
158
|
@@ -0,0 +1 @@
|
|
1
|
+
617
|
@@ -0,0 +1 @@
|
|
1
|
+
956
|
@@ -0,0 +1 @@
|
|
1
|
+
360
|
@@ -0,0 +1 @@
|
|
1
|
+
190
|
@@ -0,0 +1 @@
|
|
1
|
+
236
|
@@ -0,0 +1 @@
|
|
1
|
+
16
|
@@ -0,0 +1 @@
|
|
1
|
+
107
|
@@ -0,0 +1 @@
|
|
1
|
+
542
|
@@ -0,0 +1 @@
|
|
1
|
+
765
|
@@ -0,0 +1 @@
|
|
1
|
+
720
|
@@ -0,0 +1 @@
|
|
1
|
+
584
|
@@ -0,0 +1 @@
|
|
1
|
+
689
|
@@ -0,0 +1 @@
|
|
1
|
+
782
|
@@ -0,0 +1 @@
|
|
1
|
+
246
|
@@ -0,0 +1 @@
|
|
1
|
+
767
|
@@ -0,0 +1 @@
|
|
1
|
+
558
|