gf-treevisitor 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|