imagesorter 1.0.0 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +6 -18
- data/.travis.yml +3 -3
- data/CHANGELOG.md +8 -0
- data/Rakefile +2 -0
- data/imagesorter.gemspec +7 -7
- data/lib/imagesorter.rb +1 -0
- data/lib/imagesorter/categorizers/file_exif_categorizer.rb +2 -1
- data/lib/imagesorter/categorizers/file_stat_categorizer.rb +1 -0
- data/lib/imagesorter/cmd.rb +19 -21
- data/lib/imagesorter/file_batch_processor.rb +5 -3
- data/lib/imagesorter/file_system_processor.rb +19 -27
- data/lib/imagesorter/gem.rb +1 -1
- data/lib/imagesorter/option_parser.rb +10 -6
- data/version +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64e5b3c929c90c57ea0da7cab2671f5da16b7ce7
|
4
|
+
data.tar.gz: 2ccf08ee293fee96fae9db196bb484039b895da9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a456b17664abb93d4fd8838a1b044bc48748ef37b44f950438db762359b48f290293169e8ef815edd336381dc77cede7db61ae86e51b1542022cceb19ae4e31e
|
7
|
+
data.tar.gz: 9f6876751171848f87fe56bce6b8d491b28803025d67117d118fcea493d50b940c58702b9806e0796653dbc56db42442c88ef508b42bdcbcbf15dea1015f6fcc
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,33 +1,21 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2019-11-02 20:56:11 +0200 using RuboCop version 0.76.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 3
|
10
10
|
Metrics/AbcSize:
|
11
|
-
Max:
|
11
|
+
Max: 19
|
12
12
|
|
13
|
-
# Offense count:
|
14
|
-
# Configuration parameters: CountComments.
|
13
|
+
# Offense count: 5
|
14
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
15
15
|
Metrics/MethodLength:
|
16
|
-
Max:
|
16
|
+
Max: 14
|
17
17
|
|
18
18
|
# Offense count: 1
|
19
19
|
# Configuration parameters: CountKeywordArgs.
|
20
20
|
Metrics/ParameterLists:
|
21
21
|
Max: 7
|
22
|
-
|
23
|
-
# Offense count: 6
|
24
|
-
Style/Documentation:
|
25
|
-
Exclude:
|
26
|
-
- 'spec/**/*'
|
27
|
-
- 'test/**/*'
|
28
|
-
- 'lib/imagesorter/file_batch_processor.rb'
|
29
|
-
- 'lib/imagesorter/file_exif_categorizer.rb'
|
30
|
-
- 'lib/imagesorter/file_stat_categorizer.rb'
|
31
|
-
- 'lib/imagesorter/file_system_processor.rb'
|
32
|
-
- 'lib/imagesorter/gem.rb'
|
33
|
-
- 'lib/imagesorter/option_parser.rb'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [1.0.1] - 2019-11-02
|
8
|
+
### Fixed
|
9
|
+
- Added missing require for OptionParser
|
10
|
+
### Added
|
11
|
+
- .cr2 extension as a default
|
12
|
+
### Changed
|
13
|
+
- Drop support for deprecated Rubies, 2.4 required
|
14
|
+
|
7
15
|
## [1.0.0] - 2017-08-12
|
8
16
|
### Added
|
9
17
|
- Initial release
|
data/Rakefile
CHANGED
data/imagesorter.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
$LOAD_PATH.unshift File.expand_path('
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'imagesorter'
|
7
|
-
s.version = File.read(File.expand_path('
|
7
|
+
s.version = File.read(File.expand_path('version', __dir__)).strip
|
8
8
|
s.description = 'Command line tool for sorting photos and videos'
|
9
9
|
s.summary = 'Command line tool for sorting photos and videos'
|
10
10
|
s.authors = ['Joakim Antman']
|
@@ -19,16 +19,16 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.bindir = 'exe'
|
20
20
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
|
22
|
-
s.required_ruby_version = '>= 2.
|
22
|
+
s.required_ruby_version = '>= 2.4'
|
23
23
|
|
24
24
|
s.add_dependency 'exifr'
|
25
25
|
s.add_dependency 'progressbar'
|
26
26
|
s.add_dependency 'r18n-core'
|
27
27
|
|
28
|
-
s.add_development_dependency 'rubocop'
|
29
|
-
s.add_development_dependency 'rspec'
|
30
|
-
s.add_development_dependency 'simplecov'
|
31
28
|
s.add_development_dependency 'bundler'
|
32
|
-
s.add_development_dependency 'rake'
|
33
29
|
s.add_development_dependency 'pry'
|
30
|
+
s.add_development_dependency 'rake'
|
31
|
+
s.add_development_dependency 'rspec'
|
32
|
+
s.add_development_dependency 'rubocop'
|
33
|
+
s.add_development_dependency 'simplecov'
|
34
34
|
end
|
data/lib/imagesorter.rb
CHANGED
data/lib/imagesorter/cmd.rb
CHANGED
@@ -27,26 +27,18 @@ module Imagesorter
|
|
27
27
|
rescue Interrupt
|
28
28
|
puts 'FAIL: INTERRUPTED'
|
29
29
|
exit 1
|
30
|
-
rescue => e
|
30
|
+
rescue StandardError => e
|
31
31
|
puts e
|
32
|
+
puts e.backtrace
|
32
33
|
exit 2
|
33
34
|
end
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
38
|
def setup_logger
|
39
|
+
Imagesorter.logger = Logger.new(@options.logfile) if @options.logfile
|
38
40
|
|
39
|
-
|
40
|
-
Imagesorter.logger = Logger.new(@options.logfile)
|
41
|
-
end
|
42
|
-
|
43
|
-
if @options.verbose == true
|
44
|
-
Imagesorter.logger.level = Logger::DEBUG
|
45
|
-
elsif @options.silent == true && !@options.logfile
|
46
|
-
Imagesorter.logger.level = Logger::FATAL
|
47
|
-
else
|
48
|
-
Imagesorter.logger.level = Logger::INFO
|
49
|
-
end
|
41
|
+
Imagesorter.logger.level = resolve_log_level
|
50
42
|
|
51
43
|
Imagesorter.logger.formatter = proc do |severity, datetime, _progname, msg|
|
52
44
|
date_format = datetime.strftime('%Y-%m-%d %H:%M:%S')
|
@@ -58,6 +50,14 @@ module Imagesorter
|
|
58
50
|
end
|
59
51
|
end
|
60
52
|
|
53
|
+
def resolve_log_level
|
54
|
+
return Logger::DEBUG if @options.verbose == true
|
55
|
+
|
56
|
+
return Logger::FATAL if @options.silent == true && !@options.logfile
|
57
|
+
|
58
|
+
Logger::INFO
|
59
|
+
end
|
60
|
+
|
61
61
|
def setup_locale
|
62
62
|
R18n.locale(@options.locale)
|
63
63
|
R18n.set(@options.locale)
|
@@ -65,18 +65,16 @@ module Imagesorter
|
|
65
65
|
|
66
66
|
def batch_options
|
67
67
|
options = {
|
68
|
-
source:
|
69
|
-
recursive:
|
68
|
+
source: @options.source,
|
69
|
+
recursive: @options.recursive,
|
70
70
|
extensions: @options.extensions,
|
71
|
-
processor:
|
71
|
+
processor: Imagesorter::FileSystemProcessor.new(destination: @options.dest,
|
72
72
|
destination_fmt: @options.destination_format,
|
73
|
-
copy_mode:
|
74
|
-
test:
|
73
|
+
copy_mode: @options.copy_mode,
|
74
|
+
test: @options.test)
|
75
75
|
}
|
76
76
|
|
77
|
-
if progressbar_enabled?
|
78
|
-
options[:progress_proc] = proc { |progress_options| progress(progress_options) }
|
79
|
-
end
|
77
|
+
options[:progress_proc] = proc { |progress_options| progress(progress_options) } if progressbar_enabled?
|
80
78
|
|
81
79
|
options
|
82
80
|
end
|
@@ -88,7 +86,7 @@ module Imagesorter
|
|
88
86
|
end
|
89
87
|
|
90
88
|
def finalize
|
91
|
-
@progressbar
|
89
|
+
@progressbar&.finish
|
92
90
|
end
|
93
91
|
|
94
92
|
def progressbar_enabled?
|
@@ -54,6 +54,7 @@ module Imagesorter
|
|
54
54
|
|
55
55
|
def collect_file_from_dir(dir, file)
|
56
56
|
return if file =~ /^\.\.?$/
|
57
|
+
|
57
58
|
full_path = File.join(dir, file)
|
58
59
|
|
59
60
|
if File.directory?(full_path)
|
@@ -80,12 +81,11 @@ module Imagesorter
|
|
80
81
|
queue_categorizing(file)
|
81
82
|
end
|
82
83
|
end
|
83
|
-
|
84
|
+
|
84
85
|
def queue_categorizing(file)
|
85
86
|
queue_job do
|
86
87
|
file.process!(@categorizer)
|
87
|
-
|
88
|
-
Imagesorter.logger.debug "#{file.file.path} metadata: #{JSON.pretty_generate(file.to_h)}"
|
88
|
+
# Imagesorter.logger.debug "#{file.file.path} metadata: #{JSON.pretty_generate(file.to_h)}"
|
89
89
|
|
90
90
|
increment(@categorizer.step_name)
|
91
91
|
queue_proceesing(file)
|
@@ -94,6 +94,7 @@ module Imagesorter
|
|
94
94
|
|
95
95
|
def queue_proceesing(file)
|
96
96
|
return if @processor.nil?
|
97
|
+
|
97
98
|
queue_job do
|
98
99
|
file.process!(@processor)
|
99
100
|
increment(@processor.step_name)
|
@@ -102,6 +103,7 @@ module Imagesorter
|
|
102
103
|
|
103
104
|
def increment(step)
|
104
105
|
return if @progress_proc.nil?
|
106
|
+
|
105
107
|
@progress_proc.call(step: step.ljust(14, ' '),
|
106
108
|
total_steps: @total_steps)
|
107
109
|
end
|
@@ -23,39 +23,17 @@ module Imagesorter
|
|
23
23
|
def process(file)
|
24
24
|
source = file.file.path
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
extension: File.extname(source).delete('.')
|
30
|
-
}
|
31
|
-
|
32
|
-
dest = begin
|
33
|
-
File.join(@destination, format(l(file.time, @destination_fmt), file.to_h.merge(destination_params)))
|
34
|
-
rescue KeyError => e
|
35
|
-
Imagesorter.logger.warn e.message
|
36
|
-
|
37
|
-
key = /^key<(.*)> not found$/.match(e.message)[1]
|
38
|
-
|
39
|
-
unless key.nil?
|
40
|
-
destination_params[key.to_sym] = ''
|
41
|
-
retry
|
42
|
-
else
|
43
|
-
raise
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
return if dest.nil?
|
48
|
-
|
49
|
-
dest = handle_duplicate(source, dest)
|
26
|
+
dest = handle_duplicate(source, format_destination(file, full_name: File.basename(source),
|
27
|
+
name: File.basename(source, '.*'),
|
28
|
+
extension: File.extname(source).delete('.')))
|
50
29
|
|
51
30
|
return if dest.nil?
|
52
31
|
|
53
|
-
dest_dir = File.dirname(dest)
|
54
|
-
|
55
32
|
Imagesorter.logger.info "#{step_name} #{source} to #{dest}"
|
56
33
|
|
57
34
|
return if @test
|
58
35
|
|
36
|
+
dest_dir = File.dirname(dest)
|
59
37
|
FileUtils.mkdir_p(dest_dir) unless File.directory?(dest_dir)
|
60
38
|
|
61
39
|
if @copy_mode == :move
|
@@ -65,7 +43,21 @@ module Imagesorter
|
|
65
43
|
end
|
66
44
|
end
|
67
45
|
|
46
|
+
def format_destination(file, destination_params)
|
47
|
+
File.join(@destination, format(l(file.time, @destination_fmt), file.to_h.merge(destination_params)))
|
48
|
+
rescue KeyError => e
|
49
|
+
Imagesorter.logger.warn e.message
|
50
|
+
|
51
|
+
key = /^key<(.*)> not found$/.match(e.message)[1]
|
52
|
+
|
53
|
+
raise if key.nil?
|
54
|
+
|
55
|
+
destination_params[key.to_sym] = ''
|
56
|
+
retry
|
57
|
+
end
|
58
|
+
|
68
59
|
def handle_duplicate(source, dest)
|
60
|
+
return nil if dest.nil?
|
69
61
|
return dest unless File.exist?(dest)
|
70
62
|
|
71
63
|
return nil if FileUtils.identical?(source, dest) # skip if identical
|
@@ -74,7 +66,7 @@ module Imagesorter
|
|
74
66
|
extname = File.extname(dest)
|
75
67
|
dirname = File.dirname(dest)
|
76
68
|
|
77
|
-
sequence = 1
|
69
|
+
sequence = 1
|
78
70
|
|
79
71
|
handle_duplicate(source, File.join(dirname, "#{basename}_#{sequence}#{extname}"))
|
80
72
|
end
|
data/lib/imagesorter/gem.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'optparse'
|
4
|
+
|
3
5
|
module Imagesorter
|
4
6
|
module OptionParser
|
5
7
|
DEFAULT_OPTIONS = {
|
6
|
-
silent:
|
7
|
-
test:
|
8
|
+
silent: false,
|
9
|
+
test: false,
|
8
10
|
recursive: false,
|
9
11
|
copy_mode: :copy,
|
10
|
-
threads:
|
11
|
-
locale:
|
12
|
-
extensions: %w[JPG JPEG MP4 MOV],
|
12
|
+
threads: 1,
|
13
|
+
locale: 'en-us',
|
14
|
+
extensions: %w[JPG JPEG MP4 MOV PNG CR2],
|
13
15
|
destination_format: '%Y/%m/%d/%{full_name}' # rubocop:disable Style/FormatStringToken
|
14
16
|
}.freeze
|
15
17
|
|
16
|
-
def self.parse(argv)
|
18
|
+
def self.parse(argv) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
17
19
|
options = OpenStruct.new(DEFAULT_OPTIONS)
|
18
20
|
|
19
21
|
# rubocop:disable Metrics/BlockLength
|
@@ -81,6 +83,7 @@ module Imagesorter
|
|
81
83
|
exit
|
82
84
|
end
|
83
85
|
end
|
86
|
+
# rubocop:enable Metrics/BlockLength
|
84
87
|
|
85
88
|
parser.parse!(argv)
|
86
89
|
|
@@ -97,6 +100,7 @@ module Imagesorter
|
|
97
100
|
mandatory = %i[source dest]
|
98
101
|
missing = mandatory.select { |param| options[param].nil? }
|
99
102
|
return if missing.empty?
|
103
|
+
|
100
104
|
raise ::OptionParser::MissingArgument, missing.join(', ')
|
101
105
|
end
|
102
106
|
end
|
data/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imagesorter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joakim Antman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: exifr
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: pry
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rspec
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rubocop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: simplecov
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -180,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
180
|
requirements:
|
181
181
|
- - ">="
|
182
182
|
- !ruby/object:Gem::Version
|
183
|
-
version: '2.
|
183
|
+
version: '2.4'
|
184
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
186
|
- - ">="
|
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
188
|
version: '0'
|
189
189
|
requirements: []
|
190
190
|
rubyforge_project:
|
191
|
-
rubygems_version: 2.
|
191
|
+
rubygems_version: 2.6.14
|
192
192
|
signing_key:
|
193
193
|
specification_version: 4
|
194
194
|
summary: Command line tool for sorting photos and videos
|