thrau / jarchivelib

A simple archiving and compression library for Java
https://github.com/thrau/jarchivelib
Apache License 2.0
198 stars 36 forks source link

Add top-level folder to archive #45

Closed gbrova closed 8 years ago

gbrova commented 8 years ago

Suppose I have the following file structure:

└── rootFolder
    ├── folder1
    │   └── someFile
    ├── folder2
    │   └── someFile
    └── folder3
        └── someFile

and I want to add folder1 and folder2 to an archive.

The following code doesn't quite work, because it will just add someFile twice (without adding the roots folder1 and folder2):

Archiver archiver = ArchiverFactory.createArchiver(ArchiveFormat.ZIP);
archiver.create("archive", dest, new File("rootFolder/folder1"), new File("rootFolder/folder2"));

produces

└── archive.zip
    └── someFile

But I'd like to obtain:

└── archive.zip
    ├── folder1
    │   └── someFile
    └── folder2
        └── someFile

Any thoughts on how to achieve this?

thrau commented 8 years ago

thanks for the report, that is indeed peculiar behavior. it's certainly not intended, i will have a look.

gbrova commented 8 years ago

Thanks for taking a look! FWIW, I'm using v0.7.1.

thrau commented 8 years ago

i remember now, that because i wanted to support absolute paths, which other archiving CLIs don't, i had to decide which parts of the given path to use as entry name within the archive.

say you pass an absolute path /path/to/some/file as source. how should the entry in the archive be named? do you use the entire path without the leading slash? or just the file name? or the first parent directory (which is what you expect)? in commons-compress this is easy, because you create entries explicitly in the archive (you have to give them a concrete name/path within the archive), which you then copy stream contents into.

i originally intended for cases like archiver.create("archive", new File("rootFolder")) not to create the rootFolder as part of your archive, but only the subfolders, because this is the most common use-case, and having the rootFolder is most likely superfluous.

i see that this is a problem in your case (especially if you have files with the same name). i could of course just change the behavior of the create method to include the name of the directory, as described in your case, but this would be a major change and could break other people's code.

one could add a new method to the archiver interface that lets you parameterize this, but i don't know how much work that turns out to be.

gbrova commented 8 years ago

Thanks for the explanation, I definitely see where you're coming from - it makes sense to not create the root folder a lot of the time, especially if it's the only entry in the varargs list.

I still think the current behavior is confusing if there are multiple entries, because the resulting archive will change the file structure (and potentially also lose data, if files have the same name like in this example).

Another option to consider is to overload create to distinguish between the two cases:

File create(String archive, File destination, File source) throws IOException;       // current behavior
File create(String archive, File destination, File... sources) throws IOException;   // preserve top-level folder

This doesn't break existing code with only one source. It does change the behavior for calls with multiple sources, but it's your call whether that's bad or good (i.e. whether to treat current multi-source behavior as a bug).

Either way it seems like the way forward is to add a new method (whether it should override create in this way is secondary). I'm happy to try and put together a PR some time this week - let me know if that would be useful.

thrau commented 8 years ago

thanks for the contribution

gbrova commented 8 years ago

Cheers!

On Sun, Nov 22, 2015 at 3:04 PM Thomas Rausch notifications@github.com wrote:

thanks for the contribution

— Reply to this email directly or view it on GitHub https://github.com/thrau/jarchivelib/issues/45#issuecomment-158765391.