webgen 0.5.5 → 0.5.6
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.
- data/ChangeLog +3662 -0
- data/Rakefile +8 -1
- data/VERSION +1 -1
- data/data/webgen/website_styles/1024px/src/default.template +1 -1
- data/data/webgen/website_styles/andreas00/src/default.template +1 -1
- data/data/webgen/website_styles/andreas01/src/default.template +2 -1
- data/data/webgen/website_styles/andreas03/src/default.template +1 -1
- data/data/webgen/website_styles/andreas04/src/default.template +1 -1
- data/data/webgen/website_styles/andreas05/src/default.template +1 -1
- data/data/webgen/website_styles/andreas06/src/default.template +1 -1
- data/data/webgen/website_styles/andreas07/src/default.template +1 -1
- data/data/webgen/website_styles/andreas08/src/default.template +1 -1
- data/data/webgen/website_styles/andreas09/src/default.template +1 -1
- data/data/webgen/website_styles/simple/src/default.template +1 -1
- data/doc/contentprocessor/fragments.page +25 -0
- data/doc/extensions.page +1 -1
- data/doc/manual.page +33 -15
- data/doc/reference_configuration.page +339 -62
- data/doc/reference_metainfo.page +11 -2
- data/doc/sourcehandler/feed.page +19 -4
- data/doc/sourcehandler/page.page +0 -16
- data/doc/tag/langbar.page +8 -1
- data/doc/tag/link.page +44 -0
- data/doc/tag/tikz.page +158 -0
- data/lib/webgen/cli.rb +4 -4
- data/lib/webgen/common/sitemap.rb +2 -3
- data/lib/webgen/configuration.rb +3 -1
- data/lib/webgen/contentprocessor.rb +1 -0
- data/lib/webgen/contentprocessor/blocks.rb +0 -2
- data/lib/webgen/contentprocessor/context.rb +0 -3
- data/lib/webgen/contentprocessor/erubis.rb +0 -2
- data/lib/webgen/contentprocessor/fragments.rb +23 -0
- data/lib/webgen/default_config.rb +15 -2
- data/lib/webgen/languages.rb +9 -0
- data/lib/webgen/logger.rb +18 -1
- data/lib/webgen/node.rb +50 -25
- data/lib/webgen/page.rb +26 -16
- data/lib/webgen/path.rb +20 -10
- data/lib/webgen/sourcehandler.rb +85 -69
- data/lib/webgen/sourcehandler/base.rb +38 -15
- data/lib/webgen/sourcehandler/copy.rb +2 -2
- data/lib/webgen/sourcehandler/directory.rb +16 -13
- data/lib/webgen/sourcehandler/feed.rb +6 -12
- data/lib/webgen/sourcehandler/fragment.rb +6 -11
- data/lib/webgen/sourcehandler/memory.rb +41 -0
- data/lib/webgen/sourcehandler/metainfo.rb +21 -21
- data/lib/webgen/sourcehandler/page.rb +7 -27
- data/lib/webgen/sourcehandler/sitemap.rb +0 -2
- data/lib/webgen/sourcehandler/template.rb +0 -4
- data/lib/webgen/sourcehandler/virtual.rb +18 -18
- data/lib/webgen/tag.rb +2 -0
- data/lib/webgen/tag/breadcrumbtrail.rb +1 -4
- data/lib/webgen/tag/coderay.rb +0 -3
- data/lib/webgen/tag/date.rb +0 -2
- data/lib/webgen/tag/executecommand.rb +1 -2
- data/lib/webgen/tag/includefile.rb +1 -3
- data/lib/webgen/tag/langbar.rb +2 -5
- data/lib/webgen/tag/link.rb +23 -0
- data/lib/webgen/tag/menu.rb +1 -4
- data/lib/webgen/tag/metainfo.rb +0 -2
- data/lib/webgen/tag/relocatable.rb +2 -3
- data/lib/webgen/tag/sitemap.rb +0 -3
- data/lib/webgen/tag/tikz.rb +117 -0
- data/lib/webgen/tree.rb +11 -6
- data/lib/webgen/version.rb +1 -1
- data/lib/webgen/website.rb +2 -1
- data/test/test_cli.rb +14 -0
- data/test/test_common_sitemap.rb +4 -4
- data/test/test_contentprocessor_context.rb +1 -1
- data/test/test_contentprocessor_fragments.rb +40 -0
- data/test/test_contentprocessor_redcloth.rb +1 -0
- data/test/test_contentprocessor_tags.rb +1 -1
- data/test/test_languages.rb +12 -0
- data/test/test_logger.rb +19 -0
- data/test/test_node.rb +35 -15
- data/test/test_output_filesystem.rb +1 -1
- data/test/test_page.rb +15 -6
- data/test/test_path.rb +37 -5
- data/test/test_source_filesystem.rb +1 -1
- data/test/test_source_stacked.rb +1 -1
- data/test/test_sourcehandler_base.rb +30 -1
- data/test/test_sourcehandler_copy.rb +1 -1
- data/test/test_sourcehandler_directory.rb +16 -1
- data/test/test_sourcehandler_feed.rb +9 -8
- data/test/test_sourcehandler_fragment.rb +1 -1
- data/test/test_sourcehandler_memory.rb +42 -0
- data/test/test_sourcehandler_metainfo.rb +23 -21
- data/test/test_sourcehandler_page.rb +5 -12
- data/test/test_sourcehandler_template.rb +1 -1
- data/test/test_sourcehandler_virtual.rb +2 -2
- data/test/test_tag_base.rb +0 -1
- data/test/test_tag_breadcrumbtrail.rb +4 -4
- data/test/test_tag_includefile.rb +3 -3
- data/test/test_tag_langbar.rb +12 -7
- data/test/test_tag_link.rb +61 -0
- data/test/test_tag_menu.rb +7 -7
- data/test/test_tag_metainfo.rb +1 -1
- data/test/test_tag_relocatable.rb +1 -1
- data/test/test_tag_tikz.rb +66 -0
- data/test/test_tree.rb +8 -9
- metadata +15 -2
data/lib/webgen/languages.rb
CHANGED
|
@@ -50,6 +50,15 @@ module Webgen
|
|
|
50
50
|
self.to_s <=> other.to_s
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
def eql?(other) #:nodoc:
|
|
54
|
+
(other.is_a?(self.class) && other.to_s == self.to_s) ||
|
|
55
|
+
(other.is_a?(String) && self.to_s == other)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def hash #:nodoc:
|
|
59
|
+
self.to_s.hash
|
|
60
|
+
end
|
|
61
|
+
|
|
53
62
|
end
|
|
54
63
|
|
|
55
64
|
|
data/lib/webgen/logger.rb
CHANGED
|
@@ -27,11 +27,28 @@ module Webgen
|
|
|
27
27
|
end
|
|
28
28
|
self.level = ::Logger::WARN
|
|
29
29
|
self.verbosity = :normal
|
|
30
|
+
@marks = []
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
# Returns the output of the logger when #sync is +false+. Otherwise an empty string is returned.
|
|
33
34
|
def log_output
|
|
34
|
-
@sync
|
|
35
|
+
if @sync
|
|
36
|
+
''
|
|
37
|
+
else
|
|
38
|
+
out = @logio.string.dup
|
|
39
|
+
@marks.reverse.each_with_index do |mark, index|
|
|
40
|
+
out.insert(mark, " INFO -- Log messages for run #{@marks.length - index} are following\n")
|
|
41
|
+
end if out.length > 0
|
|
42
|
+
out
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Only used when #sync is +false: Mark the location in the log stream where a new update/write
|
|
47
|
+
# run begins.
|
|
48
|
+
def mark_new_cycle
|
|
49
|
+
if !@sync
|
|
50
|
+
@marks << @logio.string.length
|
|
51
|
+
end
|
|
35
52
|
end
|
|
36
53
|
|
|
37
54
|
# The severity threshold level.
|
data/lib/webgen/node.rb
CHANGED
|
@@ -46,17 +46,6 @@ module Webgen
|
|
|
46
46
|
# Meta information associated with the node.
|
|
47
47
|
attr_reader :meta_info
|
|
48
48
|
|
|
49
|
-
# Set by other objects to +true+ if they think the object has changed since the last run. Must
|
|
50
|
-
# not be set to +false+ once it is +true+!
|
|
51
|
-
attr_accessor :dirty
|
|
52
|
-
|
|
53
|
-
# Set by other objects to +true+ if the meta information of the node has changed since the last
|
|
54
|
-
# run. Must not be set to +false+ once it is +true+!
|
|
55
|
-
attr_accessor :dirty_meta_info
|
|
56
|
-
|
|
57
|
-
# Has the node been created or has it been read from the cache?
|
|
58
|
-
attr_accessor :created
|
|
59
|
-
|
|
60
49
|
# Create a new Node instance.
|
|
61
50
|
#
|
|
62
51
|
# +parent+ (immutable)::
|
|
@@ -78,17 +67,29 @@ module Webgen
|
|
|
78
67
|
# found, the node is language neutral.
|
|
79
68
|
def initialize(parent, path, cn, meta_info = {})
|
|
80
69
|
@parent = parent
|
|
81
|
-
@path = path.freeze
|
|
82
70
|
@cn = cn.chomp('/').freeze
|
|
83
|
-
@lang = meta_info.delete('lang').freeze
|
|
84
|
-
@lang = nil unless is_file?
|
|
85
|
-
@meta_info = meta_info
|
|
86
71
|
@children = []
|
|
87
|
-
|
|
88
|
-
@created = true
|
|
72
|
+
reinit(path, meta_info)
|
|
89
73
|
init_rest
|
|
90
74
|
end
|
|
91
75
|
|
|
76
|
+
# Re-initializes an already initialized node and resets it to its pristine state.
|
|
77
|
+
def reinit(path, meta_info = {})
|
|
78
|
+
old_path = @path
|
|
79
|
+
@path = path.freeze
|
|
80
|
+
@lang = Webgen::LanguageManager.language_for_code(meta_info.delete('lang'))
|
|
81
|
+
@lang = nil unless is_file?
|
|
82
|
+
@meta_info = meta_info
|
|
83
|
+
@flags = Set.new([:dirty, :created])
|
|
84
|
+
if @tree
|
|
85
|
+
@tree.node_access[:path].delete(old_path) if old_path
|
|
86
|
+
@tree.register_path(self)
|
|
87
|
+
self.node_info.clear
|
|
88
|
+
self.node_info[:used_nodes] = Set.new
|
|
89
|
+
self.node_info[:used_meta_info_nodes] = Set.new
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
92
93
|
# Return the meta information item for +key+.
|
|
93
94
|
def [](key)
|
|
94
95
|
@meta_info[key]
|
|
@@ -116,26 +117,50 @@ module Webgen
|
|
|
116
117
|
# Check if the node is the root node.
|
|
117
118
|
def is_root?; self == tree.root; end
|
|
118
119
|
|
|
120
|
+
# Check if the node is flagged with one of the following:
|
|
121
|
+
#
|
|
122
|
+
# :created:: Has the node been created or has it been read from the cache?
|
|
123
|
+
# :reinit:: Does the node need to be reinitialized?
|
|
124
|
+
# :dirty:: Set by other objects to +true+ if they think the object has changed since the last
|
|
125
|
+
# run. Must not be set to +false+ once it is +true+!
|
|
126
|
+
# :dirty_meta_info:: Set by other objects to +true+ if the meta information of the node has
|
|
127
|
+
# changed since the last run. Must not be set to +false+ once it is +true+!
|
|
128
|
+
def flagged(key)
|
|
129
|
+
@flags.include?(key)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Flag the node with the +keys+. See #flagged for valid keys.
|
|
133
|
+
def flag(*keys)
|
|
134
|
+
@flags += keys
|
|
135
|
+
website.blackboard.dispatch_msg(:node_flagged, self, keys)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Remove the flags +keys+ from the node.
|
|
139
|
+
def unflag(*keys)
|
|
140
|
+
@flags.subtract(keys)
|
|
141
|
+
website.blackboard.dispatch_msg(:node_unflagged, self, keys)
|
|
142
|
+
end
|
|
143
|
+
|
|
119
144
|
# Return +true+ if the node has changed since the last webgen run. If it has changed, +dirty+ is
|
|
120
145
|
# set to +true+.
|
|
121
146
|
def changed?
|
|
122
147
|
if_not_checked(:node) do
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
website.blackboard.dispatch_msg(:node_changed?, self) unless
|
|
148
|
+
flag(:dirty) if meta_info_changed? ||
|
|
149
|
+
node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)}
|
|
150
|
+
website.blackboard.dispatch_msg(:node_changed?, self) unless flagged(:dirty)
|
|
126
151
|
end
|
|
127
|
-
|
|
152
|
+
flagged(:dirty)
|
|
128
153
|
end
|
|
129
154
|
|
|
130
155
|
# Return +true+ if the meta information of the node has changed.
|
|
131
156
|
def meta_info_changed?
|
|
132
157
|
if_not_checked(:meta_info) do
|
|
133
|
-
|
|
158
|
+
flag(:dirty_meta_info) if node_info[:used_meta_info_nodes].any? do |n|
|
|
134
159
|
n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)
|
|
135
|
-
end
|
|
136
|
-
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless
|
|
160
|
+
end
|
|
161
|
+
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged(:dirty_meta_info)
|
|
137
162
|
end
|
|
138
|
-
|
|
163
|
+
flagged(:dirty_meta_info)
|
|
139
164
|
end
|
|
140
165
|
|
|
141
166
|
# Return an informative representation of the node.
|
data/lib/webgen/page.rb
CHANGED
|
@@ -55,14 +55,17 @@ module Webgen
|
|
|
55
55
|
# the information. The +meta_info+ parameter can be used to provide default meta information.
|
|
56
56
|
def from_data(data, meta_info = {})
|
|
57
57
|
md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
|
|
58
|
-
|
|
59
|
-
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
|
60
|
-
end
|
|
61
|
-
meta_info = meta_info.merge(md[1].nil? ? {} : parse_meta_info(md[1]))
|
|
58
|
+
meta_info = meta_info.merge(parse_meta_info(md[1], data))
|
|
62
59
|
blocks = parse_blocks(md[2] || '', meta_info)
|
|
63
60
|
new(meta_info, blocks)
|
|
64
61
|
end
|
|
65
62
|
|
|
63
|
+
# Parse the given string +data+ in Webgen Page Format and return the found meta information.
|
|
64
|
+
def meta_info_from_data(data)
|
|
65
|
+
md = /(#{RE_META_INFO})?/m.match(normalize_eol(data))
|
|
66
|
+
parse_meta_info(md[1], data)
|
|
67
|
+
end
|
|
68
|
+
|
|
66
69
|
#######
|
|
67
70
|
private
|
|
68
71
|
#######
|
|
@@ -72,17 +75,24 @@ module Webgen
|
|
|
72
75
|
data.gsub(/\r\n?/, "\n")
|
|
73
76
|
end
|
|
74
77
|
|
|
75
|
-
# Parse the meta info string +
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
# Parse the meta info string in +mi_data+ and return the hash with the meta information. The
|
|
79
|
+
# original +data+ is used for checking the validness of the meta information block.
|
|
80
|
+
def parse_meta_info(mi_data, data)
|
|
81
|
+
if mi_data.nil? && data =~ RE_META_INFO_START
|
|
82
|
+
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
|
83
|
+
elsif mi_data.nil?
|
|
84
|
+
{}
|
|
85
|
+
else
|
|
86
|
+
begin
|
|
87
|
+
meta_info = YAML::load(mi_data.to_s)
|
|
88
|
+
unless meta_info.kind_of?(Hash)
|
|
89
|
+
raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
|
90
|
+
end
|
|
91
|
+
rescue ArgumentError => e
|
|
92
|
+
raise WebgenPageFormatError, e.message
|
|
81
93
|
end
|
|
82
|
-
|
|
83
|
-
raise WebgenPageFormatError, e.message
|
|
94
|
+
meta_info
|
|
84
95
|
end
|
|
85
|
-
meta_info
|
|
86
96
|
end
|
|
87
97
|
|
|
88
98
|
# Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
|
|
@@ -96,7 +106,7 @@ module Webgen
|
|
|
96
106
|
options, content = *block_data
|
|
97
107
|
md = RE_BLOCKS_OPTIONS.match(options.to_s)
|
|
98
108
|
raise(WebgenPageFormatError, "Found invalid blocks starting line for block #{index+1}: #{options}") if content =~ /\A---/ || md.nil?
|
|
99
|
-
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, YAML::load(v)]}.flatten]
|
|
109
|
+
options = Hash[*md[1].to_s.scan(/(\w+):([^\s]*)/).map {|k,v| [k, (v == '' ? nil : YAML::load(v))]}.flatten]
|
|
100
110
|
options = (meta_info['blocks']['default'] || {} rescue {}).
|
|
101
111
|
merge((meta_info['blocks'][index+1] || {} rescue {})).
|
|
102
112
|
merge(options)
|
|
@@ -118,12 +128,12 @@ module Webgen
|
|
|
118
128
|
# The contents of the meta information block.
|
|
119
129
|
attr_reader :meta_info
|
|
120
130
|
|
|
121
|
-
# The
|
|
131
|
+
# The hash of blocks for the page.
|
|
122
132
|
attr_reader :blocks
|
|
123
133
|
|
|
124
134
|
# Create a new Page object with the meta information provided in +meta_info+ and the given
|
|
125
135
|
# +blocks+.
|
|
126
|
-
def initialize(meta_info = {}, blocks =
|
|
136
|
+
def initialize(meta_info = {}, blocks = {})
|
|
127
137
|
@meta_info = meta_info
|
|
128
138
|
@blocks = blocks
|
|
129
139
|
end
|
data/lib/webgen/path.rb
CHANGED
|
@@ -35,11 +35,24 @@ module Webgen
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
# Return +true+ if the given +path+ matches the given +pattern+ (trailing slashes of directories
|
|
39
|
+
# are not respected). For information on which patterns are supported, have a look at the
|
|
40
|
+
# documentation of File.fnmatch.
|
|
41
|
+
def self.match(path, pattern)
|
|
42
|
+
path = path.to_s.chomp('/') unless path == '/'
|
|
43
|
+
pattern = pattern.to_s.chomp('/') unless pattern == '/'
|
|
44
|
+
File.fnmatch(pattern, path, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
38
48
|
include Comparable
|
|
39
49
|
|
|
40
|
-
# The full
|
|
50
|
+
# The full path.
|
|
41
51
|
attr_accessor :path
|
|
42
52
|
|
|
53
|
+
# The source path that lead to the creation of this path.
|
|
54
|
+
attr_accessor :source_path
|
|
55
|
+
|
|
43
56
|
# The basename part of the path.
|
|
44
57
|
attr_accessor :basename
|
|
45
58
|
|
|
@@ -55,11 +68,13 @@ module Webgen
|
|
|
55
68
|
# Extracted meta information for the path.
|
|
56
69
|
attr_accessor :meta_info
|
|
57
70
|
|
|
58
|
-
# Create a new Path object for +path+. The optional
|
|
59
|
-
#
|
|
60
|
-
|
|
71
|
+
# Create a new Path object for +path+. The optional +source_path+ parameter specifies the path
|
|
72
|
+
# that lead to the creation of this path. The optional block needs to return an IO object for
|
|
73
|
+
# the content of the path.
|
|
74
|
+
def initialize(path, source_path = path, &ioblock)
|
|
61
75
|
@meta_info = {}
|
|
62
76
|
@io = SourceIO.new(&ioblock) if block_given?
|
|
77
|
+
@source_path = source_path
|
|
63
78
|
analyse(path)
|
|
64
79
|
end
|
|
65
80
|
|
|
@@ -70,6 +85,7 @@ module Webgen
|
|
|
70
85
|
temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
|
|
71
86
|
reanalyse = (@path == '/' || temp.path == '/')
|
|
72
87
|
temp.path = File.join(mp, temp.path)
|
|
88
|
+
temp.source_path = temp.path if @path == @source_path
|
|
73
89
|
if reanalyse
|
|
74
90
|
temp.send(:analyse, temp.path)
|
|
75
91
|
else
|
|
@@ -131,12 +147,6 @@ module Webgen
|
|
|
131
147
|
end
|
|
132
148
|
alias_method(:eql?, :==)
|
|
133
149
|
|
|
134
|
-
# Return +true+ if the localized path matches the given +pattern+. For information on which
|
|
135
|
-
# patterns are supported, have a look at the documentation of File.fnmatch.
|
|
136
|
-
def =~(pattern)
|
|
137
|
-
File.fnmatch(pattern, File.join(@directory, lcn), File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
150
|
# Implemented sothat a Path looks like a String when used as key in a hash.
|
|
141
151
|
def <=>(other)
|
|
142
152
|
@path <=> other.to_str
|
data/lib/webgen/sourcehandler.rb
CHANGED
|
@@ -19,6 +19,7 @@ module Webgen
|
|
|
19
19
|
autoload :Virtual, 'webgen/sourcehandler/virtual'
|
|
20
20
|
autoload :Feed, 'webgen/sourcehandler/feed'
|
|
21
21
|
autoload :Sitemap, 'webgen/sourcehandler/sitemap'
|
|
22
|
+
autoload :Memory, 'webgen/sourcehandler/memory'
|
|
22
23
|
|
|
23
24
|
# This class is used by Website to do the actual rendering of the website. It
|
|
24
25
|
#
|
|
@@ -39,52 +40,90 @@ module Webgen
|
|
|
39
40
|
# Render the nodes provided in the +tree+. Before the actual rendering is done, the sources
|
|
40
41
|
# are checked (nodes for deleted sources are deleted, nodes for new and changed sources).
|
|
41
42
|
def render(tree)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
while paths.length > 0
|
|
48
|
-
used_paths += (paths = Set.new(find_all_source_paths.keys) - used_paths - clean(tree))
|
|
49
|
-
create_nodes_from_paths(tree, paths)
|
|
43
|
+
begin
|
|
44
|
+
website.logger.mark_new_cycle if website.logger
|
|
45
|
+
|
|
46
|
+
puts "Updating tree..."
|
|
47
|
+
time = Benchmark.measure do
|
|
50
48
|
website.cache.reset_volatile_cache
|
|
49
|
+
update_tree(tree)
|
|
51
50
|
end
|
|
52
|
-
|
|
53
|
-
puts "...done in " + ('%2.4f' % time.real) + ' seconds'
|
|
54
|
-
|
|
55
|
-
output = website.blackboard.invoke(:output_instance)
|
|
51
|
+
puts "...done in " + ('%2.4f' % time.real) + ' seconds'
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
node.dirty_meta_info = node.created = false
|
|
61
|
-
next if node == tree.dummy_root || !node.dirty
|
|
62
|
-
node.dirty = false
|
|
63
|
-
|
|
64
|
-
begin
|
|
65
|
-
if !node['no_output'] && (content = node.content)
|
|
66
|
-
puts " "*4 + name, :verbose
|
|
67
|
-
type = if node.is_directory?
|
|
68
|
-
:directory
|
|
69
|
-
elsif node.is_fragment?
|
|
70
|
-
:fragment
|
|
71
|
-
else
|
|
72
|
-
:file
|
|
73
|
-
end
|
|
74
|
-
output.write(node.path, content, type)
|
|
75
|
-
end
|
|
76
|
-
rescue
|
|
77
|
-
raise RuntimeError, "Error while processing <#{node.absolute_lcn}>: #{$!.message}", $!.backtrace
|
|
78
|
-
end
|
|
53
|
+
puts "Writing changed nodes..."
|
|
54
|
+
time = Benchmark.measure do
|
|
55
|
+
write_tree(tree)
|
|
79
56
|
end
|
|
80
|
-
|
|
81
|
-
|
|
57
|
+
puts "...done in " + ('%2.4f' % time.real) + ' seconds'
|
|
58
|
+
end while tree.node_access[:alcn].any? {|name,node| node.flagged(:created) || node.flagged(:reinit)}
|
|
82
59
|
end
|
|
83
60
|
|
|
84
61
|
#######
|
|
85
62
|
private
|
|
86
63
|
#######
|
|
87
64
|
|
|
65
|
+
# Update the +tree+ by creating/reinitializing all needed nodes.
|
|
66
|
+
def update_tree(tree)
|
|
67
|
+
unused_paths = Set.new
|
|
68
|
+
begin
|
|
69
|
+
used_paths = Set.new(find_all_source_paths.keys) - unused_paths
|
|
70
|
+
paths_to_use = Set.new
|
|
71
|
+
nodes_to_delete = Set.new
|
|
72
|
+
|
|
73
|
+
tree.node_access[:alcn].each do |alcn, node|
|
|
74
|
+
next if node == tree.dummy_root
|
|
75
|
+
used_paths.delete(node.node_info[:src])
|
|
76
|
+
|
|
77
|
+
deleted = !find_all_source_paths.include?(node.node_info[:src])
|
|
78
|
+
if deleted
|
|
79
|
+
nodes_to_delete << node
|
|
80
|
+
#TODO: delete output path
|
|
81
|
+
elsif (!node.flagged(:created) && find_all_source_paths[node.node_info[:src]].changed?) || node.meta_info_changed?
|
|
82
|
+
node.flag(:reinit)
|
|
83
|
+
paths_to_use << node.node_info[:src]
|
|
84
|
+
elsif node.changed?
|
|
85
|
+
# nothing to be done here
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
nodes_to_delete.each {|node| tree.delete_node(node)}
|
|
90
|
+
used_paths.merge(paths_to_use)
|
|
91
|
+
paths = create_nodes_from_paths(tree, used_paths.to_a.sort)
|
|
92
|
+
unused_paths.merge(used_paths - paths)
|
|
93
|
+
tree.node_access[:alcn].each {|name, node| tree.delete_node(node) if node.flagged(:reinit)}
|
|
94
|
+
website.cache.reset_volatile_cache
|
|
95
|
+
end until used_paths.empty?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Write out all changed nodes of the +tree+.
|
|
99
|
+
def write_tree(tree)
|
|
100
|
+
output = website.blackboard.invoke(:output_instance)
|
|
101
|
+
|
|
102
|
+
tree.node_access[:alcn].select do |name, node|
|
|
103
|
+
use_node = (node != tree.dummy_root && node.flagged(:dirty))
|
|
104
|
+
node.unflag(:dirty_meta_info)
|
|
105
|
+
node.unflag(:created)
|
|
106
|
+
node.unflag(:dirty)
|
|
107
|
+
use_node
|
|
108
|
+
end.sort.each do |name, node|
|
|
109
|
+
next if node['no_output'] || !(content = node.content)
|
|
110
|
+
|
|
111
|
+
begin
|
|
112
|
+
puts " "*4 + name, :verbose
|
|
113
|
+
type = if node.is_directory?
|
|
114
|
+
:directory
|
|
115
|
+
elsif node.is_fragment?
|
|
116
|
+
:fragment
|
|
117
|
+
else
|
|
118
|
+
:file
|
|
119
|
+
end
|
|
120
|
+
output.write(node.path, content, type)
|
|
121
|
+
rescue
|
|
122
|
+
raise RuntimeError, "Error while processing <#{node.absolute_lcn}>: #{$!.message}", $!.backtrace
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
88
127
|
# Return a hash with all source paths.
|
|
89
128
|
def find_all_source_paths
|
|
90
129
|
if !defined?(@paths)
|
|
@@ -94,7 +133,7 @@ module Webgen
|
|
|
94
133
|
@paths = {}
|
|
95
134
|
source.paths.each do |path|
|
|
96
135
|
if !(website.config['sourcehandler.ignore'].any? {|pat| File.fnmatch(pat, path, File::FNM_CASEFOLD|File::FNM_DOTMATCH)})
|
|
97
|
-
@paths[path.
|
|
136
|
+
@paths[path.source_path] = path
|
|
98
137
|
end
|
|
99
138
|
end
|
|
100
139
|
end
|
|
@@ -115,16 +154,20 @@ module Webgen
|
|
|
115
154
|
|
|
116
155
|
# Use the source handlers to create nodes for the +paths+ in the +tree+.
|
|
117
156
|
def create_nodes_from_paths(tree, paths)
|
|
157
|
+
used_paths = Set.new
|
|
118
158
|
website.config['sourcehandler.invoke'].sort.each do |priority, shns|
|
|
119
159
|
shns.each do |shn|
|
|
120
160
|
sh = website.cache.instance(shn)
|
|
121
|
-
paths_for_handler(shn, paths)
|
|
161
|
+
handler_paths = paths_for_handler(shn, paths)
|
|
162
|
+
used_paths.merge(handler_paths)
|
|
163
|
+
handler_paths.sort {|a,b| a.path.length <=> b.path.length}.each do |path|
|
|
122
164
|
parent_dir = path.directory.split('/').collect {|p| Path.new(p).cn}.join('/')
|
|
123
165
|
parent_dir += '/' if path != '/' && parent_dir == ''
|
|
124
166
|
create_nodes(tree, parent_dir, path, sh)
|
|
125
167
|
end
|
|
126
168
|
end
|
|
127
169
|
end
|
|
170
|
+
used_paths
|
|
128
171
|
end
|
|
129
172
|
|
|
130
173
|
# Prepare everything to create nodes under the absolute lcn path +parent_path_name+ in the
|
|
@@ -142,7 +185,7 @@ module Webgen
|
|
|
142
185
|
*nodes = if block_given?
|
|
143
186
|
yield(parent, path)
|
|
144
187
|
else
|
|
145
|
-
source_handler.create_node(parent, path
|
|
188
|
+
source_handler.create_node(parent, path)
|
|
146
189
|
end
|
|
147
190
|
nodes.flatten.compact.each do |node|
|
|
148
191
|
website.blackboard.dispatch_msg(:after_node_created, node)
|
|
@@ -160,39 +203,12 @@ module Webgen
|
|
|
160
203
|
# take the node's path's +modified_at+ meta information into account since that changes on
|
|
161
204
|
# every path change.
|
|
162
205
|
def meta_info_changed?(node)
|
|
163
|
-
path = node.node_info[:
|
|
206
|
+
path = node.node_info[:creation_path]
|
|
164
207
|
old_mi = website.cache[:sourcehandler_path_mi][[path, node.node_info[:processor]]]
|
|
165
208
|
old_mi.delete('modified_at')
|
|
166
|
-
new_mi = default_meta_info(@paths[path], node.node_info[:processor])
|
|
209
|
+
new_mi = default_meta_info(@paths[path] || Webgen::Path.new(path), node.node_info[:processor])
|
|
167
210
|
new_mi.delete('modified_at')
|
|
168
|
-
node.dirty_meta_info
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Clean the +tree+ by deleting nodes which have changed or which don't have an associated
|
|
172
|
-
# source anymore. Return all paths for which nodes need to be created.
|
|
173
|
-
def clean(tree)
|
|
174
|
-
paths_to_delete = Set.new
|
|
175
|
-
paths_not_to_delete = Set.new
|
|
176
|
-
nodes_to_be_deleted = Set.new
|
|
177
|
-
tree.node_access[:alcn].each do |alcn, node|
|
|
178
|
-
next if node == tree.dummy_root || tree[alcn].nil?
|
|
179
|
-
|
|
180
|
-
deleted = !find_all_source_paths.include?(node.node_info[:src])
|
|
181
|
-
if !node.created && (deleted ||
|
|
182
|
-
find_all_source_paths[node.node_info[:src]].changed? ||
|
|
183
|
-
node.changed?)
|
|
184
|
-
paths_not_to_delete << node.node_info[:src]
|
|
185
|
-
nodes_to_be_deleted << [node, deleted]
|
|
186
|
-
else
|
|
187
|
-
paths_to_delete << node.node_info[:src]
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
nodes_to_be_deleted.each {|node, deleted| tree.delete_node(node, deleted)}
|
|
192
|
-
#TODO: delete output path
|
|
193
|
-
|
|
194
|
-
# source paths that should be used
|
|
195
|
-
paths_to_delete - paths_not_to_delete
|
|
211
|
+
node.flag(:dirty_meta_info) if !old_mi || old_mi != new_mi
|
|
196
212
|
end
|
|
197
213
|
|
|
198
214
|
end
|