svnno****@sourc*****
svnno****@sourc*****
2009年 12月 10日 (木) 17:26:26 JST
Revision: 57 http://sourceforge.jp/projects/ngms/svn/view?view=rev&revision=57 Author: osiire Date: 2009-12-10 17:26:26 +0900 (Thu, 10 Dec 2009) Log Message: ----------- [NMTree] implements FileSystemTree Modified Paths: -------------- trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala trunk/source/NMTree/test/NMFileSystemTreeTest.scala trunk/source/NMTree/test/NMPathTest.scala Modified: trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala =================================================================== --- trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala 2009-12-10 07:49:52 UTC (rev 56) +++ trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala 2009-12-10 08:26:26 UTC (rev 57) @@ -17,9 +17,7 @@ var mountPoint : NMPath = mnt implicit def ofRealPath( path : NMPath ) : String = { - //未実装 - //NMPath.diff( mnt.canonical, path.canonical ) - "" + NMPath.concat(realRoot, NMPath.diff(path.canonical,mnt.canonical)) } implicit def toNMPath( path : String ) : NMPath = { @@ -29,7 +27,7 @@ trait Identifier { val id = 0L // 未実装 } - + def createStream( path : NMPath ) : NMTree.TStreamElement = { val file = new File( path ) new { @@ -85,7 +83,7 @@ * 自身のパスに子供がいない場合は空リストになる。 */ def children( path : NMPath ) : List[NMPath] = { - (new File(path)).list().toList.map(toNMPath) + (new File(path)).list().toList.map(path.concat(_)) } /** @@ -95,7 +93,7 @@ def attribute( path : NMPath ) : NMElementAttribute = { var file = new File( path ) new NMElementAttribute { - val size = 0L + val size = file.length() val lastUpdateDate = new Date( file.lastModified() ) val versionStatus = Neutral } @@ -113,12 +111,56 @@ } object TreeOperations { - def move( src : NMPath, dst : NMPath ) : Unit = { } + def move( src : NMPath, dst : NMPath ) : Unit = { + (new File(src)).renameTo(new File(dst)) + } - def copy( src : NMPath, dst : NMPath, overwrite : Boolean, recursive : Boolean ) : Unit = { } + private def copyFile(in : File, out : File ) { + if( in.isDirectory ) { + out.mkdir + } else { + var sourceChannel = new FileInputStream(in).getChannel + var destinationChannel = new FileOutputStream(out).getChannel + sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel) + sourceChannel.close + destinationChannel.close + } + } - def delete( path : NMPath, recursive : Boolean ) : Unit = { } + private def copyFileRec(in : File, out : File){ + if( in.isDirectory ) { + out.mkdir + for( file <- in.listFiles ) + copyFileRec( file, new File( out, file.getName ) ) + } else { + copyFile(in, out) + } + } + def copy( src : NMPath, dst : NMPath, overwrite : Boolean, recursive : Boolean ) { + if(!overwrite && PathOperations.exists(dst)) { + return; + } + + if(recursive) + copyFileRec(new File( src ) , new File( dst )) + else { + copyFile(new File( src ) , new File( dst )) + } + } + + private def deleteFileRec(root : File) { + if(root.isDirectory) + root.listFiles.foreach( deleteFileRec( _ ) ) + root.delete() + } + def delete( path : NMPath, recursive : Boolean ) : Unit = { + if(recursive) + deleteFileRec( new File( path ) ) + else + ( new File( path ) ).delete + } + def symLink( src : NMPath, dst : NMPath ) : Unit = { } def changePermission( src : NMPath, permission : NMElementPermission ) : Unit = { } @@ -134,4 +176,4 @@ def pathOp : NMTree.TPathOperations = PathOperations def treeOp : NMTree.TTreeOperations = TreeOperations -} \ No newline at end of file +} Modified: trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala =================================================================== --- trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala 2009-12-10 07:49:52 UTC (rev 56) +++ trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala 2009-12-10 08:26:26 UTC (rev 57) @@ -54,6 +54,32 @@ } } + def diff(other : InnerPath) : String = { + if(isAbsolute && other.isAbsolute) + diffElems(this.elems,other.elems) match { + case Some(elems) => + elems2str(elems) + case _ => + this.canonical + } + else + this.canonical + } + + private def diffElems(lhs : List[Element], rhs : List[Element]) : Option[List[Element]] = { + (lhs,rhs) match { + case (_, Nil) => + Some(lhs.reverse) + case ((x :: xs),(y :: ys)) => + if(x == y) + diffElems(xs,ys) + else + None + case _ => + None + } + } + private def isDot( e : Element ) : Boolean = { e match { case DOT => true @@ -112,7 +138,9 @@ case _ => false } } - def path = opt(separator) ~ repsep( elem, separator ) ~ opt(separator) ^^ + def seps = separator <~ rep(separator) + + def path = opt(seps) ~ repsep( elem, seps ) ~ opt(seps) ^^ { case head ~ elems ~ _ => new InnerPath( head, elems.filter( e => !emptyName(e)))} def elem = "[^/]+".r ^^ { case "." => DOT @@ -146,6 +174,10 @@ path + separator + child } + def diff( path : String, base : String) : String = { + makeInnerPath(path).diff(makeInnerPath(base)) + } + } /** @@ -271,4 +303,21 @@ def diff( revision : Int ) : String = { "" } + + /** + * パス同士が等しいかを調べる + * + * @param 比較するインスタンス + * @return 等しいなら真 + */ + override def equals(other : Any) : Boolean = + other match { + case that: NMPath => + (that canEqual this) && + this.canonical == that.canonical + case _ => false + } + + def canEqual(other : Any) : Boolean = + other.isInstanceOf[NMPath] } Modified: trunk/source/NMTree/test/NMFileSystemTreeTest.scala =================================================================== --- trunk/source/NMTree/test/NMFileSystemTreeTest.scala 2009-12-10 07:49:52 UTC (rev 56) +++ trunk/source/NMTree/test/NMFileSystemTreeTest.scala 2009-12-10 08:26:26 UTC (rev 57) @@ -2,7 +2,140 @@ import org.scalatest.FunSuite import org.scalatest.BeforeAndAfterEach +import java.util.Date +import java.io._ + class NMFileSystemTreeTest extends FunSuite with BeforeAndAfterEach { + implicit def s2p( path : String ) : NMPath = { + new NMPath(path) + } + val test_dir = "./test/NMFileSystemTreeTest/" + val today = new Date + + def rm_rf(path : String) { + val file = new File(path) + if(file.isDirectory()){ + file.listFiles.foreach(f => rm_rf(f.toString)) + file.delete() + }else { + file.delete() + } + } + + def mkdir(path : String){ + val file = new File(path) + file.mkdirs() + } + + def touch(path : String, content : String){ + val output = new OutputStreamWriter(new FileOutputStream( path )) + output.write(content) + output.close() + } + + override def beforeEach() { + mkdir( test_dir ) + touch( test_dir + "foo.txt" , "123\n") + mkdir( test_dir + "bar" ) + touch( test_dir + "bar/bar.txt", "" ) + + (new File( test_dir + "foo.txt")).setLastModified( today.getTime() ) + } + + + override def afterEach() { + rm_rf( test_dir ) + } + + val fs = new NMFileSystemTree( "./test/NMFileSystemTreeTest", "/" ) + val pathOp = fs.pathOp + val treeOp = fs.treeOp + + // PathOperationsのテスト + test( "パスが実際に存在するかの確認" ) { + assert (pathOp.exists("/foo.txt") === true ) + assert (pathOp.exists("/bar") === true ) + assert (pathOp.exists("/non-exists") === false) + } + + test ( "パスがディレクトリかの確認" ) { + assert (pathOp.isNode("/foo.txt") == false) + assert (pathOp.isNode("/bar") == true) + assert (pathOp.isNode("/non-exists") == false) + } + + test ( "サブファイルの取得" ) { + assert (pathOp.children("/") === List[NMPath]("/bar","/foo.txt")) + assert (pathOp.children("/bar") === List[NMPath]("/bar/bar.txt")) + } + + test ( "ファイルの属性" ) { + val attr = pathOp.attribute( "/foo.txt" ) + assert(attr.size === 4) + assert(attr.lastUpdateDate.toString() === today.toString()) + assert(attr.versionStatus === Neutral) + } + + test ( "権限" ) ( pending ) + + test ( "バージョン" ) { + assert( pathOp.versionStatus( "/foo.txt" ) === Neutral ) + } + + // tree operation + test( "move" ) { + assert( pathOp.exists( "/foo.txt" ) === true ) + assert( pathOp.exists( "/foo2.txt" ) === false ) + + treeOp.move("/foo.txt","/foo2.txt") + + assert( pathOp.exists( "/foo.txt" ) === false ) + assert( pathOp.exists( "/foo2.txt" ) === true ) + } + + test( "copy-1" ) { + assert( pathOp.exists( "/foo.txt" ) === true ) + assert( pathOp.exists( "/foo2.txt" ) === false ) + + treeOp.copy("/foo.txt","/foo2.txt",false,false) + + assert( pathOp.exists( "/foo.txt" ) === true ) + assert( pathOp.exists( "/foo2.txt" ) === true ) + } + + test( "copy-2" ) { + treeOp.copy("/foo.txt","/bar/bar.txt", false ,false) + assert( pathOp.attribute( "/bar/bar.txt" ).size === 0) + } + + test ("copy-overwrite" ){ + treeOp.copy("/foo.txt","/bar/bar.txt", true ,false) + assert( pathOp.attribute( "/bar/bar.txt" ).size === 4) + } + + test( "copy-3" ) { + treeOp.copy("/bar","/baz",false,false) + assert( pathOp.exists( "/baz/bar.txt" ) === false ) + } + + test( "copy-4") { + treeOp.copy("/bar","/baz",false,true) + assert( pathOp.exists( "/baz/bar.txt" ) === true ) + } + + test( "delete-1" ) { + assert( pathOp.exists( "/foo.txt" ) === true ) + treeOp.delete( "/foo.txt",false ) + assert( pathOp.exists( "/foo.txt" ) === false ) + } + + test( "delete-2" ) { + treeOp.delete( "/bar",false ) + assert( pathOp.exists( "/bar" ) === true ) + + treeOp.delete( "/bar",true ) + assert( pathOp.exists( "/bar" ) === false ) + } } Modified: trunk/source/NMTree/test/NMPathTest.scala =================================================================== --- trunk/source/NMTree/test/NMPathTest.scala 2009-12-10 07:49:52 UTC (rev 56) +++ trunk/source/NMTree/test/NMPathTest.scala 2009-12-10 08:26:26 UTC (rev 57) @@ -34,6 +34,9 @@ test("canonical-9") { assert( NMPath.canonical("/usr/../../../../../bin") == "/bin" ) } + test("canonical-10") { + assert( NMPath.canonical("//foo.txt") === "/foo.txt" ) + } test("parent-1") { val parent = (new NMPath("/bin/sh")).parent @@ -61,4 +64,22 @@ test("basename-3") { assert( (new NMPath("/bin/../../")).basename == "/" ) } + + test("diff-1"){ + assert ( NMPath.diff( "/foo/bar", "/foo" ) === "bar") + } + test("diff-2"){ + assert ( NMPath.diff("/" , "/foo" ) === "/") + } + test("diff-3"){ + assert ( NMPath.diff("/foo" , "/foo" ) === "") + } + test("diff-4"){ + assert ( NMPath.diff("/bar/foo" , "/foo" ) === "/bar/foo") + } + test("diff-5"){ + assert ( NMPath.diff("/foo/bar/baz" , "/foo" ) === "bar/baz") + } } + +