Improvement: Each Archive should be bound to it own relative directory. #300

Edgy opened this Issue Apr 4, 2012 · 2 comments


None yet
2 participants

Edgy commented Apr 4, 2012

I have a situation where I want to create multiple archives (ie: logs and data). However, the files I want to include are buried deep in the file system.

With the current behavior of archive, all archives are relative to my cwd. So, if I wanted to create two archives I'd need to have my cwd be root ('/') and then have something like:

archive :logs do |archive|
  archive.add 'var/logs'
archive :data do |archive|
  archive.add 'mnt/application/data'

This creates some pretty ugly tarballs, because 'mnt/application/data' and 'var/logs' are now contained in my tarballs.

Instead, I think archive should behave like this:

  Dir.chdir('/var') do
    archive :logs do |archive|
      archive.add 'logs'
  Dir.chdir('/mnt/application') do
    archive :data do |archive|
      archive.add 'data'

The archive object is aware of the cwd it was invoked in and respects this when it generates the tarball. I've made a quick monkey-patch as a proof of concept:

  class Archive
    alias_method :orig_add, :add
    def add(*args)
      cwd = Dir.getwd
      @chdir ||= cwd
      raise "Tar cannot allow multiple relative paths: #{@chdir} -> #{Dir.getpw}" unless @chdir == cwd

    alias_method :orig_perform, :perform!
    def perform!(*args)
      result = nil
      Dir.chdir(@chdir ||= Dir.getwd) do

ronalchn commented Feb 16, 2013

I want to bump this, because this is something I've run up against. This goes beyond simple aesthetics, it has a practical use as well. See I want to backup a data archive in my rails application. However, with a name starting from the root of the filesystem, the data will be stored in a directory which differs depending on where the rails application is installed.

With development and deploying multiple instances, you end up with different paths to the rails application. Sometimes, you will want to automate the restoration. However, since the path differs, it makes it very unclean.

I would like to say that instead of depending on the current directory, it would be better to pass the root directory as an option, so for example:

    archive :logs, :root => '/var' do |archive|
      archive.add 'logs'

This would have data in a single directory called 'logs' in the archive, and it would archive the files inside the /var/logs directory.

Please implement this, it would be compatible with current behaviour, because if no :root option is passed, the root of the filesystem '/' can be assumed.


ghost commented Mar 7, 2013

I like the idea of a :root option. Currently both relative paths and absolute paths may be added to an Archive.
All paths are expanded before passing to tar. Then we use the -P option so the leading / isn't stripped.
This was primarily because tar outputs a warning that it's stripping them. But, it allows you to extract the archive either relative to the directory your in - as tar will automatically strip the leading / by default - or you can use the -P option at that time to place files directly back where they originated.

For a :root option, we could simply pass the root directory to tar's -C option. Then pass tar the relative directories from .add/.exclude without expanding them. The paths within the archive would all then be relative from that :root.

So, this is on the radar.

@ghost ghost closed this in 90ead40 Mar 23, 2013

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment