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

allow archive targets to eliminate top-level directory #276

Closed
easel opened this issue Jun 20, 2014 · 10 comments
Closed

allow archive targets to eliminate top-level directory #276

easel opened this issue Jun 20, 2014 · 10 comments

Comments

@easel
Copy link

easel commented Jun 20, 2014

See http://stackoverflow.com/questions/20133164/why-does-sbt-native-packager-generate-a-hardcoded-top-level-parent-directory-in for more details.

One use case. Trying to use the output from packageBin to deploy a docker file to elastic beanstalk fails because elastic beanstalk expects to find the Dockerfile in the root of the .zip file.

@muuki88
Copy link
Contributor

muuki88 commented Jun 20, 2014

I'm not quite sure about this one. So that I got everything right. The current behaviour is

unzip example-app.zip
> example-app/lib
> example-app/conf
> example-app/bin

And you expect

unzip example-app.zip
> lib
> conf
> bin

From a usability perspective I think it's not a good idea. Repackaging that script with a small bash or sbt script would be a workaround. You can also provide a pull request which makes this behavior configurable. Take a look at Archives.scala

If you are a bit patient, you can wait for the native docker support from native-packager #236

@easel
Copy link
Author

easel commented Jun 20, 2014

You're understanding the use case correctly. I'm comfortable making the change permanent, but less sure how you guys would prefer to see it configured. If you can point me in the right direction on that front I can take a shot at making a pull request.

@muuki88
Copy link
Contributor

muuki88 commented Jun 20, 2014

Sure :)

The configuration should be inside the ../packager/universal package. Defining a SettingsKey withTopLevelDirectory (if you have a better name, go ahead), which should by default be true (set this here)

This setting must be used here. So the logic should rather simple in makeZip, makeNativeZip and makeTarball

// old code
// val m2 = mappings map { case (f, p) => f -> (name + "/" + p) }
val m2 = if(withTopLevelDirectory) mappings map { case (f, p) => f -> (name + "/" + p) } else mappings

@jsuereth
Copy link
Member

This solution looks pretty good to me. Note: I think it may also have to hit the DMG support we have....

@prascuna
Copy link

Hi, any hint about how to achieve the same result, even if that means uncompressing the zip and recompressing it?

@easel
Copy link
Author

easel commented Nov 12, 2014

This is how I did it in my build.sbt:

/* Override the packageBin target to eliminate the top-level folder */
packageBin <<= (baseDirectory, packageBin in Universal, mappings in packageBin in Universal,     streams) map
  { (bd, artifactPath, mappings, s: TaskStreams) =>
    s.log.info(s"Creating $artifactPath")
    ZipHelper.zip(mappings, artifactPath)
    artifactPath
  } dependsOn stage

@muuki88
Copy link
Contributor

muuki88 commented Nov 12, 2014

thanks for sharing @easel

@prascuna
Copy link

Thanks @easel
You solution looks great, but unfortunately I'm not familiar enough with sbt to understand why your suggestion doesn't work for me (sbt 0.13 , sbt-native-packager 0.8.0). The output is the same old zip file, with top-level folder included

The solution that I'm using right now (ugly, redundant and incomplete, since it doesn't handle the tgz) is this:

packageBin in Universal := {
    val originalFileName = (packageBin in Universal).value
    val (base, ext) = originalFileName.baseAndExt
    val newFileName = file(originalFileName.getParent) / (base + "_dist." + ext)
    val extractedFiles = IO.unzip(originalFileName,file(originalFileName.getParent))
    val mappings: Set[(File, String)] = extractedFiles.map( f => (f, f.getAbsolutePath.substring(originalFileName.getParent.size + base.size + 2)))
    val binFiles = mappings.filter{ case (file, path) => path.startsWith("bin/")}
    for (f <- binFiles) f._1.setExecutable(true)
    ZipHelper.zip(mappings,newFileName)
    IO.move(newFileName, originalFileName)
    IO.delete(file(originalFileName.getParent +  "/" + originalFileName.base))
    originalFileName
}

I basically extract the zip, and compress it again, preserving the executable permissions of the bin folder

@jdeastwood
Copy link

@muuki88 Ha, I was just starting to look at implementing your suggestion above for packaging a samza job, only to find you've committed a fix! Thanks!

@prascuna doubtless you are more observant than I, but I was struggling to get @easel's solution working as well before I noticed he overwrote the top-level packageBin, not universal:packageBin as you did.

@muuki88
Copy link
Contributor

muuki88 commented Feb 14, 2015

I'll just add some docs and then I'll pull off a release hopefully this weekend :)

metasim pushed a commit to metasim/sbt-native-packager that referenced this issue Feb 15, 2015
* master:
  Update README.md
  Replace chmod call
  More comprehensive tests
  Adding documentation
  FIX sbt#276 creating directories as necessary and specify top level dir and sadly realizing that apache commons compress is still the best bet
  Adding documentation, examples and tests.
  Initial refactoring on sbt#453
  Revert "[fix sbt#472] /etc/default/<package-name> should be shell script setting envars"
  FIX sbt#489: Small fix in documentation
  Upgrading to java 7 and using posix nio API

Conflicts:
	src/main/scala/com/typesafe/sbt/packager/jdkpackager/JDKPackagerHelper.scala
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants