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

Adds transform option to api #73

Merged
merged 2 commits into from
Jul 20, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@ asar.createPackage(src, dest, function() {

Please note that there is currently *no* error handling provided!

### Transform
You can pass in a `transform` option, that is a function, which either returns
nothing, or a `stream.Transform`. The latter will be used on files that will be
in the `.asar` file to transform them (e.g. compress).

```js
var asar = require('asar');

var src = 'some/path/';
var dest = 'name.asar';

function transform(filename) {
return new CustomTransformStream()
}

asar.createPackageWithOptions(src, dest, { transform: transform }, function() {
console.log('done.');
})
```

## Using with grunt

There is also an unofficial grunt plugin to generate asar archives at [bwin/grunt-asar][grunt-asar].
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"glob": "^6.0.4",
"minimatch": "^3.0.0",
"mkdirp": "^0.5.0",
"mksnapshot": "^0.3.0"
"mksnapshot": "^0.3.0",
"tmp": "0.0.28"
},
"devDependencies": {
"coffee-script": "^1.10.0",
Expand Down
31 changes: 22 additions & 9 deletions src/asar.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module.exports.createPackageFromFiles = (src, dest, filenames, metadata, options
else
filenamesSorted = filenames

for filename in filenamesSorted
handleFile = (filename, done) ->
file = metadata[filename]
unless file
stat = fs.lstatSync filename
Expand All @@ -101,18 +101,31 @@ module.exports.createPackageFromFiles = (src, dest, filenames, metadata, options
dirName = path.relative src, path.dirname(filename)
shouldUnpack = isUnpackDir dirName, options.unpackDir
files.push filename: filename, unpack: shouldUnpack
filesystem.insertFile filename, shouldUnpack, file.stat
filesystem.insertFile filename, shouldUnpack, file, options, done
return
when 'link'
filesystem.insertLink filename, file.stat
done()

mkdirp path.dirname(dest), (error) ->
return callback(error) if error
disk.writeFilesystem dest, filesystem, files, (error) ->
insertsDone = ->
mkdirp path.dirname(dest), (error) ->
return callback(error) if error
if options.snapshot
createSnapshot src, dest, filenames, metadata, options, callback
else
callback null
disk.writeFilesystem dest, filesystem, files, metadata, (error) ->
return callback(error) if error
if options.snapshot
createSnapshot src, dest, filenames, metadata, options, callback
else
callback null

names = filenamesSorted.slice()

next = (name) ->
if !name then return insertsDone()

handleFile name, ->
next names.shift()

next names.shift()

module.exports.statFile = (archive, filename, followLinks) ->
filesystem = disk.readFilesystemSync archive
Expand Down
15 changes: 8 additions & 7 deletions src/disk.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ copyFileToSync = (dest, src, filename) ->
mkdirp.sync path.dirname(targetFile)
fs.writeFileSync targetFile, content, mode: stats.mode

writeFileListToStream = (dest, filesystem, out, list, callback) ->
writeFileListToStream = (dest, filesystem, out, list, metadata, callback) ->
if list.length is 0
out.end()
return callback null
Expand All @@ -28,15 +28,16 @@ writeFileListToStream = (dest, filesystem, out, list, callback) ->
copyFileToSync "#{dest}.unpacked", filesystem.src, filename
catch error
return callback error
writeFileListToStream dest, filesystem, out, list.slice(1), callback
writeFileListToStream dest, filesystem, out, list.slice(1), metadata, callback
else
stream = fs.createReadStream(file.filename)
tr = metadata[file.filename].transformed
stream = fs.createReadStream (if tr then tr.path else file.filename)
stream.pipe out, end: false
stream.on 'error', callback
stream.on 'end', ->
writeFileListToStream dest, filesystem, out, list.slice(1), callback
stream.pipe out, end: false
writeFileListToStream dest, filesystem, out, list.slice(1), metadata, callback

module.exports.writeFilesystem = (dest, filesystem, files, callback) ->
module.exports.writeFilesystem = (dest, filesystem, files, metadata, callback) ->
try
headerPickle = pickle.createEmpty()
headerPickle.writeString JSON.stringify(filesystem.header)
Expand All @@ -52,7 +53,7 @@ module.exports.writeFilesystem = (dest, filesystem, files, callback) ->
out.on 'error', callback
out.write sizeBuf
out.write headerBuf, ->
writeFileListToStream dest, filesystem, out, files, callback
writeFileListToStream dest, filesystem, out, files, metadata, callback

module.exports.readArchiveHeaderSync = (archive) ->
fd = fs.openSync archive, 'r'
Expand Down
45 changes: 35 additions & 10 deletions src/filesystem.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fs = require 'fs'
path = require 'path'
tmp = require 'tmp'
UINT64 = require('cuint').UINT64

class Filesystem
Expand Down Expand Up @@ -28,23 +29,47 @@ class Filesystem
node.unpacked = shouldUnpack if shouldUnpack
node.files = {}

insertFile: (p, shouldUnpack, stat) ->
insertFile: (p, shouldUnpack, file, options, callback) ->
dirNode = @searchNodeFromPath path.dirname(p)
node = @searchNodeFromPath p
if shouldUnpack or dirNode.unpacked
node.size = stat.size
node.size = file.stat.size
node.unpacked = true
callback()
return

# JavaScript can not precisely present integers >= UINT32_MAX.
if stat.size > 4294967295
throw new Error("#{p}: file size can not be larger than 4.2GB")
self = this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the => function in CoffeeScript, which handles this automatically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks I changed it!

handler = ->
size = if file.transformed then file.transformed.stat.size else file.stat.size

node.size = stat.size
node.offset = @offset.toString()
if process.platform isnt 'win32' and stat.mode & 0o100
node.executable = true
@offset.add UINT64(stat.size)
# JavaScript can not precisely present integers >= UINT32_MAX.
if size > 4294967295
throw new Error("#{p}: file size can not be larger than 4.2GB")

node.size = size
node.offset = self.offset.toString()
if process.platform isnt 'win32' and file.stat.mode & 0o100
node.executable = true
self.offset.add UINT64(size)

callback()

tr = options.transform && options.transform(p)
if tr
tmp.file (err, path) ->
return handler() if err
out = fs.createWriteStream(path)
stream = fs.createReadStream p

stream.pipe(tr).pipe(out)
tr.on 'end', ->
file.transformed = {
path,
stat: fs.lstatSync path
}
handler()
else
handler()

insertLink: (p, stat) ->
link = path.relative fs.realpathSync(@src), fs.realpathSync(p)
Expand Down
6 changes: 6 additions & 0 deletions test/api-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ os = require 'os'
asar = require '../lib/asar'
compDirs = require './util/compareDirectories'
compFiles = require './util/compareFiles'
transform = require './util/transformStream'

describe 'api', ->
it 'should create archive from directory', (done) ->
Expand All @@ -17,6 +18,11 @@ describe 'api', ->
done compFiles 'tmp/packthis-api.asar', 'test/expected/packthis.asar'
return
return
it 'should create archive from directory (with transformed files)', (done) ->
asar.createPackageWithOptions 'test/input/packthis/', 'tmp/packthis-api-transformed.asar', {transform}, (error) ->
done compFiles 'tmp/packthis-api-transformed.asar', 'test/expected/packthis-transformed.asar'
return
return
it 'should list files/dirs in archive', ->
actual = asar.listPackage('test/input/extractthis.asar').join('\n')
expected = fs.readFileSync 'test/expected/extractthis-filelist.txt', 'utf8'
Expand Down
Binary file added test/expected/packthis-transformed.asar
Binary file not shown.
20 changes: 20 additions & 0 deletions test/util/transformStream.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{ Transform } = require 'stream'
{ basename } = require 'path'

class Reverser extends Transform
constructor: ->
super()
@_data = ''

_transform: (buf, enc, cb) ->
@_data += buf
cb()

_flush: (cb) ->
txt = @_data.toString().split('').reverse().join('')
@push(txt)
cb()

module.exports = (filename) ->
if basename(filename) is 'file0.txt'
return new Reverser()