gf-treevisitor 0.0.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/LICENSE +20 -0
- data/README.rdoc +22 -0
- data/bin/dirtree.rb +13 -0
- data/lib/gf_utility/file_utilities.rb +70 -0
- data/lib/gf_utility/kwartzhelper.rb +82 -0
- data/lib/gf_utility/md5.rb +17 -0
- data/lib/gf_utility/numeric.rb +17 -0
- data/lib/treevisitor.rb +3 -0
- data/lib/treevisitor/abs_node.rb +116 -0
- data/lib/treevisitor/build_dir_tree_visitor.rb +58 -0
- data/lib/treevisitor/cli/cli_dir_tree.rb +84 -0
- data/lib/treevisitor/dir_processor.rb +40 -0
- data/lib/treevisitor/dir_tree_walker.rb +99 -0
- data/lib/treevisitor/leaf_node.rb +27 -0
- data/lib/treevisitor/tree_node.rb +134 -0
- data/lib/treevisitor/tree_node_visitor.rb +251 -0
- data/lib/treevisitor/visitor/print_node_visitor2.rb +35 -0
- data/test/gf_utility/tc_kwartz.rb +20 -0
- data/test/gf_utility/tc_md5.rb +14 -0
- data/test/gf_utility/tc_numeric.rb +13 -0
- data/test/gf_utility/test_helper.rb +5 -0
- data/test/treevisitor/tc_dir_processor.rb +10 -0
- data/test/treevisitor/tc_dir_tree_walker.rb +30 -0
- data/test/treevisitor/tc_tree_node.rb +129 -0
- data/test/treevisitor/tc_tree_node_visitor.rb +66 -0
- data/test/treevisitor/test_helper.rb +10 -0
- data/test/ts_treevisitor.rb +16 -0
- data/test_data/gf_utility/kwartz_test_data/source/test1.html +5 -0
- data/test_data/tree_visitor/test_data/dir.1/dir.1.2/file.1.2.1 +0 -0
- data/test_data/tree_visitor/test_data/dir.1/file.1.1 +0 -0
- data/test_data/tree_visitor/test_data/dir.2/file.2.1 +0 -0
- metadata +91 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 gf
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= dirtree.rb / tree visitor lib
|
2
|
+
|
3
|
+
<pre>dirtree.rb</pre> is a 'clone' of tree unix command.
|
4
|
+
It is based on lib tree visitor.
|
5
|
+
|
6
|
+
Tree visitor is an implementation of visitor design pattern.
|
7
|
+
|
8
|
+
== REQUIREMENTS:
|
9
|
+
|
10
|
+
* utilizza la libreria abstract di kwartz
|
11
|
+
|
12
|
+
== INSTALL:
|
13
|
+
|
14
|
+
sudo gem install tree_visitor
|
15
|
+
|
16
|
+
or
|
17
|
+
|
18
|
+
sudo gem install gf-tree_visitor -s gems.github.com
|
19
|
+
|
20
|
+
== Copyright
|
21
|
+
|
22
|
+
Copyright (c) 2009 gf. See LICENSE for details.
|
data/bin/dirtree.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Piccolo wrapper per richiamare il programma
|
4
|
+
# clidirtree
|
5
|
+
#
|
6
|
+
|
7
|
+
$TREEVISITOR_HOME = File.expand_path( File.join( File.dirname( __FILE__), ".." ) )
|
8
|
+
$:.unshift( File.join($TREEVISITOR_HOME, "lib" ) )
|
9
|
+
|
10
|
+
require "treevisitor/cli/cli_dir_tree"
|
11
|
+
|
12
|
+
CliDirTree.run
|
13
|
+
exit
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# stdlib
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
def recursive_run( dir, &block )
|
5
|
+
block.call( dir )
|
6
|
+
Dir.entries( dir ).each { |entry|
|
7
|
+
next if entry == "." or entry == ".."
|
8
|
+
next if not FileTest.directory?( dir + File::Separator + entry )
|
9
|
+
next if $config.ignore_dir( entry )
|
10
|
+
recursive_run( dir + File::Separator + entry, block )
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def copy_dir( indir, outdir, re )
|
15
|
+
if not File.directory?()
|
16
|
+
raise "#{indir} is not a directory"
|
17
|
+
end
|
18
|
+
if not File.directory?( outdir )
|
19
|
+
FileUtils.mkpath( outdir )
|
20
|
+
end
|
21
|
+
Dir.entries( indir ).each { |e|
|
22
|
+
if e.match( re )
|
23
|
+
from = File.join( indir, e )
|
24
|
+
to = File.join( outdir, e )
|
25
|
+
# puts "#{from} #{to}"
|
26
|
+
if File.exist?(to) and File.mtime(from) <= File.mtime(to)
|
27
|
+
next
|
28
|
+
end
|
29
|
+
FileUtils.cp from, to
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def copy_file( inpath, outdir )
|
35
|
+
from = inpath
|
36
|
+
to = File.join( outdir, File.basename( from ) )
|
37
|
+
# puts "#{from} #{to}"
|
38
|
+
if File.exist?(to) and File.mtime(from) <= File.mtime(to)
|
39
|
+
next
|
40
|
+
end
|
41
|
+
FileUtils.cp from, to
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# substitute into a file
|
46
|
+
#
|
47
|
+
def subfile( filename, map )
|
48
|
+
lines = IO.readlines( filename)
|
49
|
+
if $options.backup
|
50
|
+
FileUtils.mv( filename, filename + ".bck" )
|
51
|
+
end
|
52
|
+
|
53
|
+
lines.each_with_index { |l,i|
|
54
|
+
map.each { |l1, l2|
|
55
|
+
#puts "#{l} #{l1} #{l.index(l1)}"
|
56
|
+
if l.index( l1 ) == 0
|
57
|
+
puts "subst #{l1}"
|
58
|
+
lines[i] = l2
|
59
|
+
end
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
File.open( filename, "w" ) { |f|
|
64
|
+
lines.each{ |l| f.puts l }
|
65
|
+
}
|
66
|
+
puts "patched #{filename}"
|
67
|
+
|
68
|
+
rescue Errno::ENOENT => e
|
69
|
+
puts "file not found '#{filename}'"
|
70
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# ruby gems
|
2
|
+
#
|
3
|
+
# Check dependecies
|
4
|
+
require 'rubygems'
|
5
|
+
begin
|
6
|
+
require "kwartz"
|
7
|
+
require "kwartz/main"
|
8
|
+
rescue LoadError
|
9
|
+
abort 'kwartz gem required!!'
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# kwartz utility
|
14
|
+
# template_dir: directory containing kwartz template
|
15
|
+
# template_include_dir: nil or a directory contained kwarz template referenced by template
|
16
|
+
# template_out_dir: where the output goes
|
17
|
+
#
|
18
|
+
def kwartz_compile( template_dir, template_include_dir, template_out_dir )
|
19
|
+
if not File.directory?(template_dir)
|
20
|
+
raise "template_dir: '#{template_dir}' is not a directory"
|
21
|
+
end
|
22
|
+
|
23
|
+
if not File.directory?(template_out_dir)
|
24
|
+
raise "template_out_dir: '#{template_out_dir}' is not a directory"
|
25
|
+
end
|
26
|
+
|
27
|
+
re_templatefile = /^[^\.](.+).html$/
|
28
|
+
|
29
|
+
maxtime_incs = Time.local( 1980 )
|
30
|
+
incs = []
|
31
|
+
if template_include_dir
|
32
|
+
if not File.directory?( template_include_dir )
|
33
|
+
raise "include_dir: '#{template_include_dir}' is not a directory"
|
34
|
+
end
|
35
|
+
incs = Dir.new( template_include_dir ).find_all { |f| f =~ re_templatefile }
|
36
|
+
incs = incs.map{ |f| File.join(template_include_dir, f) }
|
37
|
+
maxtime_incs = incs.inject(maxtime_incs) {|t,f|
|
38
|
+
t1 = File.mtime( f )
|
39
|
+
if t1 > t then t1 else t end
|
40
|
+
}
|
41
|
+
incs = incs.join(",")
|
42
|
+
end
|
43
|
+
|
44
|
+
Dir.foreach( template_dir ) { |f|
|
45
|
+
next unless f =~ re_templatefile
|
46
|
+
|
47
|
+
inpath = File.join(template_dir, f)
|
48
|
+
inpath_time = File.mtime( inpath )
|
49
|
+
|
50
|
+
plogicpath = template_dir + File::Separator + f.sub( /.html$/, ".plogic" )
|
51
|
+
plogicpath_time = Time.local( 1980 )
|
52
|
+
if File.exists?( plogicpath )
|
53
|
+
plogicpath_time = File.mtime( plogicpath )
|
54
|
+
end
|
55
|
+
|
56
|
+
outpath = File.join( template_out_dir, f.sub( /.html$/, ".rb" ) )
|
57
|
+
outpath_time = Time.local( 1980 )
|
58
|
+
if File.exist?( outpath )
|
59
|
+
outpath_time = File.mtime( outpath )
|
60
|
+
end
|
61
|
+
|
62
|
+
argv = %w[--delspan -a defun -l ruby]
|
63
|
+
if incs.length > 0
|
64
|
+
argv << "-i"
|
65
|
+
argv.push( incs )
|
66
|
+
end
|
67
|
+
|
68
|
+
if File.exist?( plogicpath )
|
69
|
+
argv.push( "-p", plogicpath )
|
70
|
+
end
|
71
|
+
argv.push( inpath )
|
72
|
+
|
73
|
+
if outpath_time < maxtime_incs or
|
74
|
+
outpath_time < inpath_time or
|
75
|
+
outpath_time < plogicpath_time
|
76
|
+
# puts "kwartz " + argv.join(" ")
|
77
|
+
main = Kwartz::Main.new(argv)
|
78
|
+
output = main.execute()
|
79
|
+
File.open(outpath, 'w') { |f| f.write(output) }
|
80
|
+
end
|
81
|
+
}
|
82
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# stdlib
|
2
|
+
require 'md5'
|
3
|
+
|
4
|
+
#
|
5
|
+
# calcola md5 di file grandi, copiata da usenet
|
6
|
+
#
|
7
|
+
class MD5
|
8
|
+
def self.file(file)
|
9
|
+
File.open(file, "rb") do |f|
|
10
|
+
res = self.new
|
11
|
+
while (data = f.read(4096))
|
12
|
+
res << data
|
13
|
+
end
|
14
|
+
res
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Numeric
|
2
|
+
#
|
3
|
+
# ritorna una stringa con le migliaia serparate da <separator>
|
4
|
+
# es.: 100000 -> 1.000.000
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# copiata da http://wiki.rubygarden.org/Ruby/page/show/FixNumFormat
|
8
|
+
#
|
9
|
+
def with_separator( separator = ',', length = 3 )
|
10
|
+
splitter = Regexp.compile "(\\d{#{length}})"
|
11
|
+
before, after = self.to_s.split('.')
|
12
|
+
before = before.reverse.gsub splitter, '\1' + separator
|
13
|
+
str = "#{ before.chomp( separator ).reverse }"
|
14
|
+
str += ".#{ after }" if after
|
15
|
+
return str
|
16
|
+
end
|
17
|
+
end
|
data/lib/treevisitor.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# rubygems
|
2
|
+
require "rubygems"
|
3
|
+
require "abstract"
|
4
|
+
|
5
|
+
#
|
6
|
+
# Nodo Astratto
|
7
|
+
# Gerarchia delle classi
|
8
|
+
#
|
9
|
+
# AbsNode ha un nome, un parent
|
10
|
+
# | definisce un path
|
11
|
+
# |
|
12
|
+
# |- LeafNode
|
13
|
+
# |
|
14
|
+
# |- TreeNode
|
15
|
+
#
|
16
|
+
#
|
17
|
+
class AbsNode
|
18
|
+
|
19
|
+
attr_reader :parent
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# solo TreeNode puo' scrivere vedi funzione add_leaf
|
23
|
+
attr_accessor :prev
|
24
|
+
attr_accessor :next
|
25
|
+
|
26
|
+
|
27
|
+
def initialize( name )
|
28
|
+
@parent = nil
|
29
|
+
@name = name
|
30
|
+
@prefix_path = nil
|
31
|
+
invalidate
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# invalidate cached info
|
36
|
+
#
|
37
|
+
def invalidate
|
38
|
+
@path = nil
|
39
|
+
@path_from_root = nil
|
40
|
+
@depth = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefix_path
|
44
|
+
if not @parent.nil?
|
45
|
+
raise "Not root!!"
|
46
|
+
end
|
47
|
+
@prefix_path
|
48
|
+
end
|
49
|
+
|
50
|
+
def prefix_path=( prefix )
|
51
|
+
if not @parent.nil?
|
52
|
+
raise "Not root!!"
|
53
|
+
end
|
54
|
+
if prefix != @prefix_path
|
55
|
+
@prefix_path = prefix
|
56
|
+
invalidate
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def root
|
61
|
+
if root?
|
62
|
+
self
|
63
|
+
else
|
64
|
+
parent.root
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def path
|
69
|
+
return @path unless @path.nil?
|
70
|
+
if @parent.nil?
|
71
|
+
if @prefix_path
|
72
|
+
@path = @prefix_path + @name
|
73
|
+
else
|
74
|
+
@path = @name
|
75
|
+
end
|
76
|
+
else
|
77
|
+
@path = File.join( @parent.path, @name )
|
78
|
+
end
|
79
|
+
@path
|
80
|
+
end
|
81
|
+
|
82
|
+
def path_from_root
|
83
|
+
return @path_from_root unless @path_from_root.nil?
|
84
|
+
if @parent.nil?
|
85
|
+
if @prefix_path
|
86
|
+
@path_from_root = @prefix_path
|
87
|
+
else
|
88
|
+
@path_from_root = ""
|
89
|
+
end
|
90
|
+
else
|
91
|
+
@path_from_root = File.join( @parent.path_from_root, @name )
|
92
|
+
end
|
93
|
+
@path_from_root
|
94
|
+
end
|
95
|
+
|
96
|
+
def depth
|
97
|
+
return @depth unless @depth.nil?
|
98
|
+
if @parent.nil?
|
99
|
+
@depth = 1
|
100
|
+
else
|
101
|
+
@depth = @parent.depth + 1
|
102
|
+
end
|
103
|
+
@depth
|
104
|
+
end
|
105
|
+
|
106
|
+
def accept( visitor )
|
107
|
+
not_implemented
|
108
|
+
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
|
112
|
+
def parent=( parent )
|
113
|
+
@parent = parent
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# common
|
2
|
+
require 'treevisitor/tree_node'
|
3
|
+
require 'treevisitor/dir_tree_walker'
|
4
|
+
require 'treevisitor/tree_node_visitor'
|
5
|
+
|
6
|
+
#
|
7
|
+
# costruisce una albero TreeNode a partire dalla struttura
|
8
|
+
# della directory, simile a clona
|
9
|
+
# Clona un TreeNode
|
10
|
+
#
|
11
|
+
class BuildDirTreeVisitor < TreeNodeVisitor
|
12
|
+
|
13
|
+
attr_reader :root
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super
|
17
|
+
@root = nil
|
18
|
+
@stack = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def enter_treeNode( pathname )
|
22
|
+
if @stack.empty?
|
23
|
+
treeNode = TreeNode.new( File.basename( pathname ) )
|
24
|
+
@root = treeNode
|
25
|
+
else
|
26
|
+
treeNode = TreeNode.new( File.basename( pathname ), @stack.last )
|
27
|
+
end
|
28
|
+
@stack.push( treeNode )
|
29
|
+
end
|
30
|
+
|
31
|
+
def exit_treeNode( pathname )
|
32
|
+
@stack.pop
|
33
|
+
end
|
34
|
+
|
35
|
+
def visit_leafNode( pathname )
|
36
|
+
leafNode = LeafNode.new( File.basename(pathname), @stack.last )
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Utilizzo della classa astratta DirTreeProcessor
|
43
|
+
# per stampare i nodi di un TreeNode
|
44
|
+
#
|
45
|
+
class PrintDirTreeVisitor < TreeNodeVisitor
|
46
|
+
|
47
|
+
def enter_treeNode( pathname )
|
48
|
+
puts pathname
|
49
|
+
end
|
50
|
+
|
51
|
+
def exit_treeNode( treeNode )
|
52
|
+
end
|
53
|
+
|
54
|
+
def visit_leafNode( pathname )
|
55
|
+
puts pathname
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# stdlib
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
# common
|
5
|
+
require 'treevisitor/dir_tree_walker'
|
6
|
+
require 'treevisitor/build_dir_treevisitor'
|
7
|
+
|
8
|
+
#
|
9
|
+
#
|
10
|
+
#
|
11
|
+
class CliDirTree
|
12
|
+
|
13
|
+
def self.run
|
14
|
+
self.new.parse_args( ARGV )
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_args( argv )
|
18
|
+
|
19
|
+
options = { :verbose => true, :force => false, :algo => 'build' }
|
20
|
+
|
21
|
+
opts = OptionParser.new
|
22
|
+
opts.banner = "Usage: example.rb [options]"
|
23
|
+
|
24
|
+
opts.separator ""
|
25
|
+
opts.separator "programma per testare la classe DirProcessor"
|
26
|
+
opts.separator "Inserire il nome della directory da cui costuire il tree"
|
27
|
+
|
28
|
+
opts.separator ""
|
29
|
+
opts.separator "opzioni: "
|
30
|
+
|
31
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
32
|
+
options[:verbose] = v
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-q", "--quiet", "quiet mode as --no-verbose") do |v|
|
36
|
+
options[:verbose] = false
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-h", "--help", "Show this message") do
|
40
|
+
puts opts
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
algos = %w[build visit]
|
46
|
+
algo_aliases = { "b" => "build", "v" => "visit" }
|
47
|
+
|
48
|
+
algo_list = (algo_aliases.keys + algos).join(',')
|
49
|
+
opts.on("-a", "--algo ALGO", algos, algo_aliases, "Select algo"," (#{algo_list})") do |algo|
|
50
|
+
options[:algo] = algo
|
51
|
+
end
|
52
|
+
|
53
|
+
rest = opts.parse(argv)
|
54
|
+
|
55
|
+
# p options
|
56
|
+
# p ARGV
|
57
|
+
|
58
|
+
if rest.length < 1
|
59
|
+
puts opts
|
60
|
+
return 1
|
61
|
+
end
|
62
|
+
|
63
|
+
dirname = rest[0]
|
64
|
+
dirname = File.expand_path( dirname )
|
65
|
+
|
66
|
+
puts "reading : #{dirname}"
|
67
|
+
|
68
|
+
dtw = DirTreeWalker.new( dirname )
|
69
|
+
dtw.add_ignore_dir( ".svn" )
|
70
|
+
dtw.add_ignore_dir( "catalog_data" )
|
71
|
+
|
72
|
+
case options[:algo]
|
73
|
+
when 'build'
|
74
|
+
visitor = BuildDirTreeVisitor.new
|
75
|
+
dtw.run( visitor )
|
76
|
+
puts visitor.root.to_str
|
77
|
+
when 'visit'
|
78
|
+
visitor = PrintDirTreeVisitor.new
|
79
|
+
dtw.run( visitor )
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|