From 25c5c938c6a6dfaac4a3d59881c5bd38557cf6b0 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Mon, 6 Jul 2015 01:48:24 +0100 Subject: [PATCH 1/3] Typo --- files/src/main/scala/coursier/Files.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/src/main/scala/coursier/Files.scala b/files/src/main/scala/coursier/Files.scala index 7c09f4533..ddaa8724d 100644 --- a/files/src/main/scala/coursier/Files.scala +++ b/files/src/main/scala/coursier/Files.scala @@ -167,7 +167,7 @@ case class Files( } case None => - Task.now(-\/(FileError.ChecksumNoFound(sumType, artifact0.url))) + Task.now(-\/(FileError.ChecksumNotFound(sumType, artifact0.url))) } } @@ -256,7 +256,7 @@ object FileError { case class DownloadError(message: String) extends FileError case class NotFound(file: String) extends FileError case class Locked(file: String) extends FileError - case class ChecksumNoFound(sumType: String, file: String) extends FileError + case class ChecksumNotFound(sumType: String, file: String) extends FileError case class WrongChecksum(sumType: String, got: String, expected: String, file: String, sumFile: String) extends FileError } From d7696cc44575e498aa283d6bf6e0788331329e69 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Mon, 6 Jul 2015 01:48:25 +0100 Subject: [PATCH 2/3] Formatting --- files/src/main/scala/coursier/Files.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/files/src/main/scala/coursier/Files.scala b/files/src/main/scala/coursier/Files.scala index ddaa8724d..dc008e98b 100644 --- a/files/src/main/scala/coursier/Files.scala +++ b/files/src/main/scala/coursier/Files.scala @@ -188,11 +188,11 @@ case class Files( checksum.fold(res) { sumType => res .flatMap{ - case err @ -\/(_) => Task.now(err) - case \/-(f) => - validateChecksum(artifact, sumType) - .map(_.map(_ => f)) - } + case err @ -\/(_) => Task.now(err) + case \/-(f) => + validateChecksum(artifact, sumType) + .map(_.map(_ => f)) + } } } From d84fcf6608f80c82aa77f6b2ed8f7732a6547c44 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Mon, 6 Jul 2015 01:48:26 +0100 Subject: [PATCH 3/3] Basic file locking Needs tests --- files/src/main/scala/coursier/Files.scala | 47 +++++++++++++++-------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/files/src/main/scala/coursier/Files.scala b/files/src/main/scala/coursier/Files.scala index dc008e98b..830b0e216 100644 --- a/files/src/main/scala/coursier/Files.scala +++ b/files/src/main/scala/coursier/Files.scala @@ -1,6 +1,7 @@ package coursier import java.net.URL +import java.nio.channels.{ OverlappingFileLockException, FileLock } import java.security.MessageDigest import java.util.concurrent.{ Executors, ExecutorService } @@ -92,27 +93,43 @@ case class Files( logger.foreach(_.downloadingArtifact(url)) val url0 = new URL(url) - val b = Array.fill[Byte](Files.bufferSize)(0) val in = new BufferedInputStream(url0.openStream(), Files.bufferSize) - try { - val out = new FileOutputStream(file) + val result = try { - @tailrec - def helper(): Unit = { - val read = in.read(b) - if (read >= 0) { - out.write(b, 0, read) - helper() - } - } + val out = new FileOutputStream(file) + try { + var lock: FileLock = null + try { + lock = out.getChannel.tryLock() + if (lock == null) + -\/(FileError.Locked(file.toString)) + else { + val b = Array.fill[Byte](Files.bufferSize)(0) - helper() - } finally out.close() - } finally in.close() + @tailrec + def helper(): Unit = { + val read = in.read(b) + if (read >= 0) { + out.write(b, 0, read) + helper() + } + } + + helper() + \/-(file) + } + } + catch { + case e: OverlappingFileLockException => + -\/(FileError.Locked(file.toString)) + } + finally if (lock != null) lock.release() + } finally out.close() + } finally in.close() logger.foreach(_.downloadedArtifact(url, success = true)) - \/-(file) + result } catch { case e: Exception => logger.foreach(_.downloadedArtifact(url, success = false))