Skip to content

Instantly share code, notes, and snippets.

@isaacs
Created April 23, 2017 05:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isaacs/99f2186a2caf8a16cea09f1f39625bf9 to your computer and use it in GitHub Desktop.
Save isaacs/99f2186a2caf8a16cea09f1f39625bf9 to your computer and use it in GitHub Desktop.

The goal is to mimic the command line.

For create helper methods, pass in a list of files to add to the tarball.

If a file is specified, then write out to the file. Otherwise, return the stream, which can be piped wherever.

If no cb is provided, return a Promise. Actually, just return a Promise from creation helper methods no matter what, maybe?

So, to replicate tar czf my-tarball.tgz files and folders, you'd do:

tar.c(
  {
    gzip: <true|gzip options>,
    file: 'my-tarball.tgz',
    glob: <true|glob options>
  },
  ['some', 'files', 'and', 'folders']
).then(_ => { .. tarball has been created .. })

To replicate tar cz files and folders > my-tarball.tgz, you'd do:

tar.c(
  {
    gzip: <true|gzip options>,
    glob: <true|glob options>
  },
  ['some', 'files', 'and', 'folders']
).pipe(fs.createWriteStream('my-tarball.tgz')

To replicate tar xf my-tarball.tgz you'd do:

tar.x(
  {
    file: 'my-tarball.tgz'
  }
).then(_=> { .. tarball has been dumped in cwd .. })

To replicate cat my-tarball.tgz | tar x -C some-dir --strip=1:

fs.createReadStream('my-tarball.tgz').pipe(
  tar.x({
    strip: 1,
    C: 'some-dir' // alias for cwd:'some-dir', also ok
  })
)

To replicate tar tf my-tarball.tgz, do this:

tar.t({ file: 'my-tarball.tgz' })
  .on('entry', entry => { .. do whatever with it .. })

To replicate cat my-tarball.tgz | tar t do:

fs.createReadStream('my-tarball.tgz')
  .pipe(tar.t())
  .on('entry', entry => { .. do whatever with it .. })

The arguments list to tar t and tar x specify a list of filenames to extract or list, so they're equivalent to:

{
  filter: (path, entry) => new Set(itemList).has(path)
}

To do anything synchronous, add sync: true to the options.

To filter entries, add filter: <function> to the options. Tar-creating methods call the filter with filter(path, stat). Tar-reading methods (including extraction) call the filter with filter(path, entry). The filter is called in the this-context of the stream object.

For those who aren't fans of tar's single-character command names:

tar.c === tar.create
tar.r === tar.replace (appends to archive, file is required)
tar.u === tar.update (appends if newer, file is required)
tar.x === tar.extract
tar.t === tar.list

Future enhancement idea: if @file is passed as an entry argument, and @file is a tarball, then read the entries out of it, and add them as if they were files. (This allows for filtering items out of a tarball, into a new tarball, for example.)

options todo:

C or cwd: read entries out of or extract them into the specified dir

strip or stripComponents like --strip on the tar cli

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