photish 0.3.3 → 0.3.4

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.
@@ -3,8 +3,8 @@ module Photish
3
3
  class FileConfigLocation
4
4
  FILE_NAME = 'config.yml'
5
5
 
6
- def initialize(site_dir)
7
- @site_dir = site_dir
6
+ def initialize(config_dir)
7
+ @config_dir = config_dir
8
8
  end
9
9
 
10
10
  def path
@@ -13,10 +13,10 @@ module Photish
13
13
 
14
14
  private
15
15
 
16
- attr_reader :site_dir
16
+ attr_reader :config_dir
17
17
 
18
18
  def directory
19
- site_dir || Dir.pwd
19
+ config_dir || Dir.pwd
20
20
  end
21
21
 
22
22
  def config_file_name
@@ -1,10 +1,10 @@
1
1
  module Photish
2
2
  module Gallery
3
3
  class Album
4
- include Photish::Gallery::Traits::Urlable
5
- include Photish::Gallery::Traits::Albumable
6
- include Photish::Gallery::Traits::Metadatable
7
- include Photish::Gallery::Traits::Breadcrumbable
4
+ include Traits::Urlable
5
+ include Traits::Albumable
6
+ include Traits::Metadatable
7
+ include Traits::Breadcrumbable
8
8
  include Photish::Plugin::Pluginable
9
9
 
10
10
  delegate :qualities,
@@ -25,8 +25,8 @@ module Photish
25
25
  @photos ||= Dir.entries(path)
26
26
  .reject { |file| ['.', '..'].include?(file) }
27
27
  .map { |file| File.join(path, file) }
28
- .reject { |file| !File.file?(file) }
29
- .reject { |file| !FileMagic.new(FileMagic::MAGIC_MIME).file(file).match(formats) }
28
+ .reject { |file| !File.file?(file) ||
29
+ !image_format?(file) }
30
30
  .map { |file| Photo.new(self, file) }
31
31
  end
32
32
 
@@ -41,6 +41,14 @@ module Photish
41
41
 
42
42
  alias_method :base_url_name, :name
43
43
 
44
+ def image_format?(file)
45
+ extension = File.extname(file).split('.').last.try(:downcase)
46
+ return if extension.nil?
47
+ MIME::Types.type_for(extension).any? do
48
+ |mime| mime.to_s.match(formats)
49
+ end
50
+ end
51
+
44
52
  def album_class
45
53
  self.class
46
54
  end
@@ -1,10 +1,10 @@
1
1
  module Photish
2
2
  module Gallery
3
3
  class Collection
4
- include Photish::Gallery::Traits::Urlable
5
- include Photish::Gallery::Traits::Albumable
6
- include Photish::Gallery::Traits::Metadatable
7
- include Photish::Gallery::Traits::Breadcrumbable
4
+ include Traits::Urlable
5
+ include Traits::Albumable
6
+ include Traits::Metadatable
7
+ include Traits::Breadcrumbable
8
8
  include Photish::Plugin::Pluginable
9
9
 
10
10
  attr_reader :qualities,
@@ -29,11 +29,11 @@ module Photish
29
29
  Photish::Plugin::Type::Collection
30
30
  end
31
31
 
32
- def all_url_paths
33
- @all_url_paths ||= [url_path,
34
- all_albums.map(&:url_path),
35
- all_photos.map(&:url_path),
36
- all_images.map(&:url_path)].flatten
32
+ def all_url_parts
33
+ @all_url_parts ||= [url_parts,
34
+ all_albums.map(&:url_parts),
35
+ all_photos.map(&:url_parts),
36
+ all_images.map(&:url_parts)].flatten(1)
37
37
  end
38
38
 
39
39
  private
@@ -1,7 +1,7 @@
1
1
  module Photish
2
2
  module Gallery
3
3
  class Image
4
- include Photish::Gallery::Traits::Urlable
4
+ include Traits::Urlable
5
5
  include Photish::Plugin::Pluginable
6
6
 
7
7
  delegate :name,
@@ -36,7 +36,7 @@ module Photish
36
36
  alias_method :base_url_name, :name
37
37
 
38
38
  def url_end
39
- "#{slugify(basename)}-#{slugify(quality_name)}#{extension}"
39
+ @url_end ||= "#{slugify(basename)}-#{slugify(quality_name)}#{extension}"
40
40
  end
41
41
 
42
42
  def basename
@@ -1,9 +1,9 @@
1
1
  module Photish
2
2
  module Gallery
3
3
  class Photo
4
- include Photish::Gallery::Traits::Urlable
5
- include Photish::Gallery::Traits::Metadatable
6
- include Photish::Gallery::Traits::Breadcrumbable
4
+ include Traits::Urlable
5
+ include Traits::Metadatable
6
+ include Traits::Breadcrumbable
7
7
  include Photish::Plugin::Pluginable
8
8
 
9
9
  delegate :qualities,
@@ -3,17 +3,13 @@ module Photish
3
3
  module Traits
4
4
  module Breadcrumbable
5
5
  def breadcrumbs
6
- doc = Nokogiri::HTML::DocumentFragment.parse("")
7
- Nokogiri::HTML::Builder.with(doc) do |doc|
8
- doc.ul(class: 'breadcrumbs') {
9
- parents_and_me.each_with_index do |level, index|
10
- doc.li(class: crumb_class(index)) {
11
- doc.a(level.name, href: level.url)
12
- }
13
- end
14
- }
6
+ html = "<ul class=\"breadcrumbs\">"
7
+ parents_and_me.each_with_index do |level, index|
8
+ html << "<li class=\"" << crumb_class(index) << "\">"
9
+ html << "<a href=\"" << level.url << "\">" << level.name << "</a>"
10
+ html << "</li>"
15
11
  end
16
- doc.to_html
12
+ html << "</ul>"
17
13
  end
18
14
 
19
15
  def parents_and_me
@@ -24,13 +20,12 @@ module Photish
24
20
  private
25
21
 
26
22
  def crumb_class(index)
27
- crumb_class = []
28
- crumb_class << 'breadcrumb'
29
- crumb_class << "crumb-#{index}"
30
- crumb_class << 'crumb-first' if index == 0
31
- crumb_class << 'crumb-last' if index == (parents_and_me.count - 1)
32
- crumb_class << 'crumb-only' if parents_and_me.count == 1
33
- crumb_class.join(' ')
23
+ crumb_class = 'breadcrumb'
24
+ crumb_class << ' crumb-' << index.to_s
25
+ crumb_class << ' crumb-first' if index == 0
26
+ crumb_class << ' crumb-last' if index == (parents_and_me.count - 1)
27
+ crumb_class << ' crumb-only' if parents_and_me.count == 1
28
+ crumb_class
34
29
  end
35
30
  end
36
31
  end
@@ -21,11 +21,7 @@ module Photish
21
21
  private
22
22
 
23
23
  def host
24
- @host ||= normalized_host || ''
25
- end
26
-
27
- def normalized_host
28
- url_info.host.try(:chomp, '/')
24
+ @host ||= url_info.host || ''
29
25
  end
30
26
 
31
27
  def slugify(word)
@@ -11,6 +11,7 @@ module Photish
11
11
 
12
12
  def setup_logging(config)
13
13
  return if setup_complete
14
+
14
15
  setup_color_scheme if colorize?(config)
15
16
  setup_stdout_output if output_to_stdout?(config)
16
17
  setup_file_output if output_to_file?(config)
@@ -22,7 +23,7 @@ module Photish
22
23
  private
23
24
 
24
25
  def logging_level(config)
25
- config.logging.level.to_sym
26
+ config.logging.level.try(:to_sym)
26
27
  end
27
28
 
28
29
  def colorize?(config)
@@ -55,7 +56,7 @@ module Photish
55
56
  stdout_appender = Logging.appenders.stdout(
56
57
  'stdout',
57
58
  layout: Logging.layouts.pattern(
58
- pattern: '[%d] %-5l %c: %m\n',
59
+ pattern: '[%d][%p][%t] %-5l %c: %m\n',
59
60
  color_scheme: 'bright'
60
61
  )
61
62
  )
@@ -67,7 +68,7 @@ module Photish
67
68
  file_appender = Logging.appenders.file(
68
69
  'log/photish.log',
69
70
  layout: Logging.layouts.pattern(
70
- pattern: '[%d] %-5l %c: %m\n',
71
+ pattern: '[%d][%p][%t] %-5l %c: %m\n',
71
72
  )
72
73
  )
73
74
  Logging.logger.root.add_appenders(file_appender)
@@ -1,39 +1,63 @@
1
1
  module Photish
2
2
  module Plugin
3
- module Repository
3
+ class Repository
4
+ include Singleton
5
+
4
6
  class << self
5
7
  def reload(log, site_dir)
6
- log.info "Loading plugins..."
7
- Dir[File.join(site_dir, '_plugins', '*.rb')].each do |file|
8
- load file
9
- end
10
-
11
- all_plugins.each do |plugin|
12
- log.info "Found plugin #{plugin}"
13
- end
8
+ self.instance.reload(log, site_dir)
14
9
  end
15
10
 
16
11
  def plugins_for(type)
17
- all_plugins.reject { |m| !m.is_for?(type) }
12
+ self.instance.plugins_for(type)
18
13
  end
19
14
 
20
- def all_plugins
21
- Photish::Plugin.constants.map { |m| constantize(m) }
22
- .reject { |m| ignored_modules.include?(m) }
15
+ def loaded?
16
+ self.instance.loaded?
23
17
  end
24
-
25
- private
18
+ end
26
19
 
27
- def ignored_modules
28
- [Photish::Plugin::Repository,
29
- Photish::Plugin::Pluginable,
30
- Photish::Plugin::Type]
20
+ def reload(log, site_dir)
21
+ log.info "Loading plugins..."
22
+ Dir[File.join(site_dir, '_plugins', '*.rb')].each do |file|
23
+ load file
31
24
  end
32
25
 
33
- def constantize(symbol)
34
- Kernel.const_get("Photish::Plugin::#{symbol}")
26
+ @all_plugins = nil
27
+
28
+ all_plugins.each do |plugin|
29
+ log.info "Found plugin #{plugin}"
35
30
  end
36
31
  end
32
+
33
+ def plugins_for(type)
34
+ all_plugins.reject { |m| !m.is_for?(type) }
35
+ end
36
+
37
+ def all_plugins
38
+ @all_plugins ||= constants.map { |m| constantize(m) }
39
+ .reject { |m| ignored_modules.include?(m) }
40
+ end
41
+
42
+ def loaded?
43
+ @all_plugins.present?
44
+ end
45
+
46
+ private
47
+
48
+ def constants
49
+ Photish::Plugin.constants
50
+ end
51
+
52
+ def ignored_modules
53
+ [Photish::Plugin::Repository,
54
+ Photish::Plugin::Pluginable,
55
+ Photish::Plugin::Type]
56
+ end
57
+
58
+ def constantize(symbol)
59
+ Kernel.const_get("Photish::Plugin::#{symbol}")
60
+ end
37
61
  end
38
62
  end
39
63
  end
@@ -1,30 +1,20 @@
1
1
  module Photish
2
2
  module Render
3
3
  class ImageConversion
4
- def initialize(output_dir, max_workers)
4
+ def initialize(output_dir, worker_index, version_hash, threads)
5
5
  @output_dir = output_dir
6
- @max_workers = max_workers
6
+ @worker_index = worker_index
7
+ @version_hash = version_hash
8
+ @threads = threads
7
9
  @log = Logging.logger[self]
8
10
  end
9
11
 
10
12
  def render(images)
11
- image_queue = to_queue(images)
12
-
13
- log.info "Rendering #{images.count} images across #{max_workers} threads"
13
+ log.info "Rendering #{images.count} images across #{threads} threads"
14
14
 
15
15
  change_manifest.preload
16
- workers = (0...max_workers).map do
17
- Thread.new do
18
- begin
19
- while image = image_queue.pop(true)
20
- convert(image) if changed?(image.url_path, image.path)
21
- end
22
- rescue ThreadError => e
23
- log.info "Expected exception, queue is empty #{e.class} \"#{e.message}\" #{e.backtrace.join("\n")}"
24
- end
25
- end
26
- end
27
- workers.map(&:join)
16
+ threads = spawn_thread_instances(to_queue(images))
17
+ threads.map(&:join)
28
18
  flush_to_disk
29
19
  end
30
20
 
@@ -32,16 +22,32 @@ module Photish
32
22
 
33
23
  attr_reader :output_dir,
34
24
  :log,
35
- :max_workers
25
+ :worker_index,
26
+ :version_hash,
27
+ :threads
36
28
 
37
29
  delegate :record,
38
30
  :changed?,
39
31
  :flush_to_disk,
32
+ :preload,
40
33
  to: :change_manifest
41
34
 
35
+ def spawn_thread_instances(image_queue)
36
+ (0...threads).map do
37
+ Thread.new { process_images(image_queue) }
38
+ end
39
+ end
40
+
41
+ def process_images(image_queue)
42
+ while !image_queue.empty?
43
+ image = image_queue.pop
44
+ convert(image) if changed?(image.url_path, image.path)
45
+ end
46
+ end
47
+
42
48
  def to_queue(images)
43
49
  image_queue = Queue.new
44
- Array(images).each { |image| image_queue << image }
50
+ Array(images).shuffle.each { |image| image_queue << image }
45
51
  image_queue
46
52
  end
47
53
 
@@ -69,7 +75,9 @@ module Photish
69
75
  end
70
76
 
71
77
  def change_manifest
72
- @change_manifest ||= ChangeManifest.new(output_dir)
78
+ @change_manifest ||= Cache::Manifest.new(output_dir,
79
+ worker_index,
80
+ version_hash)
73
81
  end
74
82
  end
75
83
  end
@@ -1,58 +1,44 @@
1
1
  module Photish
2
2
  module Render
3
3
  class Site
4
- def initialize(templates, site_dir, output_dir, max_workers)
5
- @templates = templates
6
- @site_dir = site_dir
7
- @output_dir = output_dir
8
- @max_workers = max_workers
4
+ def initialize(config)
5
+ @config = config
9
6
  end
10
7
 
11
8
  def all_for(collection)
12
- delete_unknown_files(collection.all_url_paths)
9
+ delete_unknown_files(collection.all_url_parts)
13
10
  move_non_ignored_site_contents
14
-
15
11
  collection_template.render(collection)
16
- album_template.render(collection.all_albums)
17
- photo_template.render(collection.all_photos)
18
-
19
- image_conversion.render(collection.all_images)
20
12
  end
21
13
 
22
14
  private
23
15
 
24
- attr_reader :templates,
25
- :site_dir,
26
- :output_dir,
27
- :max_workers
16
+ attr_reader :config
28
17
 
29
- def delete_unknown_files(expected_url_paths)
30
- files_to_delete = Dir["#{output_dir}/**/*"].select do |f|
31
- relative_file_path = f.gsub(/#{output_dir}\/?/, '')
32
- File.file?(f) && expected_url_paths.exclude?(relative_file_path)
33
- end
34
- FileUtils.rm_rf(files_to_delete)
35
- end
18
+ delegate :templates,
19
+ :site_dir,
20
+ :output_dir,
21
+ :worker_index,
22
+ to: :config
36
23
 
37
24
  def move_non_ignored_site_contents
38
25
  FileUtils.mkdir_p(output_dir)
39
26
  FileUtils.cp_r(non_ignored_site_contents, output_dir)
40
27
  end
41
28
 
42
- def image_conversion
43
- Photish::Render::ImageConversion.new(output_dir, max_workers)
44
- end
45
-
46
- def album_template
47
- Photish::Render::Page.new(layout_file, template_album_file, output_dir)
48
- end
49
-
50
- def photo_template
51
- Photish::Render::Page.new(layout_file, template_photo_file, output_dir)
29
+ def delete_unknown_files(url_parts)
30
+ do_not_delete = Set.new(url_parts.map { |url| File.join(output_dir, url) }
31
+ .map(&:to_s))
32
+ files_to_delete = Dir["#{output_dir}/**/*"].select do |f|
33
+ File.file?(f) && !do_not_delete.include?(f)
34
+ end
35
+ FileUtils.rm_rf(files_to_delete)
52
36
  end
53
37
 
54
38
  def collection_template
55
- Photish::Render::Page.new(layout_file, template_collection_file, output_dir)
39
+ Page.new(layout_file,
40
+ template_collection_file,
41
+ output_dir)
56
42
  end
57
43
 
58
44
  def non_ignored_site_contents
@@ -67,14 +53,6 @@ module Photish
67
53
  File.join(site_dir, templates_dir, templates.collection)
68
54
  end
69
55
 
70
- def template_album_file
71
- File.join(site_dir, templates_dir, templates.album)
72
- end
73
-
74
- def template_photo_file
75
- File.join(site_dir, templates_dir, templates.photo)
76
- end
77
-
78
56
  def templates_dir
79
57
  '_templates'
80
58
  end
@@ -0,0 +1,80 @@
1
+ module Photish
2
+ module Render
3
+ class SiteWorker
4
+ def initialize(config, version_hash)
5
+ @config = config
6
+ @version_hash = version_hash
7
+ end
8
+
9
+ def all_for(collection)
10
+ tasks(collection).shuffle.each(&:call)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :config,
16
+ :version_hash
17
+
18
+ delegate :templates,
19
+ :site_dir,
20
+ :output_dir,
21
+ :workers,
22
+ :threads,
23
+ :worker_index,
24
+ to: :config
25
+
26
+ def tasks(collection)
27
+ [
28
+ ->{ album_template.render(subset(collection.all_albums)) },
29
+ ->{ photo_template.render(subset(collection.all_photos)) },
30
+ ->{ image_conversion.render(subset(collection.all_images)) },
31
+ ]
32
+ end
33
+
34
+ def subset(items)
35
+ worker_index_zeroed.step(items.count, workers)
36
+ .map { |i| items[i] }
37
+ .compact
38
+ end
39
+
40
+ def image_conversion
41
+ ImageConversion.new(output_dir,
42
+ worker_index,
43
+ version_hash,
44
+ threads)
45
+ end
46
+
47
+ def album_template
48
+ Page.new(layout_file,
49
+ template_album_file,
50
+ output_dir)
51
+ end
52
+
53
+ def photo_template
54
+ Page.new(layout_file,
55
+ template_photo_file,
56
+ output_dir)
57
+ end
58
+
59
+ def layout_file
60
+ File.join(site_dir, templates_dir, templates.layout)
61
+ end
62
+
63
+ def template_album_file
64
+ File.join(site_dir, templates_dir, templates.album)
65
+ end
66
+
67
+ def template_photo_file
68
+ File.join(site_dir, templates_dir, templates.photo)
69
+ end
70
+
71
+ def templates_dir
72
+ '_templates'
73
+ end
74
+
75
+ def worker_index_zeroed
76
+ worker_index - 1
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module Photish
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.4"
3
3
  end
data/lib/photish.rb CHANGED
@@ -10,16 +10,20 @@ require 'webrick'
10
10
  require 'listen'
11
11
  require 'yaml'
12
12
  require 'thor'
13
- require 'filemagic'
14
13
  require 'recursive_open_struct'
15
14
  require 'cgi'
16
15
  require 'facter'
16
+ require 'mime-types'
17
+ require 'thread'
18
+ require 'thwait'
19
+ require 'slim'
17
20
 
18
21
  # Photish
19
22
  require 'photish/plugin/type'
20
23
  require 'photish/plugin/pluginable'
21
24
  require 'photish/plugin/repository'
22
25
  require 'photish/command/base'
26
+ require 'photish/command/worker'
23
27
  require 'photish/command/generate'
24
28
  require 'photish/command/host'
25
29
  require 'photish/command/init'
@@ -43,8 +47,10 @@ require 'photish/gallery/image'
43
47
  require 'photish/gallery/collection'
44
48
  require 'photish/render/page'
45
49
  require 'photish/render/site'
50
+ require 'photish/render/site_worker'
46
51
  require 'photish/render/image_conversion'
47
- require 'photish/render/change_manifest'
52
+ require 'photish/cache/manifest'
53
+ require 'photish/cache/manifest_db_file'
48
54
  require 'photish/rake/task'
49
55
  require 'photish/version'
50
56
 
data/photish.gemspec CHANGED
@@ -27,13 +27,12 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "slim", "~> 3.0"
28
28
  spec.add_dependency "tilt", "~> 2.0"
29
29
  spec.add_dependency "mini_magick", "~> 4.3"
30
- spec.add_dependency "ruby-filemagic", "~> 0.7"
31
30
  spec.add_dependency "mini_exiftool", "~> 2.5"
32
31
  spec.add_dependency "recursive-open-struct", "~> 1.0"
33
- spec.add_dependency "nokogiri", "~> 1.6"
34
32
  spec.add_dependency "logging", "~> 2.0"
35
33
  spec.add_dependency "listen", "~> 3.0"
36
34
  spec.add_dependency "facter", "~> 2.4"
35
+ spec.add_dependency "mime-types", "~> 3.0"
37
36
 
38
37
  spec.add_development_dependency "anemone", "~> 0.7"
39
38
  spec.add_development_dependency "bundler", "~> 1.10"