webgen 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|