nanoc 3.2.4 → 3.3.0

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.
Files changed (230) hide show
  1. data/.gemtest +0 -0
  2. data/ChangeLog +3 -0
  3. data/Gemfile +32 -0
  4. data/LICENSE +19 -0
  5. data/NEWS.md +470 -0
  6. data/README.md +114 -0
  7. data/Rakefile +14 -0
  8. data/bin/nanoc +7 -27
  9. data/bin/nanoc3 +3 -0
  10. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  11. data/lib/nanoc.rb +41 -0
  12. data/lib/nanoc/base.rb +49 -0
  13. data/lib/nanoc/base/compilation/checksum_store.rb +57 -0
  14. data/lib/nanoc/base/compilation/compiled_content_cache.rb +62 -0
  15. data/lib/nanoc/base/compilation/compiler.rb +458 -0
  16. data/lib/nanoc/base/compilation/compiler_dsl.rb +214 -0
  17. data/lib/nanoc/base/compilation/dependency_tracker.rb +200 -0
  18. data/lib/nanoc/base/compilation/filter.rb +165 -0
  19. data/lib/nanoc/base/compilation/item_rep_proxy.rb +103 -0
  20. data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +102 -0
  21. data/lib/nanoc/base/compilation/outdatedness_checker.rb +223 -0
  22. data/lib/nanoc/base/compilation/outdatedness_reasons.rb +46 -0
  23. data/lib/nanoc/base/compilation/rule.rb +73 -0
  24. data/lib/nanoc/base/compilation/rule_context.rb +84 -0
  25. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +40 -0
  26. data/lib/nanoc/base/compilation/rule_memory_store.rb +53 -0
  27. data/lib/nanoc/base/compilation/rules_collection.rb +243 -0
  28. data/lib/nanoc/base/context.rb +47 -0
  29. data/lib/nanoc/base/core_ext.rb +6 -0
  30. data/lib/nanoc/base/core_ext/array.rb +62 -0
  31. data/lib/nanoc/base/core_ext/hash.rb +63 -0
  32. data/lib/nanoc/base/core_ext/pathname.rb +26 -0
  33. data/lib/nanoc/base/core_ext/string.rb +46 -0
  34. data/lib/nanoc/base/directed_graph.rb +275 -0
  35. data/lib/nanoc/base/errors.rb +211 -0
  36. data/lib/nanoc/base/memoization.rb +67 -0
  37. data/lib/nanoc/base/notification_center.rb +84 -0
  38. data/lib/nanoc/base/ordered_hash.rb +200 -0
  39. data/lib/nanoc/base/plugin_registry.rb +181 -0
  40. data/lib/nanoc/base/result_data/item_rep.rb +492 -0
  41. data/lib/nanoc/base/source_data/code_snippet.rb +58 -0
  42. data/lib/nanoc/base/source_data/configuration.rb +24 -0
  43. data/lib/nanoc/base/source_data/data_source.rb +234 -0
  44. data/lib/nanoc/base/source_data/item.rb +301 -0
  45. data/lib/nanoc/base/source_data/layout.rb +130 -0
  46. data/lib/nanoc/base/source_data/site.rb +361 -0
  47. data/lib/nanoc/base/store.rb +135 -0
  48. data/lib/nanoc/cli.rb +137 -0
  49. data/lib/nanoc/cli/command_runner.rb +104 -0
  50. data/lib/nanoc/cli/commands/autocompile.rb +58 -0
  51. data/lib/nanoc/cli/commands/compile.rb +297 -0
  52. data/lib/nanoc/cli/commands/create_item.rb +60 -0
  53. data/lib/nanoc/cli/commands/create_layout.rb +73 -0
  54. data/lib/nanoc/cli/commands/create_site.rb +411 -0
  55. data/lib/nanoc/cli/commands/debug.rb +117 -0
  56. data/lib/nanoc/cli/commands/deploy.rb +79 -0
  57. data/lib/nanoc/cli/commands/info.rb +98 -0
  58. data/lib/nanoc/cli/commands/nanoc.rb +38 -0
  59. data/lib/nanoc/cli/commands/prune.rb +50 -0
  60. data/lib/nanoc/cli/commands/update.rb +70 -0
  61. data/lib/nanoc/cli/commands/view.rb +82 -0
  62. data/lib/nanoc/cli/commands/watch.rb +124 -0
  63. data/lib/nanoc/cli/error_handler.rb +199 -0
  64. data/lib/nanoc/cli/logger.rb +92 -0
  65. data/lib/nanoc/data_sources.rb +29 -0
  66. data/lib/nanoc/data_sources/deprecated/delicious.rb +42 -0
  67. data/lib/nanoc/data_sources/deprecated/last_fm.rb +87 -0
  68. data/lib/nanoc/data_sources/deprecated/twitter.rb +38 -0
  69. data/lib/nanoc/data_sources/filesystem.rb +299 -0
  70. data/lib/nanoc/data_sources/filesystem_unified.rb +121 -0
  71. data/lib/nanoc/data_sources/filesystem_verbose.rb +91 -0
  72. data/lib/nanoc/extra.rb +24 -0
  73. data/lib/nanoc/extra/auto_compiler.rb +103 -0
  74. data/lib/nanoc/extra/chick.rb +125 -0
  75. data/lib/nanoc/extra/core_ext.rb +6 -0
  76. data/lib/nanoc/extra/core_ext/enumerable.rb +33 -0
  77. data/lib/nanoc/extra/core_ext/pathname.rb +30 -0
  78. data/lib/nanoc/extra/core_ext/time.rb +19 -0
  79. data/lib/nanoc/extra/deployer.rb +47 -0
  80. data/lib/nanoc/extra/deployers.rb +15 -0
  81. data/lib/nanoc/extra/deployers/fog.rb +98 -0
  82. data/lib/nanoc/extra/deployers/rsync.rb +70 -0
  83. data/lib/nanoc/extra/file_proxy.rb +40 -0
  84. data/lib/nanoc/extra/pruner.rb +86 -0
  85. data/lib/nanoc/extra/validators.rb +12 -0
  86. data/lib/nanoc/extra/validators/links.rb +268 -0
  87. data/lib/nanoc/extra/validators/w3c.rb +95 -0
  88. data/lib/nanoc/extra/vcs.rb +66 -0
  89. data/lib/nanoc/extra/vcses.rb +17 -0
  90. data/lib/nanoc/extra/vcses/bazaar.rb +25 -0
  91. data/lib/nanoc/extra/vcses/dummy.rb +24 -0
  92. data/lib/nanoc/extra/vcses/git.rb +25 -0
  93. data/lib/nanoc/extra/vcses/mercurial.rb +25 -0
  94. data/lib/nanoc/extra/vcses/subversion.rb +25 -0
  95. data/lib/nanoc/filters.rb +59 -0
  96. data/lib/nanoc/filters/asciidoc.rb +38 -0
  97. data/lib/nanoc/filters/bluecloth.rb +19 -0
  98. data/lib/nanoc/filters/coderay.rb +21 -0
  99. data/lib/nanoc/filters/coffeescript.rb +20 -0
  100. data/lib/nanoc/filters/colorize_syntax.rb +298 -0
  101. data/lib/nanoc/filters/erb.rb +38 -0
  102. data/lib/nanoc/filters/erubis.rb +34 -0
  103. data/lib/nanoc/filters/haml.rb +27 -0
  104. data/lib/nanoc/filters/kramdown.rb +20 -0
  105. data/lib/nanoc/filters/less.rb +53 -0
  106. data/lib/nanoc/filters/markaby.rb +20 -0
  107. data/lib/nanoc/filters/maruku.rb +20 -0
  108. data/lib/nanoc/filters/mustache.rb +24 -0
  109. data/lib/nanoc/filters/rainpress.rb +19 -0
  110. data/lib/nanoc/filters/rdiscount.rb +22 -0
  111. data/lib/nanoc/filters/rdoc.rb +33 -0
  112. data/lib/nanoc/filters/redcarpet.rb +62 -0
  113. data/lib/nanoc/filters/redcloth.rb +47 -0
  114. data/lib/nanoc/filters/relativize_paths.rb +94 -0
  115. data/lib/nanoc/filters/rubypants.rb +20 -0
  116. data/lib/nanoc/filters/sass.rb +74 -0
  117. data/lib/nanoc/filters/slim.rb +25 -0
  118. data/lib/nanoc/filters/typogruby.rb +23 -0
  119. data/lib/nanoc/filters/uglify_js.rb +42 -0
  120. data/lib/nanoc/filters/xsl.rb +46 -0
  121. data/lib/nanoc/filters/yui_compressor.rb +23 -0
  122. data/lib/nanoc/helpers.rb +16 -0
  123. data/lib/nanoc/helpers/blogging.rb +319 -0
  124. data/lib/nanoc/helpers/breadcrumbs.rb +40 -0
  125. data/lib/nanoc/helpers/capturing.rb +138 -0
  126. data/lib/nanoc/helpers/filtering.rb +50 -0
  127. data/lib/nanoc/helpers/html_escape.rb +55 -0
  128. data/lib/nanoc/helpers/link_to.rb +151 -0
  129. data/lib/nanoc/helpers/rendering.rb +140 -0
  130. data/lib/nanoc/helpers/tagging.rb +71 -0
  131. data/lib/nanoc/helpers/text.rb +44 -0
  132. data/lib/nanoc/helpers/xml_sitemap.rb +76 -0
  133. data/lib/nanoc/tasks.rb +10 -0
  134. data/lib/nanoc/tasks/clean.rake +16 -0
  135. data/lib/nanoc/tasks/clean.rb +29 -0
  136. data/lib/nanoc/tasks/deploy/rsync.rake +16 -0
  137. data/lib/nanoc/tasks/validate.rake +92 -0
  138. data/nanoc.gemspec +49 -0
  139. data/tasks/doc.rake +16 -0
  140. data/tasks/test.rake +46 -0
  141. data/test/base/core_ext/array_spec.rb +73 -0
  142. data/test/base/core_ext/hash_spec.rb +98 -0
  143. data/test/base/core_ext/pathname_spec.rb +27 -0
  144. data/test/base/core_ext/string_spec.rb +37 -0
  145. data/test/base/test_checksum_store.rb +35 -0
  146. data/test/base/test_code_snippet.rb +31 -0
  147. data/test/base/test_compiler.rb +403 -0
  148. data/test/base/test_compiler_dsl.rb +161 -0
  149. data/test/base/test_context.rb +31 -0
  150. data/test/base/test_data_source.rb +46 -0
  151. data/test/base/test_dependency_tracker.rb +262 -0
  152. data/test/base/test_directed_graph.rb +288 -0
  153. data/test/base/test_filter.rb +83 -0
  154. data/test/base/test_item.rb +179 -0
  155. data/test/base/test_item_rep.rb +579 -0
  156. data/test/base/test_layout.rb +59 -0
  157. data/test/base/test_memoization.rb +90 -0
  158. data/test/base/test_notification_center.rb +34 -0
  159. data/test/base/test_outdatedness_checker.rb +394 -0
  160. data/test/base/test_plugin.rb +30 -0
  161. data/test/base/test_rule.rb +19 -0
  162. data/test/base/test_rule_context.rb +65 -0
  163. data/test/base/test_site.rb +190 -0
  164. data/test/cli/commands/test_compile.rb +33 -0
  165. data/test/cli/commands/test_create_item.rb +14 -0
  166. data/test/cli/commands/test_create_layout.rb +28 -0
  167. data/test/cli/commands/test_create_site.rb +24 -0
  168. data/test/cli/commands/test_deploy.rb +74 -0
  169. data/test/cli/commands/test_help.rb +12 -0
  170. data/test/cli/commands/test_info.rb +11 -0
  171. data/test/cli/commands/test_prune.rb +98 -0
  172. data/test/cli/commands/test_update.rb +10 -0
  173. data/test/cli/test_cli.rb +102 -0
  174. data/test/cli/test_error_handler.rb +29 -0
  175. data/test/cli/test_logger.rb +10 -0
  176. data/test/data_sources/test_filesystem.rb +433 -0
  177. data/test/data_sources/test_filesystem_unified.rb +536 -0
  178. data/test/data_sources/test_filesystem_verbose.rb +357 -0
  179. data/test/extra/core_ext/test_enumerable.rb +30 -0
  180. data/test/extra/core_ext/test_pathname.rb +17 -0
  181. data/test/extra/core_ext/test_time.rb +15 -0
  182. data/test/extra/deployers/test_fog.rb +67 -0
  183. data/test/extra/deployers/test_rsync.rb +100 -0
  184. data/test/extra/test_auto_compiler.rb +417 -0
  185. data/test/extra/test_file_proxy.rb +19 -0
  186. data/test/extra/test_vcs.rb +22 -0
  187. data/test/extra/validators/test_links.rb +62 -0
  188. data/test/extra/validators/test_w3c.rb +47 -0
  189. data/test/filters/test_asciidoc.rb +22 -0
  190. data/test/filters/test_bluecloth.rb +18 -0
  191. data/test/filters/test_coderay.rb +44 -0
  192. data/test/filters/test_coffeescript.rb +18 -0
  193. data/test/filters/test_colorize_syntax.rb +379 -0
  194. data/test/filters/test_erb.rb +105 -0
  195. data/test/filters/test_erubis.rb +78 -0
  196. data/test/filters/test_haml.rb +96 -0
  197. data/test/filters/test_kramdown.rb +18 -0
  198. data/test/filters/test_less.rb +113 -0
  199. data/test/filters/test_markaby.rb +24 -0
  200. data/test/filters/test_maruku.rb +18 -0
  201. data/test/filters/test_mustache.rb +25 -0
  202. data/test/filters/test_rainpress.rb +29 -0
  203. data/test/filters/test_rdiscount.rb +31 -0
  204. data/test/filters/test_rdoc.rb +18 -0
  205. data/test/filters/test_redcarpet.rb +73 -0
  206. data/test/filters/test_redcloth.rb +33 -0
  207. data/test/filters/test_relativize_paths.rb +533 -0
  208. data/test/filters/test_rubypants.rb +18 -0
  209. data/test/filters/test_sass.rb +229 -0
  210. data/test/filters/test_slim.rb +35 -0
  211. data/test/filters/test_typogruby.rb +21 -0
  212. data/test/filters/test_uglify_js.rb +30 -0
  213. data/test/filters/test_xsl.rb +105 -0
  214. data/test/filters/test_yui_compressor.rb +44 -0
  215. data/test/gem_loader.rb +11 -0
  216. data/test/helper.rb +207 -0
  217. data/test/helpers/test_blogging.rb +754 -0
  218. data/test/helpers/test_breadcrumbs.rb +81 -0
  219. data/test/helpers/test_capturing.rb +41 -0
  220. data/test/helpers/test_filtering.rb +106 -0
  221. data/test/helpers/test_html_escape.rb +32 -0
  222. data/test/helpers/test_link_to.rb +249 -0
  223. data/test/helpers/test_rendering.rb +89 -0
  224. data/test/helpers/test_tagging.rb +87 -0
  225. data/test/helpers/test_text.rb +24 -0
  226. data/test/helpers/test_xml_sitemap.rb +103 -0
  227. data/test/tasks/test_clean.rb +67 -0
  228. metadata +327 -15
  229. data/bin/nanoc-select +0 -86
  230. data/lib/nanoc-select.rb +0 -11
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ require 'nanoc/extra/core_ext/enumerable'
4
+ require 'nanoc/extra/core_ext/pathname'
5
+ require 'nanoc/extra/core_ext/time'
6
+
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ module Enumerable
4
+
5
+ if !Enumerable.instance_methods.include?('group_by')
6
+
7
+ # Returns a hash, which keys are evaluated result from the block, and
8
+ # values are arrays of elements in enum corresponding to the key. This
9
+ # method is provided for backward compatibility with Ruby 1.8.6 and lower,
10
+ # since {#group_by} is only available in 1.8.7 and higher.
11
+ #
12
+ # @yieldparam [Object] obj The object to classify
13
+ #
14
+ # @return [Hash]
15
+ #
16
+ # @example Grouping integers by rest by division through 3
17
+ #
18
+ # (1..6).group_by { |i| i % 3 }
19
+ # # => { 0 => [3, 6], 1 => [1, 4], 2 => [2, 5] }
20
+ def group_by
21
+ groups = {}
22
+ each do |item|
23
+ key = yield(item)
24
+
25
+ groups[key] ||= []
26
+ groups[key] << item
27
+ end
28
+ groups
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ module PathnameExtensions
6
+
7
+ def components
8
+ components = []
9
+ tmp = self
10
+ loop do
11
+ old = tmp
12
+ components << File.basename(tmp)
13
+ tmp = File.dirname(tmp)
14
+ break if old == tmp
15
+ end
16
+ components.reverse
17
+ end
18
+
19
+ def include_component?(component)
20
+ self.components.include?(component)
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ class ::Pathname
28
+ include ::Nanoc::Extra::PathnameExtensions
29
+ end
30
+
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra::TimeExtensions
4
+
5
+ # @return [String] The time in an ISO-8601 date format.
6
+ def to_iso8601_date
7
+ self.strftime("%Y-%m-%d")
8
+ end
9
+
10
+ # @return [String] The time in an ISO-8601 time format.
11
+ def to_iso8601_time
12
+ self.getutc.strftime("%Y-%m-%dT%H:%M:%SZ")
13
+ end
14
+
15
+ end
16
+
17
+ class Time
18
+ include Nanoc::Extra::TimeExtensions
19
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ # Represents a deployer, an object that allows uploading the compiled site
6
+ # to a specific (remote) location.
7
+ #
8
+ # @abstract Subclass and override {#run} to implement a custom filter.
9
+ class Deployer
10
+
11
+ extend Nanoc::PluginRegistry::PluginMethods
12
+
13
+ # @return [String] The path to the directory that contains the files to
14
+ # upload. It should not have a trailing slash.
15
+ attr_reader :source_path
16
+
17
+ # @return [Hash] The deployer configuration
18
+ attr_reader :config
19
+
20
+ # @return [Boolean] true if the deployer should only show what would be
21
+ # deployed instead of doing the actual deployment
22
+ attr_reader :dry_run
23
+ alias_method :dry_run?, :dry_run
24
+
25
+ # @param [String] source_path The path to the directory that contains the
26
+ # files to upload. It should not have a trailing slash.
27
+ #
28
+ # @return [Hash] config The deployer configuration
29
+ #
30
+ # @option params [Boolean] :dry_run (false) true if the deployer should
31
+ # only show what would be deployed instead actually deploying
32
+ def initialize(source_path, config, params={})
33
+ @source_path = source_path
34
+ @config = config
35
+ @dry_run = params.fetch(:dry_run) { false }
36
+ end
37
+
38
+ # Performs the actual deployment.
39
+ #
40
+ # @abstract
41
+ def run
42
+ raise NotImplementedError.new("Nanoc::Extra::Deployer subclasses must implement #run")
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ module Deployers
6
+
7
+ autoload 'Fog', 'nanoc/extra/deployers/fog'
8
+ autoload 'Rsync', 'nanoc/extra/deployers/rsync'
9
+
10
+ Nanoc::Extra::Deployer.register '::Nanoc::Extra::Deployers::Fog', :fog
11
+ Nanoc::Extra::Deployer.register '::Nanoc::Extra::Deployers::Rsync', :rsync
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra::Deployers
4
+
5
+ # A deployer that deploys a site using [fog](https://github.com/geemus/fog).
6
+ #
7
+ # @example A deployment configuration with public and staging configurations
8
+ #
9
+ # deploy:
10
+ # public:
11
+ # kind: fog
12
+ # provider: local
13
+ # local_root: ~/myCloud
14
+ # bucket: nanoc-site
15
+ # staging:
16
+ # kind: fog
17
+ # provider: local
18
+ # local_root: ~/myCloud
19
+ # bucket: nanoc-site-staging
20
+ class Fog < ::Nanoc::Extra::Deployer
21
+
22
+ # @see Nanoc::Extra::Deployer#run
23
+ def run
24
+ require 'fog'
25
+
26
+ # Get params
27
+ src = File.expand_path(self.source_path)
28
+ bucket = self.config.delete(:bucket) || self.config.delete(:bucket_name)
29
+ path = self.config[:path]
30
+
31
+ self.config.delete(:kind)
32
+
33
+ # Validate params
34
+ error 'The path requires no trailing slash' if path && path[-1,1] == '/'
35
+
36
+ # Mock if necessary
37
+ if self.dry_run?
38
+ ::Fog.mock!
39
+ end
40
+
41
+ # Get connection
42
+ puts "Connecting"
43
+ connection = ::Fog::Storage.new(self.config)
44
+
45
+ # Get bucket
46
+ puts "Getting bucket"
47
+ begin
48
+ directory = connection.directories.get(bucket)
49
+ rescue ::Excon::Errors::NotFound
50
+ should_create_bucket = true
51
+ end
52
+ should_create_bucket = true if directory.nil?
53
+
54
+ # Create bucket if necessary
55
+ if should_create_bucket
56
+ directory = connection.directories.create(:key => bucket)
57
+ end
58
+
59
+ # Get list of remote files
60
+ files = directory.files
61
+ truncated = files.respond_to?(:is_truncated) && files.is_truncated
62
+ while truncated
63
+ set = directory.files.all(:marker => files.last.key)
64
+ truncated = set.is_truncated
65
+ files = files + set
66
+ end
67
+
68
+ # Delete all the files in the bucket
69
+ puts "Removing remote files"
70
+ files.all.each do |file|
71
+ file.destroy
72
+ end
73
+
74
+ # Upload all the files in the output folder to the clouds
75
+ puts "Uploading local files"
76
+ FileUtils.cd(src) do
77
+ files = Dir['**/*'].select { |f| File.file?(f) }
78
+ files.each do |file_path|
79
+ directory.files.create(
80
+ :key => "#{path}#{file_path}",
81
+ :body => File.open(file_path),
82
+ :public => true)
83
+ end
84
+ end
85
+
86
+ puts "Done!"
87
+ end
88
+
89
+ private
90
+
91
+ # Prints the given message on stderr and exits.
92
+ def error(msg)
93
+ raise RuntimeError.new(msg)
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra::Deployers
4
+
5
+ # A deployer that deploys a site using rsync.
6
+ #
7
+ # The configuration has should include a `:dst` value, a string containing
8
+ # the destination to where rsync should upload its data. It will likely be
9
+ # in `host:path` format. It should not end with a slash. For example,
10
+ # `"example.com:/var/www/sites/mysite/html"`.
11
+ #
12
+ # @example A deployment configuration with public and staging configurations
13
+ #
14
+ # deploy:
15
+ # public:
16
+ # kind: rsync
17
+ # dst: "ectype:sites/stoneship/public"
18
+ # staging:
19
+ # kind: rsync
20
+ # dst: "ectype:sites/stoneship-staging/public"
21
+ # options: [ "-glpPrtvz" ]
22
+ class Rsync < ::Nanoc::Extra::Deployer
23
+
24
+ # Default rsync options
25
+ DEFAULT_OPTIONS = [
26
+ '-glpPrtvz',
27
+ '--exclude=".hg"',
28
+ '--exclude=".svn"',
29
+ '--exclude=".git"'
30
+ ]
31
+
32
+ # @see Nanoc::Extra::Deployer#run
33
+ def run
34
+ require 'systemu'
35
+
36
+ # Get params
37
+ src = File.expand_path(self.source_path) + '/'
38
+ dst = self.config[:dst]
39
+ options = self.config[:options] || DEFAULT_OPTIONS
40
+
41
+ # Validate
42
+ error 'No dst found in deployment configuration' if dst.nil?
43
+ error 'dst requires no trailing slash' if dst[-1,1] == '/'
44
+
45
+ # Run
46
+ if dry_run
47
+ warn 'Performing a dry-run; no actions will actually be performed'
48
+ run_shell_cmd([ 'echo', 'rsync', options, src, dst ].flatten)
49
+ else
50
+ run_shell_cmd([ 'rsync', options, src, dst ].flatten)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Prints the given message on stderr and exits.
57
+ def error(msg)
58
+ raise RuntimeError.new(msg)
59
+ end
60
+
61
+ # Runs the given shell command. It will raise an error if execution fails
62
+ # (results in a nonzero exit code).
63
+ def run_shell_cmd(args)
64
+ status = systemu(args, 'stdout' => $stdout, 'stderr' => $stderr)
65
+ raise "command exited with a nonzero status code #{$?.exitstatus} (command: #{args.join(' ')})" if !status.success?
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ # @deprecated Create a File instance directly and use that instead.
6
+ class FileProxy
7
+
8
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ || m.to_s == 'object_id' }
9
+
10
+ @@deprecation_warning_shown = false
11
+
12
+ def initialize(path)
13
+ @path = path
14
+ end
15
+
16
+ def freeze
17
+ end
18
+
19
+ def respond_to?(meth)
20
+ file_instance_methods.include?(meth.to_sym)
21
+ end
22
+
23
+ def method_missing(sym, *args, &block)
24
+ if !@@deprecation_warning_shown
25
+ $stderr.puts 'WARNING: The :file attribute is deprecated and will be removed in a future version of nanoc. Instead of using this :file attribute, consider manually creating a File object when it’s needed, using the :content_filename, :meta_filename or :filename attributes.'
26
+ @@deprecation_warning_shown = true
27
+ end
28
+
29
+ File.open(@path, 'r') { |io| io.__send__(sym, *args, &block) }
30
+ end
31
+
32
+ private
33
+
34
+ def file_instance_methods
35
+ @@file_instance_methods ||= Set.new(File.instance_methods.map { |m| m.to_sym })
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Extra
4
+
5
+ # Responsible for finding and deleting files in the site’s output directory
6
+ # that are not managed by nanoc.
7
+ class Pruner
8
+
9
+ # @return [Nanoc::Site] The site this pruner belongs to
10
+ attr_reader :site
11
+
12
+ # @param [Nanoc::Site] The site for which a pruner is created
13
+ #
14
+ # @option params [Boolean] :dry_run (false) true if the files to be deleted
15
+ # should only be printed instead of actually deleted, false if the files
16
+ # should actually be deleted.
17
+ def initialize(site, params={})
18
+ @site = site
19
+ @dry_run = params.fetch(:dry_run) { false }
20
+ @exclude = params.fetch(:exclude) { [] }
21
+ end
22
+
23
+ # Prunes all output files not managed by nanoc.
24
+ #
25
+ # @return [void]
26
+ def run
27
+ require 'find'
28
+
29
+ # Get compiled files
30
+ compiled_files = self.site.items.map do |item|
31
+ item.reps.map do |rep|
32
+ rep.raw_path
33
+ end
34
+ end.flatten.compact.select { |f| File.file?(f) }
35
+
36
+ # Get present files and dirs
37
+ present_files_and_dirs = Set.new
38
+ Find.find(self.site.config[:output_dir]) do |f|
39
+ present_files_and_dirs << f
40
+ end
41
+ present_files = present_files_and_dirs.select { |f| File.file?(f) }
42
+ present_dirs = present_files_and_dirs.select { |f| File.directory?(f) }
43
+
44
+ # Remove stray files
45
+ stray_files = (present_files - compiled_files)
46
+ stray_files.each do |f|
47
+ next if filename_excluded?(f)
48
+ self.delete_file(f)
49
+ end
50
+
51
+ # Remove empty directories
52
+ present_dirs.sort_by{ |d| -d.length }.each do |dir|
53
+ next if Dir.foreach(dir) { |n| break true if n !~ /\A\.\.?\z/ }
54
+ next if filename_excluded?(dir)
55
+ self.delete_dir(dir)
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ def filename_excluded?(f)
62
+ pathname = Pathname.new(f)
63
+ @exclude.any? { |e| pathname.include_component?(e) }
64
+ end
65
+
66
+ def delete_file(file)
67
+ if @dry_run
68
+ puts file
69
+ else
70
+ Nanoc::CLI::Logger.instance.file(:high, :delete, file)
71
+ FileUtils.rm(file)
72
+ end
73
+ end
74
+
75
+ def delete_dir(dir)
76
+ if @dry_run
77
+ puts dir
78
+ else
79
+ Nanoc::CLI::Logger.instance.file(:high, :delete, dir)
80
+ Dir.rmdir(dir)
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ end