require 'epitools' require 'epitools/permutations' describe Path do it "initializes and accesses everything" do path = Path.new("/blah/what.mp4/.mp3/hello.avi") path.dirs.should == %w[ blah what.mp4 .mp3 ] path.dir.should == "/blah/what.mp4/.mp3" path.filename.should == "hello.avi" path.ext.should == "avi" path.base.should == "hello" end it "dups itself" do path = Path.new "/whatever/blah/stuff.ext" path2 = path.dup path2.path.should == path.path path.dirs.pop path2.path.should_not == path.path end it "works with relative paths" do path = Path.new("../hello.mp3/blah") path.filename.should == "blah" path.ext.should == nil abs_path = File.join(File.expand_path(".."), "hello.mp3") path.dir.should == abs_path end it "'relative_to's" do # Path["/etc"].relative_to(Path["/tmp"]).should == "../etc/" Path["/etc/passwd"].relative_to("/etc").should == "passwd" end it "should glob with relative paths" do # raise "not implemented" end it "handles directories" do path = Path.new("/etc/") path.dirs.should_not == nil path.dir.should == "/etc" path.filename.should == nil end it "replaces ext" do path = Path.new("/blah/what.mp4/.mp3/hello.avi") path.ext.should == "avi" path.ext = "mkv" path.ext.should == "mkv" path.filename[-4..-1].should == ".mkv" path.ext += ".extra" path.filename.should == "hello.mkv.extra" path.ext.should == "extra" end it "replaces filename" do path = Path.new(__FILE__) path.dir?.should == false path.filename = nil path.dir?.should == true end it "fstats" do path = Path.new(__FILE__) path.exists?.should == true path.dir?.should == false path.file?.should == true path.symlink?.should == false path.mtime.class.should == Time end it "globs" do path = Path.new(__FILE__) glob = path.dir + "/*spec.rb" specs = Path.glob(glob) path.in?(specs).should == true end it "Path[file] and Path[glob]s" do path = Path.new(__FILE__) path.should == Path[__FILE__] glob = path.dir + "/*spec.rb" specs = Path.glob(glob) Path[glob].should == specs end it "paths can be passed to ruby File methods" do path = Path.new(__FILE__) data = File.read(path) data.size.should > 0 end it "opens & read files" do path = Path.new(__FILE__) path.open do |f| f.read.size.should > 0 end path.read.size.should > 0 end it "reads with length and offset" do path = Path.new(__FILE__) path.read(25).size.should == 25 s1 = path.read(25,15) s2 = path.read(40) s2[15..-1].should == s1 end it "reads/writes various formats (json, yaml, etc.)" do data = { "hello" => "there", "amazing" => [1,2,3,4] } yaml = Path.tmpfile yaml.write_yaml(data) yaml.read_yaml.should == data json = Path.tmpfile json.write_json(data) json.read_json.should == data data = "

The best webpage in the universe.

" html = Path.tmpfile html.write data html.read_html.at("h1").to_s.should == data end it "parses files" do data = {"hello"=>"there"} f = Path["/tmp/something.json"] f.write_json(data) f.parse.should == data end it "makes paths THREE WAYS!" do [ Path(__FILE__), Path[__FILE__], Path.new(__FILE__), ].all_pairs do |p1, p2| p1.path.should == p2.path end end it "appending to paths with /" do ( Path['/etc']/'passwd' ).should == Path['/etc/passwd'] ( Path['/etc']/Path['passwd'] ).should_not == Path['/etc/passwd'] end it "lets you change the dirs array" do path = Path['/spam/spam/spam/'] path.dirs.should == %w[ spam spam spam ] path.dirs << 'humbug' path.dir.should == '/spam/spam/spam/humbug' path.path.should == '/spam/spam/spam/humbug/' end it "handles URLs" do path = Path["http://google.com/?search=blah"] path.host.should == "google.com" path.port.should == 80 path.query.should == {"search" => "blah"} path.uri?.should == true end it "tempfiles" do path = Path.tmpfile path.exists?.should == true path.write "blah" path.read.should == "blah" path.delete! path.exists?.should == false end it "appends and writes" do path = Path.tmpfile path.exists?.should == true path.write "blah" path.append "what" (path << "lul").should == path path.read.should == "blahwhatlul" path.write "rawr" path.read.should == "rawr" end it "cds into directories" do path = Path["/etc"] start = Path.pwd path.should_not == Path.pwd path.cd { path.should == Path.pwd } Path.pwd.should == start end it "renames/mvs" do path = Path.tmp path.rm path.touch path.exists?.should == true old_name = path.to_s dest = path.rename(:ext=>".dat") dest.to_s.should == old_name+".dat" path.to_s.should == old_name dest.to_s.should_not == old_name dest.exists?.should == true path.exists?.should == false path.touch lambda { path.rename(:ext=>".dat") }.should raise_error dest.rm path.rename!(:ext=>".dat") path.to_s.should_not == old_name path.exists?.should == true path.rm end it "backups" do path = Path.tmp path.rm path.touch dest = path.backup! path.exists?.should == false dest.exists?.should == true dest.rm path.touch p path.numbered_backup_file dest = path.numbered_backup! path.touch dest2 = path.numbered_backup! dest.should_not == dest2 path.should_not == dest dest.rm dest2.rm end it "rms" do path = Path.tmpfile path << "data" path.exists?.should == true path.rm.should == true path.exists?.should == false end it "truncates" do tmp = Path.tmp tmp.rm tmp.touch tmp.exists?.should == true tmp.write("1"*100) tmp.size.should == 100 tmp.truncate(50) tmp.size.should == 50 tmp.truncate tmp.size.should == 0 end it "checksums" do a, b = Path["**/*.rb"].take(2) [:sha1, :sha2, :md5].each do |meth| sum1 = a.send(meth) sum2 = b.send(meth) sum1.should_not == sum2 sum1.size.should > 5 sum1.should =~ /[a-z0-9]/ sum2.should =~ /[a-z0-9]/ end end it "mkdirs" do tmp = Path.tmpfile lambda { tmp.mkdir }.should raise_error tmp.rm tmp.mkdir.should be_truthy tmp.rm.should be_truthy tmp2 = Path.tmpfile tmp2.rm tmp2 = tmp2/"nonexistent"/"directory" tmp2.exists?.should == false lambda { tmp2.mkdir_p }.should_not raise_error end it "has classmethods" do path = Path.tmpfile path << "whee"*100 path.sha1.should == Path.sha1(path) end it "gzips and gunzips" do tmp = Path.tmp data = "" 500.times { data << "whee" } tmp.write data tmp.size.should == data.size tmp.ext.should_not == "gz" before = tmp.size tmp.gzip! after = tmp.size before.should > after tmp.ext.should == "gz" tmp.gunzip! tmp.size.should == before end it "exts" do path = Path["file.tar.gz"] path.ext.should == "gz" path.exts.should == ["tar", "gz"] end it "ios and streams" do path = Path.tmpfile f = open(path) f.inspect.should == path.io.inspect f.inspect.should == path.stream.inspect end it "mimes" do Path[__FILE__].mimetype.should == "application/x-ruby" end it "magic types" do Path[__FILE__].type.should == "rb" end it "whiches" do Path.which("ruby").should_not be_nil Path.which("asdfasdfhkajlsdhfkljashdf").should be_nil Path.which("ruby").class.should == Path testprogs = ["ps", "sh", "tar"] real_result = `which #{testprogs.join(" ")}`.each_line.map(&:strip) Path.which(*testprogs).map(&:path).should == real_result end it "Path[]s another path" do path = Path.tmpfile Path[path].path.should == path.path end it "uses advanced glob features" do # ruby-1.9.2-p180 :001 > Path["~/.ssh/id_{dsa,rsa}.pub"] # => /home/epi/.ssh/id_{dsa,rsa}.pub # ruby-1.9.2-p180 :002 > Dir["~/.ssh/id_{dsa,rsa}.pub"] # => [] # ruby-1.9.2-p180 :003 > Dir["../../.ssh/id_{dsa,rsa}.pub"] # => ["../../.ssh/id_rsairb.pub"] Path["~/.ssh/id_{dsa,rsa}.pub"].size.should > 0 end it "modes" do Path.tmpfile.mode.class.should == Fixnum end it "chmods and chmod_Rs" do tmp = Path.tmpfile tmp2 = Path.tmpfile tmp.touch tmp2.touch tmp.mode.should == tmp2.mode tmp.chmod("+x") system("chmod", "+x", tmp2) tmp.mode.should == tmp2.mode end it "siblingses" do sibs = Path.tempfile.siblings sibs.is_an?(Array).should == true sibs.include?(self).should == false end it 'path/".."s shows parent dir of file' do # path/ tmp = Path.tmpfile tmp.rm if tmp.exists? tmp.mkdir #tmp.to_s.endswith('/').should == true file = tmp/"file" file.touch file.dirs.should == tmp.dirs file.filename.should_not == tmp.filename end it 'parents and childs properly' do root = Path["/"] parent = Path["/blah/stuff"] child = Path["/blah/stuff/what"] neither = Path["/whee/yay"] # Table of parent=>child relationships { parent => child, root => parent, root => child, root => neither, }.each do |parent, child| parent.should be_parent_of child child.should_not be_parent_of parent child.should be_child_of parent parent.should_not be_child_of child end neither.parent_of?(child).should == false neither.parent_of?(parent).should == false end it "checks file modes" do path = Path.tmpfile path.exe?.should == false path.chmod(0o666) (path.mode & 0o666).should > 0 end it 'symlinks files' do path = Path.tmpfile path << "some data" target = "#{path}-symlinked" path.ln_s target target = Path[target] target.symlink?.should == true target.read.should == path.read target.symlink_target.should == path end it 'symlinks relative dirs' do raise "Path.ln_s arguments are backwards. It needs to be something easier to remember, like 'Path#symlink_to'" tmpdir = Path.tmpdir symlink = (tmpdir/"a_new_link") symlink.ln_s "../../etc/passwd" symlink.symlink?.should == true symlink.rm dir.rm end it 'swaps two files' do # swap two regular files # swap a symlink and a regular file # swap two symlinks end it 'realpaths' do etc = Path["/etc"] tmp = Path.tmpfile tmp.rm etc.ln_s tmp tmp.symlink_target.should == etc tmp.realpath.should == etc Path["/etc/../etc"].realpath.should == etc end it "shouldn't glob with Path#join" do path = Path["/etc"].join("blah{}") path.path.should == "/etc/blah{}" end it "should glob with Path#/" do entries = Path["/etc"]/"*" entries.should be_an Array end it "xattrs" do file = Path["~/test"] file.touch file["nothing"].should == nil file["user.test"] = "whee" file["user.test"].should == "whee" Path.getfattr(file)["user.test"].should == "whee" file["user.test"] = nil file["user.test"].should == nil Path.getfattr(file)["user.test"].should == nil lambda { file["blahblahblah"] = "whee" }.should raise_error # Test assigning an entire hash of attributes, using diffing attrs = file.attrs attrs["user.diff_element"] = "newtest" file.attrs = attrs file["user.diff_element"].should == "newtest" file["user.null-terminated-string"] = "stuff\u0000" file["user.null-terminated-string"].should == "stuff" end it "changes mtime/atime" do file = Path.tmp now = file.mtime before = now - 50.days file.mtime = before file.mtime.should == before beforebefore = before - 50.days file.atime = beforebefore file.atime.should == beforebefore end it "each_chunks" do path = Path["/etc/passwd"] path.each_chunk(20) { |chunk| chunk.size.should == 20; break } end end