-
Notifications
You must be signed in to change notification settings - Fork 443
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Upgrading to java 7 and using posix nio API
- Loading branch information
Showing
6 changed files
with
261 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,60 @@ | ||
package com.typesafe.sbt | ||
package packager | ||
|
||
import java.io.File | ||
import sbt.Process | ||
import java.io.{ File, IOException } | ||
import java.nio.file.{ Paths, Files } | ||
import java.nio.file.attribute.{ PosixFilePermission, PosixFilePermissions } | ||
|
||
/** | ||
* Setting the file permissions | ||
*/ | ||
object chmod { | ||
|
||
/** | ||
* Using java 7 nio API to set the permissions. | ||
* | ||
* @param file | ||
* @param perms in octal format | ||
*/ | ||
def apply(file: File, perms: String): Unit = | ||
Process(Seq("chmod", perms, file.getAbsolutePath)).! match { | ||
case 0 => () | ||
case n => sys.error("Error running chmod " + perms + " " + file) | ||
} | ||
def safe(file: File, perms: String): Unit = | ||
try apply(file, perms) | ||
catch { | ||
case e: RuntimeException => () | ||
try { | ||
Files.setPosixFilePermissions(file.toPath, permissions(perms)) | ||
} catch { | ||
case e: IOException => sys.error("Error setting permissions " + perms + " on " + file.getAbsolutePath + ": " + e.getMessage) | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Converts a octal unix permission representation into | ||
* a java `PosiFilePermissions` compatible string. | ||
*/ | ||
object permissions { | ||
|
||
/** | ||
* @param perms in octal format | ||
* @return java 7 posix file permissions | ||
*/ | ||
def apply(perms: String): java.util.Set[PosixFilePermission] = PosixFilePermissions fromString convert(perms) | ||
|
||
def convert(perms: String): String = { | ||
require(perms.length == 4, s"Permissions must have 4 digits, got [$perms]") | ||
// ignore setuid/setguid/sticky bit | ||
val user = Character getNumericValue (perms charAt 1) | ||
val group = Character getNumericValue (perms charAt 2) | ||
val other = Character getNumericValue (perms charAt 3) | ||
|
||
asString(user) + asString(group) + asString(other) | ||
} | ||
|
||
private def asString(perm: Int): String = perm match { | ||
case 0 => "---" | ||
case 1 => "--x" | ||
case 2 => "-w-" | ||
case 3 => "-wx" | ||
case 4 => "r--" | ||
case 5 => "r-x" | ||
case 6 => "rw-" | ||
case 7 => "rwx" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/test/scala/com/typesafe/sbt/packager/DeleteDirectoryVisitor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.typesafe.sbt.packager | ||
|
||
import java.nio.file._ | ||
import java.nio.file.attribute.BasicFileAttributes | ||
import java.io.IOException | ||
|
||
class DeleteDirectoryVisitor extends SimpleFileVisitor[Path] { | ||
|
||
override def visitFile(file: Path, attrs: BasicFileAttributes) = { | ||
Files delete file | ||
FileVisitResult.CONTINUE | ||
} | ||
|
||
override def postVisitDirectory(dir: Path, exc: IOException) = { | ||
Files delete dir | ||
FileVisitResult.CONTINUE | ||
} | ||
|
||
} | ||
|
28 changes: 28 additions & 0 deletions
28
src/test/scala/com/typesafe/sbt/packager/FileUtilSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.typesafe.sbt.packager | ||
|
||
import org.scalatest._ | ||
import java.nio.file.attribute.PosixFilePermission._ | ||
|
||
class FileUtilSpec extends FlatSpec with Matchers { | ||
|
||
"permissions" should "convert octal to symbolic correctly" in { | ||
permissions convert "0000" should be("---------") | ||
permissions convert "0600" should be("rw-------") | ||
permissions convert "0755" should be("rwxr-xr-x") | ||
permissions convert "0777" should be("rwxrwxrwx") | ||
} | ||
|
||
it should "generate valid java PosixFilePermission" in { | ||
permissions("0000") should be(empty) | ||
|
||
val perm1 = permissions("0600") | ||
perm1 should not be (empty) | ||
perm1 should contain only (OWNER_READ, OWNER_WRITE) | ||
|
||
val perm2 = permissions("0755") | ||
perm2 should not be (empty) | ||
perm2 should contain only (OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_EXECUTE, OTHERS_READ, OTHERS_EXECUTE) | ||
|
||
} | ||
|
||
} |
109 changes: 109 additions & 0 deletions
109
src/test/scala/com/typesafe/sbt/packager/universal/ZipHelperSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package com.typesafe.sbt.packager.universal | ||
|
||
import com.typesafe.sbt.packager.DeleteDirectoryVisitor | ||
import com.typesafe.sbt.packager.permissions | ||
import org.scalatest._ | ||
import java.nio.file.{ Path, Paths, Files } | ||
import java.nio.file.attribute.PosixFilePermission._ | ||
|
||
class ZipHelperSpec extends FlatSpec with Matchers with BeforeAndAfterAll { | ||
|
||
var tmp: Path = _ | ||
|
||
override def beforeAll { | ||
tmp = Files createTempDirectory "_sbt-native-packager" | ||
} | ||
|
||
override def afterAll { | ||
Files.walkFileTree(tmp, new DeleteDirectoryVisitor) | ||
} | ||
|
||
"The zip helper" should "create a zip with a single file" in { | ||
// setup | ||
val out = tmp resolve "single.zip" | ||
val file = tmp resolve "single.txt" | ||
Files createFile file | ||
|
||
ZipHelper.zip(List(file.toFile -> "single.txt"), out.toFile) | ||
Files exists out should be(true) | ||
|
||
ZipHelper.withZipFilesystem(out.toFile) { system => | ||
val zippedFile = system getPath "single.txt" | ||
Files exists zippedFile should be(true) | ||
} | ||
} | ||
|
||
it should "create a zip with nested directories" in { | ||
// setup | ||
val out = tmp resolve "single.zip" | ||
val dir = tmp resolve "dir" | ||
val nested = dir resolve "nested" | ||
Files createDirectories nested | ||
|
||
ZipHelper.zip(List(nested.toFile -> "dir/nested"), out.toFile) | ||
|
||
ZipHelper.withZipFilesystem(out.toFile) { system => | ||
val zDir = system getPath "dir" | ||
Files exists zDir should be(true) | ||
Files isDirectory zDir should be(true) | ||
|
||
val zNested = zDir resolve "nested" | ||
Files exists zNested should be(true) | ||
Files isDirectory zNested should be(true) | ||
} | ||
} | ||
|
||
it should "create a zip with nested directories containing file" in { | ||
// setup | ||
val out = tmp resolve "single.zip" | ||
val dir = tmp resolve "dir" | ||
val file = dir resolve "file.txt" | ||
Files createDirectories dir | ||
Files createFile file | ||
|
||
ZipHelper.zip(List(file.toFile -> "dir/file.txt"), out.toFile) | ||
|
||
ZipHelper.withZipFilesystem(out.toFile) { system => | ||
val zDir = system getPath "dir" | ||
Files exists zDir should be(true) | ||
Files isDirectory zDir should be(true) | ||
|
||
val zFile = zDir resolve "file.txt" | ||
Files exists zFile should be(true) | ||
Files isDirectory zFile should be(false) | ||
} | ||
} | ||
|
||
/* | ||
* This is currently not possible. | ||
*/ | ||
it should "preserve the executable bit" ignore { | ||
// setup | ||
val out = tmp resolve "exec.zip" | ||
val exec = tmp resolve "exec" | ||
Files createFile exec | ||
Files.setPosixFilePermissions(exec, permissions("0755")) | ||
|
||
val perms = Files getPosixFilePermissions exec | ||
perms should contain only (OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_EXECUTE, OTHERS_READ, OTHERS_EXECUTE) | ||
|
||
ZipHelper.zip(List(exec.toFile -> "exec"), out.toFile) | ||
Files exists out should be(true) | ||
|
||
Files.copy(out, Paths get "/home/muki/test.zip") | ||
|
||
val unzipped = tmp resolve "unzipped-exec" | ||
ZipHelper.withZipFilesystem(out.toFile) { system => | ||
val zippedFile = system getPath "exec" | ||
Files exists zippedFile should be(true) | ||
|
||
Files.copy(zippedFile, unzipped) | ||
} | ||
|
||
// checking permissions | ||
val unzippedPerms = Files getPosixFilePermissions unzipped | ||
unzippedPerms should contain only (OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_EXECUTE, OTHERS_READ, OTHERS_EXECUTE) | ||
|
||
} | ||
|
||
} |