nanoc 4.9.1 → 4.9.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ab127f94d9ffc710fc374831e36f805e16e1fd1bf1dcadfc65d48ce8009d4f8
4
- data.tar.gz: 4f167936c1d475ce4625875ec5788d99d1f0e22fb0499644e5c632d26bfe0ef1
3
+ metadata.gz: b913559b6a6971b80377035d086779ac7d799a7ffee38289778bec2e8a82cd7c
4
+ data.tar.gz: 28bb11a9f2146ace9c6a018a69bc11c766bfe29ee08fbce18923f4686bda8379
5
5
  SHA512:
6
- metadata.gz: 3ce94577815ee770cb5e572d232357a60fd4447ab68c101d0a6215e9b45c1f25866433ac90e478475dbccf92cbbf97d5a01c1b6a40198a715a6e5364f68f6064
7
- data.tar.gz: 38dec7119c8a3239ec8ab5a2922fe4aca8857645446100f6601bffebe75c6ff2414d0b0886bebc633b95f7df8c12ef25a6d59926e1101cc63917584ad13170de
6
+ metadata.gz: 9862f93c33f34a75792f371ff106bfe9119f61c0e052e648ef8caa66364e81adc91ec36d015b22f8f9faea4479839fe013edb388886785b7149089428bb57b69
7
+ data.tar.gz: 75f1f8f4039bc15ba041861696b80ededbf7fb67ed18f57b2c1b4e0cd65efef46a331e5ea6e659de37eb1e8c5f05dfea39a097a2d5f4d25a493410fd77e2ec3b
data/NEWS.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.9.2 (2018-03-30)
4
+
5
+ Fixes:
6
+
7
+ * Fixed bug which caused `output_dir` not to be ignored when checking for excludes in pruner (#1313, #1324)
8
+ * Fixed bug which caused `Filter#depend_on` not to create a proper dependency when the depended-on item has no representations (#1330)
9
+
10
+ Enhancements:
11
+
12
+ * Made Nanoc use hardlinks instead of copying files when possible (#1321) [Antonio Terceiro]
13
+ * Made Nanoc show an understandable error when a filter returns `nil` by accident (#1323, #1326)
14
+ * Made the checks also consider `.xhtml` and `.htm` files (#1328, #1329)
15
+ * Made Nanoc not report thread exceptions, which would freeze Ruby (#1332)
16
+
3
17
  ## 4.9.1 (2018-02-22)
4
18
 
5
19
  Fixes:
@@ -54,6 +54,7 @@ require 'stringio'
54
54
  require 'tempfile'
55
55
  require 'time'
56
56
  require 'timeout'
57
+ require 'tomlrb'
57
58
  require 'tmpdir'
58
59
  require 'uri'
59
60
  require 'yaml'
@@ -224,6 +224,18 @@ module Nanoc::Int
224
224
  end
225
225
  end
226
226
 
227
+ class OutputNotWritten < Generic
228
+ def initialize(filter_name, output_filename)
229
+ super("The #{filter_name.inspect} filter did not write anything to the required output file, #{output_filename}.")
230
+ end
231
+ end
232
+
233
+ class FilterReturnedNil < Generic
234
+ def initialize(filter_name)
235
+ super("The #{filter_name.inspect} filter returned nil, but is required to return a String.")
236
+ end
237
+ end
238
+
227
239
  class InternalInconsistency < Generic
228
240
  end
229
241
  end
@@ -91,4 +91,10 @@ module Nanoc
91
91
  end
92
92
  end
93
93
 
94
+ # Tracking issue:
95
+ # https://github.com/nanoc/features/issues/24
94
96
  Nanoc::Feature.define('live_cmd', version: '4.9')
97
+
98
+ # Tracking issue:
99
+ # https://github.com/nanoc/features/issues/40
100
+ Nanoc::Feature.define('toml', version: '4.9')
@@ -28,7 +28,12 @@ module Nanoc::Int
28
28
 
29
29
  # @return [String]
30
30
  def self.config_filename_for_cwd
31
- filenames = %w[nanoc.yaml config.yaml]
31
+ filenames =
32
+ if Nanoc::Feature.enabled?(Nanoc::Feature::TOML)
33
+ %w[nanoc.yaml config.yaml nanoc.toml]
34
+ else
35
+ %w[nanoc.yaml config.yaml]
36
+ end
32
37
  candidate = filenames.find { |f| File.file?(f) }
33
38
  candidate && File.expand_path(candidate)
34
39
  end
@@ -41,7 +46,7 @@ module Nanoc::Int
41
46
  # Read
42
47
  config =
43
48
  apply_parent_config(
44
- Nanoc::Int::Configuration.new(hash: YAML.load_file(filename)),
49
+ Nanoc::Int::Configuration.new(hash: load_file(filename)),
45
50
  [filename],
46
51
  ).with_defaults
47
52
 
@@ -49,6 +54,17 @@ module Nanoc::Int
49
54
  config.with_environment
50
55
  end
51
56
 
57
+ def load_file(filename)
58
+ case File.extname(filename)
59
+ when '.yaml'
60
+ YAML.load_file(filename)
61
+ when '.toml'
62
+ Tomlrb.load_file(filename)
63
+ else
64
+ raise Nanoc::Int::Errors::InternalInconsistency, 'Unhandled config file extension'
65
+ end
66
+ end
67
+
52
68
  # @api private
53
69
  def apply_parent_config(config, processed_paths = [])
54
70
  parent_path = config[:parent_config_file]
@@ -66,7 +82,7 @@ module Nanoc::Int
66
82
  end
67
83
 
68
84
  # Load
69
- parent_config = Nanoc::Int::Configuration.new(hash: YAML.load_file(parent_path))
85
+ parent_config = Nanoc::Int::Configuration.new(hash: load_file(parent_path))
70
86
  full_parent_config = apply_parent_config(parent_config, processed_paths + [parent_path])
71
87
  full_parent_config.merge(config.without(:parent_config_file))
72
88
  end
@@ -23,6 +23,8 @@ module Nanoc::Int
23
23
  def bounce(_obj, raw_content: false, attributes: false, compiled_content: false, path: false); end
24
24
  end
25
25
 
26
+ attr_reader :dependency_store
27
+
26
28
  def initialize(dependency_store)
27
29
  @dependency_store = dependency_store
28
30
  @stack = []
@@ -3,12 +3,6 @@
3
3
  module Nanoc
4
4
  module Int
5
5
  class Executor
6
- class OutputNotWrittenError < ::Nanoc::Error
7
- def initialize(filter_name, output_filename)
8
- super("The #{filter_name.inspect} filter did not write anything to the required output file, #{output_filename}.")
9
- end
10
- end
11
-
12
6
  def initialize(rep, compilation_context, dependency_tracker)
13
7
  @rep = rep
14
8
  @compilation_context = compilation_context
@@ -35,11 +29,6 @@ module Nanoc
35
29
 
36
30
  # Store
37
31
  @compilation_context.snapshot_repo.set(@rep, :last, last)
38
-
39
- # Check whether file was written
40
- if filter.class.to_binary? && !File.file?(filter.output_filename)
41
- raise OutputNotWrittenError.new(filter_name, filter.output_filename)
42
- end
43
32
  ensure
44
33
  Nanoc::Int::NotificationCenter.post(:filtering_ended, @rep, filter_name)
45
34
  end
@@ -87,6 +87,11 @@ module Nanoc
87
87
  (@to || :text) == :binary
88
88
  end
89
89
 
90
+ # @api private
91
+ def to_text?
92
+ (@to || :text) == :text
93
+ end
94
+
90
95
  # @return [Boolean]
91
96
  #
92
97
  # @api private
@@ -149,7 +154,7 @@ module Nanoc
149
154
  # @api private
150
155
  def setup_and_run(*args)
151
156
  self.class.setup
152
- run(*args)
157
+ run(*args).tap { |res| verify(res) }
153
158
  end
154
159
 
155
160
  # Runs the filter on the given content or filename.
@@ -170,6 +175,18 @@ module Nanoc
170
175
  raise NotImplementedError.new('Nanoc::Filter subclasses must implement #run')
171
176
  end
172
177
 
178
+ def verify(res)
179
+ if self.class.to_binary?
180
+ unless File.file?(output_filename)
181
+ raise Nanoc::Int::Errors::OutputNotWritten.new(self.class.identifier, output_filename)
182
+ end
183
+ elsif self.class.to_text?
184
+ unless res
185
+ raise Nanoc::Int::Errors::FilterReturnedNil.new(self.class.identifier)
186
+ end
187
+ end
188
+ end
189
+
173
190
  # Returns a filename that is used to write data to. This method is only
174
191
  # used on binary items. When running a binary filter on a file, the
175
192
  # resulting file must end up in the location returned by this method.
@@ -211,6 +228,7 @@ module Nanoc
211
228
  # @return [void]
212
229
  def depend_on(items)
213
230
  items.flat_map(&:reps).flat_map(&:raw_path)
231
+ items.each(&:raw_filename)
214
232
  end
215
233
  end
216
234
  end
@@ -48,7 +48,13 @@ module Nanoc::Int
48
48
  is_modified = is_created || !FileUtils.identical?(raw_path, temp_path)
49
49
 
50
50
  # Write
51
- FileUtils.cp(temp_path, raw_path) if is_modified
51
+ if is_modified
52
+ begin
53
+ FileUtils.ln(temp_path, raw_path, force: true)
54
+ rescue Errno::EXDEV
55
+ FileUtils.cp(temp_path, raw_path)
56
+ end
57
+ end
52
58
 
53
59
  item_rep.modified = is_modified
54
60
 
@@ -6,6 +6,8 @@ module Nanoc
6
6
  #
7
7
  # @api private
8
8
  class Pruner
9
+ include Nanoc::Int::ContractsSupport
10
+
9
11
  # @param [Nanoc::Int::Configuration] config
10
12
  #
11
13
  # @param [Nanoc::Int::ItemRepRepo] reps
@@ -22,9 +24,6 @@ module Nanoc
22
24
  @exclude = Set.new(exclude)
23
25
  end
24
26
 
25
- # Prunes all output files not managed by Nanoc.
26
- #
27
- # @return [void]
28
27
  def run
29
28
  return unless File.directory?(@config[:output_dir])
30
29
 
@@ -35,18 +34,13 @@ module Nanoc
35
34
  remove_empty_directories(present_dirs)
36
35
  end
37
36
 
38
- def exclude?(component)
39
- @exclude.include?(component)
40
- end
41
-
42
- # @param [String] filename The filename to check
43
- #
44
- # @return [Boolean] true if the given file is excluded, false otherwise
37
+ contract String => C::Bool
45
38
  def filename_excluded?(filename)
46
39
  pathname = Pathname.new(strip_output_dir(filename))
47
40
  @exclude.any? { |e| pathname_components(pathname).include?(e) }
48
41
  end
49
42
 
43
+ contract String => String
50
44
  def strip_output_dir(filename)
51
45
  if filename.start_with?(@config[:output_dir])
52
46
  filename[@config[:output_dir].size..-1]
@@ -55,6 +49,7 @@ module Nanoc
55
49
  end
56
50
  end
57
51
 
52
+ contract Pathname => C::ArrayOf[String]
58
53
  def pathname_components(pathname)
59
54
  components = []
60
55
  tmp = pathname
@@ -67,22 +62,27 @@ module Nanoc
67
62
  components.reverse
68
63
  end
69
64
 
65
+ contract C::ArrayOf[String], C::ArrayOf[String] => self
70
66
  # @api private
71
67
  def remove_stray_files(present_files, compiled_files)
72
68
  (present_files - compiled_files).each do |f|
73
- delete_file(f) unless exclude?(f)
69
+ delete_file(f) unless filename_excluded?(f)
74
70
  end
71
+ self
75
72
  end
76
73
 
74
+ contract C::ArrayOf[String] => self
77
75
  # @api private
78
76
  def remove_empty_directories(present_dirs)
79
77
  present_dirs.reverse_each do |dir|
80
78
  next if Dir.foreach(dir) { |n| break true if n !~ /\A\.\.?\z/ }
81
- next if exclude?(dir)
79
+ next if filename_excluded?(dir)
82
80
  delete_dir(dir)
83
81
  end
82
+ self
84
83
  end
85
84
 
85
+ contract String => C::ArrayOf[C::ArrayOf[String]]
86
86
  # @api private
87
87
  def files_and_dirs_in(dir)
88
88
  present_files = []
@@ -91,15 +91,13 @@ module Nanoc
91
91
  expanded_dir = File.expand_path(dir)
92
92
 
93
93
  Find.find(dir) do |f|
94
- basename = File.basename(f)
95
-
96
94
  case File.ftype(f)
97
95
  when 'file'
98
- unless exclude?(basename)
96
+ unless filename_excluded?(f)
99
97
  present_files << f
100
98
  end
101
99
  when 'directory'
102
- if exclude?(basename)
100
+ if filename_excluded?(f)
103
101
  Find.prune
104
102
  elsif expanded_dir != File.expand_path(f)
105
103
  present_dirs << f
@@ -45,6 +45,7 @@ module Nanoc
45
45
 
46
46
  # @api private
47
47
  def raw_filename
48
+ @context.dependency_tracker.bounce(_unwrap, raw_content: true)
48
49
  _unwrap.content.filename
49
50
  end
50
51
  end
@@ -58,5 +58,10 @@ module Nanoc::Checking
58
58
  def add_issue(desc, subject: nil)
59
59
  @issues << Issue.new(desc, subject, self.class)
60
60
  end
61
+
62
+ # @private
63
+ def output_html_filenames
64
+ output_filenames.select { |f| File.extname(f) =~ /\A\.x?html?\z/ }
65
+ end
61
66
  end
62
67
  end
@@ -10,7 +10,7 @@ module ::Nanoc::Checking::Checks
10
10
  def run
11
11
  # Find all broken external hrefs
12
12
  # TODO: de-duplicate this (duplicated in internal links check)
13
- filenames = output_filenames.select { |f| File.extname(f) == '.html' && !excluded_file?(f) }
13
+ filenames = output_html_filenames.reject { |f| excluded_file?(f) }
14
14
  hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :external).filenames_per_href
15
15
  results = select_invalid(hrefs_with_filenames.keys)
16
16
 
@@ -15,7 +15,7 @@ module Nanoc::Checking::Checks
15
15
  # @return [void]
16
16
  def run
17
17
  # TODO: de-duplicate this (duplicated in external links check)
18
- filenames = output_filenames.select { |f| File.extname(f) == '.html' }
18
+ filenames = output_html_filenames
19
19
  hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :internal).filenames_per_href
20
20
  resource_uris_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :internal).filenames_per_resource_uri
21
21
 
@@ -11,7 +11,7 @@ module Nanoc::Checking::Checks
11
11
  PROTOCOL_PATTERN = /^(\w+):\/\//
12
12
 
13
13
  def run
14
- filenames = output_filenames.select { |f| File.extname(f) == '.html' }
14
+ filenames = output_html_filenames
15
15
  resource_uris_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames).filenames_per_resource_uri
16
16
 
17
17
  resource_uris_with_filenames.each_pair do |uri, fns|
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nanoc::Deploying::Deployers
4
- # A deployer that deploys a site using [fog](https://github.com/geemus/fog).
4
+ # A deployer that deploys a site using [fog](https://github.com/fog/fog).
5
5
  #
6
6
  # @example A deployment configuration with public and staging configurations
7
7
  #
@@ -25,6 +25,12 @@ module Nanoc
25
25
  skip "Could not find external command \"#{cmd}\"" unless command?(cmd)
26
26
  end
27
27
 
28
+ def skip_unless_gem_available(gem)
29
+ require gem
30
+ rescue LoadError
31
+ skip "Could not load gem \"#{gem}\""
32
+ end
33
+
28
34
  def sleep_until(max: 3.0)
29
35
  start = Time.now
30
36
  loop do
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nanoc
4
4
  # The current Nanoc version.
5
- VERSION = '4.9.1'
5
+ VERSION = '4.9.2'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.9.1
4
+ version: 4.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-22 00:00:00.000000000 Z
11
+ date: 2018-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: tomlrb
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.2'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.2'
139
153
  description: Nanoc is a static-site generator focused on flexibility. It transforms
140
154
  content from a format such as Markdown or AsciiDoc into another format, usually
141
155
  HTML, and lays out pages consistently to retain the site’s look and feel throughout.