Skip to content

Instantly share code, notes, and snippets.

@yhara
Created Oct 12, 2008
Embed
What would you like to do?
A sample code of 'treemap' gem (and Rack). [1] du ~/ > a.du [2] edit path to a.du [3] rackup du.ru
require 'yaml'
require 'rubygems'
require 'treemap'
require 'rack'
# monkey patch for treemap :-(
class Treemap::HtmlOutput
def node_label(node)
node.label
end
end
class DUParser
Entry = Struct.new(:size, :bytes, :path)
def initialize(src)
@data = src.lines.map{|x|
size, *rest = x.chomp.split(/\t/)
Entry.new(size.strip, size_to_bytes(size.strip), rest.join("\t"))
}
end
TYPES = {
"B" => 1,
"K" => 1024,
"M" => 1024 * 1024,
"G" => 1024 * 1024 * 1024,
"T" => 1024 * 1024 * 1024 * 1024,
"P" => 1024 * 1024 * 1024 * 1024 * 1024,
}
def size_to_bytes(s)
_, n, t = s.match(/([\d.]+)(.)/).to_a
if (m = TYPES[t])
(n.to_f * m).to_i
else
raise ArgumentError, "bad size format: unknown size type: #{t}"
end
end
def ls(subpath)
@data.select{|entry|
(entry.path =~ %r<\A#{Regexp.quote subpath}(.+)>) and ($1 !~ %r<[^\\]/>)
}.map{|entry|
Entry.new(entry.size, entry.bytes, entry.path.sub(subpath, ""))
}
end
end
class TreemapApp
def initialize(path)
@parser = DUParser.new(File.read(path))
@writer = Treemap::HtmlOutput.new{|o|
o.width = 800
o.height = 600
o.center_labels_at_depth = 1
}
end
def call(env)
req = Rack::Request.new(env)
res = Rack::Response.new
res.write make_tree(req.path_info, @parser.ls("."+req.path_info))
res.finish
end
def make_tree(here, data)
root = Treemap::Node.new
data.each do |entry|
newpath = "#{here}#{entry.path}/"
label = "#{entry.path}<br>(#{entry.size})"
root.new_child :size => entry.bytes,
:label => "<a href='#{newpath}' title='#{label}'>#{label}</a>"
end
@writer.to_html(root)
end
end
unless $NO_RUN
use Rack::Reloader
use Rack::CommonLogger
use Rack::ShowExceptions
use Rack::ShowStatus
run TreemapApp.new("/Users/yhara/a.du")
end
# vim: set ft=ruby:
$NO_RUN = true
load 'du.ru'
DU_SAMPLE = <<EOD
36B ./A
4.0K ./B
2.0K ./C/chocolate
10B ./C/call\\/cc
4.0K ./C
2.0K ./D\\/F
100K .
EOD
describe "DUParser" do
before :each do
@parser = DUParser.new(DU_SAMPLE)
end
# it should take the path of the file which contains an output of 'du' command
it "は、インスタンス生成時にduの出力ファイルをとる" do
@parser.should be_an_instance_of(DUParser)
end
# it should convert size to bytes
it "は、サイズをバイト数に直せる" do
@parser.size_to_bytes("100B").should == 100
@parser.size_to_bytes("0.5K").should == 512
@parser.size_to_bytes("3M").should == (3 * 1024 * 1024)
end
# it should list up the directories under a given directory
it "は、指定したディレクトリ以下の情報を検索できる" do
@parser.ls("./").should == [
DUParser::Entry.new("36B", 36, "A"),
DUParser::Entry.new("4.0K", 4096, "B"),
DUParser::Entry.new("4.0K", 4096, "C"),
DUParser::Entry.new("2.0K", 2048, "D\\/F")
]
@parser.ls("./C/").should == [
DUParser::Entry.new("2.0K", 2048, "chocolate"),
DUParser::Entry.new("10B", 10, "call\\/cc"),
]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment