Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #92: Remove File.Type #101

Merged
merged 2 commits into from
Jan 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@
## v2.17.1

* [PR #99](https://github.com/pathikrit/better-files/pull/99): Release for Scala 2.12

## v2.18.0

* [PR #100](https://github.com/pathikrit/better-files/pull/100): Fix issue in unzip of parents
* [PR #101](https://github.com/pathikrit/better-files/pull/101): Removed File.Type
21 changes: 2 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
0. [Simple I/O](#file-readwrite)
0. [Streams and Codecs](#streams-and-codecs)
0. [Java compatibility](#java-interoperability)
0. [Pattern matching](#pattern-matching)
0. [Globbing](#globbing)
0. [File system operations](#file-system-operations)
0. [UNIX DSL](#unix-dsl)
Expand All @@ -38,13 +37,13 @@ To use the [Akka based file monitor](akka), also add this:
```scala
libraryDependencies ++= Seq(
"com.github.pathikrit" %% "better-files-akka" % version,
"com.typesafe.akka" %% "akka-actor" % "2.3.15"
"com.typesafe.akka" %% "akka-actor" % "2.4.16"
)
```
Latest `version`: [![Maven][mavenImg]][mavenLink]

Although this library is currently only actively developed for Scala 2.12,
you can find reasonably recent versions of this library for Scala 2.10 and 2.11 [here](https://oss.sonatype.org/#nexus-search;quick~better-files)
you can find reasonably recent versions of this library for Scala 2.10 and 2.11 [here](https://oss.sonatype.org/#nexus-search;quick~better-files).

## Tests [![codecov][codecovImg]][codecovLink]
* [FileSpec](core/src/test/scala/better/files/FileSpec.scala)
Expand Down Expand Up @@ -221,22 +220,6 @@ val br : BufferedReader = reader.buffered
val bw : BufferedWriter = writer.buffered
val mm : MappedByteBuffer = fileChannel.toMappedByteBuffer
```

### Pattern matching
Instead of `if-else`, more idiomatic powerful Scala [pattern matching](http://pathikrit.github.io/better-files/latest/api/better/files/File$$Type$.html):
```scala
/**
* @return true if file is a directory with no children or a file with no contents
*/
def isEmpty(file: File): Boolean = file match {
case File.Type.SymbolicLink(to) => isEmpty(to) // this must be first case statement if you want to handle symlinks specially; else will follow link
case File.Type.Directory(files) => files.isEmpty
case File.Type.RegularFile(content) => content.isEmpty
case _ => file.notExists // a file may not be one of the above e.g. UNIX pipes, sockets, devices etc
}
// or as extractors on LHS:
val File.Type.Directory(researchDocs) = home/"Downloads"/"research"
```

### Globbing
No need to port [this](http://docs.oracle.com/javase/tutorial/essential/io/find.html) to Scala:
Expand Down
49 changes: 16 additions & 33 deletions core/src/main/scala/better/files/File.scala
Original file line number Diff line number Diff line change
Expand Up @@ -722,24 +722,31 @@ class File private(val path: Path) {
/**
* @return true if file is not present or empty directory or 0-bytes file
*/
def isEmpty: Boolean = {
this match {
case File.Type.Directory(children) => children.isEmpty
case File.Type.RegularFile(content) => content.isEmpty
case _ => notExists
def isEmpty(implicit linkOptions: File.LinkOptions = File.LinkOptions.default): Boolean = {
if (isDirectory(linkOptions)) {
children.isEmpty
} else if (isRegularFile(linkOptions)) {
toJava.length() == 0
} else {
notExists(linkOptions)
}
}

def isNotEmpty(implicit linkOptions: File.LinkOptions = File.LinkOptions.default): Boolean = {
!isEmpty(linkOptions)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a new method in the upcoming release, consider renaming it to nonEmpty by analogy with the collections methods isEmpty/nonEmpty.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Done: 18c9cd5


/**
* If this is a directory, remove all its children
* If its a file, empty the contents
*
* @return this
*/
def clear(): this.type = {
this match {
case File.Type.Directory(children) => children.foreach(_.delete())
case _ => writeByteArray(Array.emptyByteArray)(File.OpenOptions.default)
def clear()(implicit linkOptions: File.LinkOptions = File.LinkOptions.default): this.type = {
if (isDirectory(linkOptions)) {
children.foreach(_.delete())
} else {
writeByteArray(Array.emptyByteArray)(File.OpenOptions.default)
}
this
}
Expand Down Expand Up @@ -882,30 +889,6 @@ object File {
val default : Order = byDirectoriesFirst
}

/**
* Denote various file types using this
*
* @tparam Content The type of underlying contents e.g. a directory has its children files as contents but a regular file may have bytes as contents
*/
sealed trait Type[Content] {
def unapply(file: File): Option[Content]
}

object Type {

case object RegularFile extends Type[BufferedSource] {
override def unapply(file: File) = when(file.isRegularFile)(file.newBufferedSource)
}

case object Directory extends Type[Files] {
override def unapply(file: File) = when(file.isDirectory)(file.children)
}

case object SymbolicLink extends Type[File] {
override def unapply(file: File) = file.symbolicLink
}
}

class PathMatcherSyntax private (val name: String)
object PathMatcherSyntax {
val glob = new PathMatcherSyntax("glob")
Expand Down
28 changes: 3 additions & 25 deletions core/src/test/scala/better/files/FileSpec.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package better.files

import File.{root, home}
import File.Type._
import Cmds._

import org.scalatest._
Expand Down Expand Up @@ -92,27 +91,6 @@ class FileSpec extends FlatSpec with BeforeAndAfterEach with Matchers {
Seq(f, f1, f2, f4, /*f5,*/ f6, f8, f9).map(_.toString).toSet shouldBe Set(f.toString)
}

it can "be matched" in {
"src"/"test"/"foo" match {
case SymbolicLink(to) => fail() //this must be first case statement if you want to handle symlinks specially; else will follow link
case Directory(children) => fail()
case RegularFile(contents) => fail()
case other if other.exists => fail() //A file may not be one of the above e.g. UNIX pipes, sockets, devices etc
case _ => //A file that does not exist
}
root/"dev"/"null" match {
case SymbolicLink(to) => fail()
case Directory(children) => fail()
case RegularFile(contents) => fail()
case other if other.exists => //A file can be not any of the above e.g. UNIX pipes & sockets etc
case _ => fail()
}
root/"dev" match {
case Directory(children) => children.exists(_.pathAsString == "/dev/null") shouldBe true // /dev should have 'null'
case _ => fail()
}
}

it should "do basic I/O" in {
t1 < "hello"
t1.contentAsString shouldEqual "hello"
Expand Down Expand Up @@ -197,9 +175,9 @@ class FileSpec extends FlatSpec with BeforeAndAfterEach with Matchers {

it should "support sorting" in {
testRoot.list.toSeq.sorted(File.Order.byName) should not be empty
testRoot.list.toSeq.max(File.Order.bySize) should not be empty
testRoot.list.toSeq.min(File.Order.byDepth) should not be empty
testRoot.list.toSeq.min(File.Order.byModificationTime) should not be empty
testRoot.list.toSeq.max(File.Order.bySize).isEmpty shouldBe false
testRoot.list.toSeq.min(File.Order.byDepth).isEmpty shouldBe false
testRoot.list.toSeq.min(File.Order.byModificationTime).isEmpty shouldBe false
testRoot.list.toSeq.sorted(File.Order.byDirectoriesFirst) should not be empty
}

Expand Down