From ec2b7f4bd72458405ad82921ccca0f101ec50604 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 31 Jan 2026 15:08:00 -0800 Subject: [PATCH 1/6] Machine decaf source code with Coffeescript 1.x tooling --- src/ls-archive-cli.js | 57 +++++++ src/ls-archive.js | 388 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 src/ls-archive-cli.js create mode 100644 src/ls-archive.js diff --git a/src/ls-archive-cli.js b/src/ls-archive-cli.js new file mode 100644 index 0000000..9a2456a --- /dev/null +++ b/src/ls-archive-cli.js @@ -0,0 +1,57 @@ +var archive, async, colors, optimist, path; + +path = require('path'); + +async = require('async'); + +colors = require('colors'); + +optimist = require('optimist'); + +archive = require('./ls-archive'); + +module.exports = function() { + var cli, files, queue; + cli = optimist.usage(`Usage: lsa [file ...] + +List the files and folders inside an archive file. + +Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files.`).describe('colors', 'Enable colored output').default('colors', true).boolean('colors').describe('help', 'Show this message').alias('h', 'help').demand(1); + if (cli.argv.help) { + cli.showHelp(); + return; + } + if (!cli.argv.colors) { + colors.setTheme({ + cyan: 'stripColors', + red: 'stripColors' + }); + } + queue = async.queue(function(archivePath, callback) { + return (function(archivePath) { + return archive.list(archivePath, function(error, files) { + var file, i, index, len, prefix; + if (error != null) { + console.error(`Error reading: ${archivePath}`.red); + } else { + console.log(`${archivePath.cyan} (${files.length})`); + for (index = i = 0, len = files.length; i < len; index = ++i) { + file = files[index]; + if (index === files.length - 1) { + prefix = '\u2514\u2500\u2500 '; + } else { + prefix = '\u251C\u2500\u2500 '; + } + console.log(`${prefix}${file.getPath()}`); + } + console.log(); + } + return callback(); + }); + })(archivePath); + }); + files = cli.argv._; + return files.forEach(function(file) { + return queue.push(path.resolve(process.cwd(), file)); + }); +}; diff --git a/src/ls-archive.js b/src/ls-archive.js new file mode 100644 index 0000000..2bd56b3 --- /dev/null +++ b/src/ls-archive.js @@ -0,0 +1,388 @@ +var ArchiveEntry, convertToTree, findEntryWithName, fs, isBzipPath, isGzipPath, isTarPath, isZipPath, listBzip, listGzip, listTar, listTarStream, listZip, path, readEntry, readFileFromBzip, readFileFromGzip, readFileFromTar, readFileFromTarStream, readFileFromZip, util, wrapCallback; + +fs = require('fs'); + +path = require('path'); + +util = require('util'); + +ArchiveEntry = class ArchiveEntry { + constructor(path1, type) { + this.path = path1; + this.type = type; + if (this.isDirectory()) { + this.children = []; + } + } + + add(entry) { + var child, name, segments; + if (!this.isParentOf(entry)) { + return false; + } + segments = entry.getPath().substring(this.getPath().length + 1).split(path.sep); + if (segments.length === 0) { + return false; + } + if (segments.length === 1) { + this.children.push(entry); + return true; + } else { + name = segments[0]; + child = findEntryWithName(this.children, name); + if (child == null) { + child = new ArchiveEntry(`${this.getPath()}${path.sep}${name}`, 5); + this.children.push(child); + } + if (child.isDirectory()) { + return child.add(entry); + } else { + return false; + } + } + } + + isParentOf(entry) { + return this.isDirectory() && entry.getPath().indexOf(`${this.getPath()}${path.sep}`) === 0; + } + + getPath() { + return this.path; + } + + getName() { + return this.name != null ? this.name : this.name = path.basename(this.path); + } + + isFile() { + return this.type === 0; + } + + isDirectory() { + return this.type === 5; + } + + isSymbolicLink() { + return this.type === 2; + } + + toString() { + return this.getPath(); + } + +}; + +findEntryWithName = function(entries, name) { + var entry, i, len; + for (i = 0, len = entries.length; i < len; i++) { + entry = entries[i]; + if (name === entry.getName()) { + return entry; + } + } +}; + +convertToTree = function(entries) { + var entry, i, len, name, parent, rootEntries, segments; + rootEntries = []; + for (i = 0, len = entries.length; i < len; i++) { + entry = entries[i]; + segments = entry.getPath().split(path.sep); + if (segments.length === 1) { + rootEntries.push(entry); + } else { + name = segments[0]; + parent = findEntryWithName(rootEntries, name); + if (parent == null) { + parent = new ArchiveEntry(name, 5); + rootEntries.push(parent); + } + parent.add(entry); + } + } + return rootEntries; +}; + +wrapCallback = function(callback) { + var called; + called = false; + return function(error, data) { + if (!called) { + if ((error != null) && !util.isError(error)) { + error = new Error(error); + } + called = true; + return callback(error, data); + } + }; +}; + +listZip = function(archivePath, options, callback) { + var entries, yauzl; + yauzl = require('yauzl'); + entries = []; + return yauzl.open(archivePath, { + lazyEntries: true + }, function(error, zipFile) { + if (error) { + return callback(error); + } + zipFile.readEntry(); + zipFile.on('error', callback); + zipFile.on('entry', function(entry) { + var entryPath, entryType; + if (entry.fileName.slice(-1) === '/') { + entryPath = entry.fileName.slice(0, -1); + entryType = 5; + } else { + entryPath = entry.fileName; + entryType = 0; + } + entryPath = entryPath.replace(/\//g, path.sep); + entries.push(new ArchiveEntry(entryPath, entryType)); + return zipFile.readEntry(); + }); + return zipFile.on('end', function() { + if (options.tree) { + entries = convertToTree(entries); + } + return callback(null, entries); + }); + }); +}; + +listGzip = function(archivePath, options, callback) { + var fileStream, gzipStream, zlib; + zlib = require('zlib'); + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + gzipStream = fileStream.pipe(zlib.createGunzip()); + gzipStream.on('error', callback); + return listTarStream(gzipStream, options, callback); +}; + +listBzip = function(archivePath, options, callback) { + var bzip, bzipStream, fileStream; + bzip = require('unbzip2-stream'); + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + bzipStream = fileStream.pipe(bzip()); + bzipStream.on('error', callback); + return listTarStream(bzipStream, options, callback); +}; + +listTar = function(archivePath, options, callback) { + var fileStream; + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + return listTarStream(fileStream, options, callback); +}; + +listTarStream = function(inputStream, options, callback) { + var entries, tarStream; + entries = []; + tarStream = inputStream.pipe(require('tar').Parse()); + tarStream.on('error', callback); + tarStream.on('entry', function(entry) { + var entryPath, entryType; + if (entry.props.path.slice(-1) === '/') { + entryPath = entry.props.path.slice(0, -1); + } else { + entryPath = entry.props.path; + } + entryType = parseInt(entry.props.type); + entryPath = entryPath.replace(/\//g, path.sep); + return entries.push(new ArchiveEntry(entryPath, entryType)); + }); + return tarStream.on('end', function() { + if (options.tree) { + entries = convertToTree(entries); + } + return callback(null, entries); + }); +}; + +readFileFromZip = function(archivePath, filePath, callback) { + var yauzl; + yauzl = require('yauzl'); + return yauzl.open(archivePath, { + lazyEntries: true + }, function(error, zipFile) { + if (error) { + return callback(error); + } + zipFile.readEntry(); + zipFile.on('error', callback); + zipFile.on('end', function() { + return callback(`${filePath} does not exist in the archive: ${archivePath}`); + }); + return zipFile.on('entry', function(entry) { + if (filePath !== entry.fileName.replace(/\//g, path.sep)) { + return zipFile.readEntry(); + } + if (filePath.slice(-1) !== path.sep) { + return zipFile.openReadStream(entry, function(error, entryStream) { + if (error) { + return callback(error); + } + return readEntry(entryStream, callback); + }); + } else { + return callback(`${filePath} is not a normal file in the archive: ${archivePath}`); + } + }); + }); +}; + +readFileFromGzip = function(archivePath, filePath, callback) { + var fileStream, gzipStream; + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + gzipStream = fileStream.pipe(require('zlib').createGunzip()); + gzipStream.on('error', callback); + gzipStream.on('end', function() { + return callback(`${filePath} does not exist in the archive: ${archivePath}`); + }); + return readFileFromTarStream(gzipStream, archivePath, filePath, callback); +}; + +readFileFromBzip = function(archivePath, filePath, callback) { + var bzipStream, fileStream; + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + bzipStream = fileStream.pipe(require('unbzip2-stream')()); + bzipStream.on('error', callback); + bzipStream.on('end', function() { + return callback(`${filePath} does not exist in the archive: ${archivePath}`); + }); + return readFileFromTarStream(bzipStream, archivePath, filePath, callback); +}; + +readFileFromTar = function(archivePath, filePath, callback) { + var fileStream; + fileStream = fs.createReadStream(archivePath); + fileStream.on('error', callback); + fileStream.on('end', function() { + return callback(`${filePath} does not exist in the archive: ${archivePath}`); + }); + return readFileFromTarStream(fileStream, archivePath, filePath, callback); +}; + +readFileFromTarStream = function(inputStream, archivePath, filePath, callback) { + var tar, tarStream; + tar = require('tar'); + tarStream = inputStream.pipe(tar.Parse()); + tarStream.on('error', callback); + return tarStream.on('entry', function(entry) { + if (filePath !== entry.props.path.replace(/\//g, path.sep)) { + return; + } + if (entry.props.type === '0') { + return readEntry(entry, callback); + } else { + return callback(`${filePath} is not a normal file in the archive: ${archivePath}`); + } + }); +}; + +readEntry = function(entry, callback) { + var contents; + contents = []; + entry.on('data', function(data) { + return contents.push(data); + }); + return entry.on('end', function() { + return callback(null, Buffer.concat(contents)); + }); +}; + +isTarPath = function(archivePath) { + return path.extname(archivePath) === '.tar'; +}; + +isZipPath = function(archivePath) { + var extension; + extension = path.extname(archivePath); + return extension === '.epub' || extension === '.jar' || extension === '.love' || extension === '.war' || extension === '.zip' || extension === '.egg' || extension === '.whl' || extension === '.xpi' || extension === '.nupkg'; +}; + +isGzipPath = function(archivePath) { + return path.extname(archivePath) === '.tgz' || path.extname(path.basename(archivePath, '.gz')) === '.tar'; +}; + +isBzipPath = function(archivePath) { + return path.extname(archivePath) === '.tbz' || path.extname(archivePath) === '.tbz2' || path.extname(path.basename(archivePath, '.bz2')) === '.tar'; +}; + +module.exports = { + isPathSupported: function(archivePath) { + if (!archivePath) { + return false; + } + return isTarPath(archivePath) || isZipPath(archivePath) || isGzipPath(archivePath) || isBzipPath(archivePath); + }, + list: function(archivePath, options = {}, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (isTarPath(archivePath)) { + listTar(archivePath, options, wrapCallback(callback)); + } else if (isGzipPath(archivePath)) { + listGzip(archivePath, options, wrapCallback(callback)); + } else if (isBzipPath(archivePath)) { + listBzip(archivePath, options, wrapCallback(callback)); + } else if (isZipPath(archivePath)) { + listZip(archivePath, options, wrapCallback(callback)); + } else { + callback(new Error(`'${path.extname(archivePath)}' files are not supported`)); + } + return void 0; + }, + readFile: function(archivePath, filePath, callback) { + if (isTarPath(archivePath)) { + readFileFromTar(archivePath, filePath, wrapCallback(callback)); + } else if (isGzipPath(archivePath)) { + readFileFromGzip(archivePath, filePath, wrapCallback(callback)); + } else if (isBzipPath(archivePath)) { + readFileFromBzip(archivePath, filePath, wrapCallback(callback)); + } else if (isZipPath(archivePath)) { + readFileFromZip(archivePath, filePath, wrapCallback(callback)); + } else { + callback(new Error(`'${path.extname(archivePath)}' files are not supported`)); + } + return void 0; + }, + readGzip: function(gzipArchivePath, callback) { + var chunks, fileStream, gzipStream, zlib; + callback = wrapCallback(callback); + zlib = require('zlib'); + fileStream = fs.createReadStream(gzipArchivePath); + fileStream.on('error', callback); + gzipStream = fileStream.pipe(zlib.createGunzip()); + gzipStream.on('error', callback); + chunks = []; + gzipStream.on('data', function(chunk) { + return chunks.push(chunk); + }); + return gzipStream.on('end', function() { + return callback(null, Buffer.concat(chunks)); + }); + }, + readBzip: function(bzipArchivePath, callback) { + var bzip, bzipStream, chunks, fileStream; + callback = wrapCallback(callback); + bzip = require('unbzip2-stream'); + fileStream = fs.createReadStream(bzipArchivePath); + fileStream.on('error', callback); + bzipStream = fileStream.pipe(bzip()); + bzipStream.on('error', callback); + chunks = []; + bzipStream.on('data', function(chunk) { + return chunks.push(chunk); + }); + return bzipStream.on('end', function() { + return callback(null, Buffer.concat(chunks)); + }); + } +}; From 62c19acc18829d30227953c91c5cdd288f8cbaf9 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 31 Jan 2026 15:08:47 -0800 Subject: [PATCH 2/6] Delete coffee files from source --- src/ls-archive-cli.coffee | 45 ------- src/ls-archive.coffee | 266 -------------------------------------- 2 files changed, 311 deletions(-) delete mode 100644 src/ls-archive-cli.coffee delete mode 100644 src/ls-archive.coffee diff --git a/src/ls-archive-cli.coffee b/src/ls-archive-cli.coffee deleted file mode 100644 index 50127b8..0000000 --- a/src/ls-archive-cli.coffee +++ /dev/null @@ -1,45 +0,0 @@ -path = require 'path' -async = require 'async' -colors = require 'colors' -optimist = require 'optimist' -archive = require './ls-archive' - -module.exports = -> - cli = optimist.usage( """ - Usage: lsa [file ...] - - List the files and folders inside an archive file. - - Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files. - """) - .describe('colors', 'Enable colored output').default('colors', true).boolean('colors') - .describe('help', 'Show this message').alias('h', 'help') - .demand(1) - - if cli.argv.help - cli.showHelp() - return - - unless cli.argv.colors - colors.setTheme - cyan: 'stripColors' - red: 'stripColors' - - queue = async.queue (archivePath, callback) -> - do (archivePath) -> - archive.list archivePath, (error, files) -> - if error? - console.error("Error reading: #{archivePath}".red) - else - console.log("#{archivePath.cyan} (#{files.length})") - for file, index in files - if index is files.length - 1 - prefix = '\u2514\u2500\u2500 ' - else - prefix = '\u251C\u2500\u2500 ' - console.log "#{prefix}#{file.getPath()}" - console.log() - callback() - - files = cli.argv._ - files.forEach (file) -> queue.push(path.resolve(process.cwd(), file)) diff --git a/src/ls-archive.coffee b/src/ls-archive.coffee deleted file mode 100644 index 4421767..0000000 --- a/src/ls-archive.coffee +++ /dev/null @@ -1,266 +0,0 @@ -fs = require 'fs' -path = require 'path' -util = require 'util' - -class ArchiveEntry - constructor: (@path, @type) -> - @children = [] if @isDirectory() - - add: (entry) -> - return false unless @isParentOf(entry) - - segments = entry.getPath().substring(@getPath().length + 1).split(path.sep) - return false if segments.length is 0 - - if segments.length is 1 - @children.push(entry) - true - else - name = segments[0] - child = findEntryWithName(@children, name) - unless child? - child = new ArchiveEntry("#{@getPath()}#{path.sep}#{name}", 5) - @children.push(child) - if child.isDirectory() - child.add(entry) - else - false - - isParentOf: (entry) -> - @isDirectory() and entry.getPath().indexOf("#{@getPath()}#{path.sep}") is 0 - - getPath: -> @path - getName: -> @name ?= path.basename(@path) - isFile: -> @type is 0 - isDirectory: -> @type is 5 - isSymbolicLink: -> @type is 2 - toString: -> @getPath() - -findEntryWithName = (entries, name) -> - return entry for entry in entries when name is entry.getName() - -convertToTree = (entries) -> - rootEntries = [] - for entry in entries - segments = entry.getPath().split(path.sep) - if segments.length is 1 - rootEntries.push(entry) - else - name = segments[0] - parent = findEntryWithName(rootEntries, name) - unless parent? - parent = new ArchiveEntry(name, 5) - rootEntries.push(parent) - parent.add(entry) - rootEntries - -wrapCallback = (callback) -> - called = false - (error, data) -> - unless called - error = new Error(error) if error? and not util.isError(error) - called = true - callback(error, data) - -listZip = (archivePath, options, callback) -> - yauzl = require 'yauzl' - entries = [] - yauzl.open archivePath, {lazyEntries: true}, (error, zipFile) -> - return callback(error) if error - zipFile.readEntry() - zipFile.on 'error', callback - zipFile.on 'entry', (entry) -> - if entry.fileName[-1..] is '/' - entryPath = entry.fileName[0...-1] - entryType = 5 - else - entryPath = entry.fileName - entryType = 0 - entryPath = entryPath.replace(/\//g, path.sep) - entries.push(new ArchiveEntry(entryPath, entryType)) - zipFile.readEntry() - zipFile.on 'end', -> - entries = convertToTree(entries) if options.tree - callback(null, entries) - -listGzip = (archivePath, options, callback) -> - zlib = require 'zlib' - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - gzipStream = fileStream.pipe(zlib.createGunzip()) - gzipStream.on 'error', callback - listTarStream(gzipStream, options, callback) - -listBzip = (archivePath, options, callback) -> - bzip = require 'unbzip2-stream' - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - bzipStream = fileStream.pipe(bzip()) - bzipStream.on 'error', callback - listTarStream(bzipStream, options, callback) - -listTar = (archivePath, options, callback) -> - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - listTarStream(fileStream, options, callback) - -listTarStream = (inputStream, options, callback) -> - entries = [] - tarStream = inputStream.pipe(require('tar').Parse()) - tarStream.on 'error', callback - tarStream.on 'entry', (entry) -> - if entry.props.path[-1..] is '/' - entryPath = entry.props.path[0...-1] - else - entryPath = entry.props.path - entryType = parseInt(entry.props.type) - entryPath = entryPath.replace(/\//g, path.sep) - entries.push(new ArchiveEntry(entryPath, entryType)) - tarStream.on 'end', -> - entries = convertToTree(entries) if options.tree - callback(null, entries) - -readFileFromZip = (archivePath, filePath, callback) -> - yauzl = require 'yauzl' - yauzl.open archivePath, {lazyEntries: true}, (error, zipFile) -> - return callback(error) if error - zipFile.readEntry() - zipFile.on 'error', callback - zipFile.on 'end', -> - callback("#{filePath} does not exist in the archive: #{archivePath}") - zipFile.on 'entry', (entry) -> - return zipFile.readEntry() unless filePath is entry.fileName.replace(/\//g, path.sep) - - if filePath[-1..] isnt path.sep - zipFile.openReadStream entry, (error, entryStream) -> - return callback(error) if error - readEntry(entryStream, callback) - else - callback("#{filePath} is not a normal file in the archive: #{archivePath}") - -readFileFromGzip = (archivePath, filePath, callback) -> - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - gzipStream = fileStream.pipe(require('zlib').createGunzip()) - gzipStream.on 'error', callback - gzipStream.on 'end', -> - callback("#{filePath} does not exist in the archive: #{archivePath}") - readFileFromTarStream(gzipStream, archivePath, filePath, callback) - -readFileFromBzip = (archivePath, filePath, callback) -> - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - bzipStream = fileStream.pipe(require('unbzip2-stream')()) - bzipStream.on 'error', callback - bzipStream.on 'end', -> - callback("#{filePath} does not exist in the archive: #{archivePath}") - readFileFromTarStream(bzipStream, archivePath, filePath, callback) - -readFileFromTar = (archivePath, filePath, callback) -> - fileStream = fs.createReadStream(archivePath) - fileStream.on 'error', callback - fileStream.on 'end', -> - callback("#{filePath} does not exist in the archive: #{archivePath}") - readFileFromTarStream(fileStream, archivePath, filePath, callback) - -readFileFromTarStream = (inputStream, archivePath, filePath, callback) -> - tar = require 'tar' - tarStream = inputStream.pipe(tar.Parse()) - - tarStream.on 'error', callback - tarStream.on 'entry', (entry) -> - return unless filePath is entry.props.path.replace(/\//g, path.sep) - - if entry.props.type is '0' - readEntry(entry, callback) - else - callback("#{filePath} is not a normal file in the archive: #{archivePath}") - -readEntry = (entry, callback) -> - contents = [] - entry.on 'data', (data) -> contents.push(data) - entry.on 'end', -> callback(null, Buffer.concat(contents)) - -isTarPath = (archivePath) -> - path.extname(archivePath) is '.tar' - -isZipPath = (archivePath) -> - extension = path.extname(archivePath) - extension in ['.epub', '.jar', '.love', '.war', '.zip', '.egg', '.whl', '.xpi', '.nupkg'] - -isGzipPath = (archivePath) -> - path.extname(archivePath) is '.tgz' or - path.extname(path.basename(archivePath, '.gz')) is '.tar' - -isBzipPath = (archivePath) -> - path.extname(archivePath) is '.tbz' or - path.extname(archivePath) is '.tbz2' or - path.extname(path.basename(archivePath, '.bz2')) is '.tar' - -module.exports = - isPathSupported: (archivePath) -> - return false unless archivePath - isTarPath(archivePath) or - isZipPath(archivePath) or - isGzipPath(archivePath) or - isBzipPath(archivePath) - - list: (archivePath, options={}, callback) -> - if typeof options is 'function' - callback = options - options = {} - - if isTarPath(archivePath) - listTar(archivePath, options, wrapCallback(callback)) - else if isGzipPath(archivePath) - listGzip(archivePath, options, wrapCallback(callback)) - else if isBzipPath(archivePath) - listBzip(archivePath, options, wrapCallback(callback)) - else if isZipPath(archivePath) - listZip(archivePath, options, wrapCallback(callback)) - else - callback(new Error("'#{path.extname(archivePath)}' files are not supported")) - undefined - - readFile: (archivePath, filePath, callback) -> - if isTarPath(archivePath) - readFileFromTar(archivePath, filePath, wrapCallback(callback)) - else if isGzipPath(archivePath) - readFileFromGzip(archivePath, filePath, wrapCallback(callback)) - else if isBzipPath(archivePath) - readFileFromBzip(archivePath, filePath, wrapCallback(callback)) - else if isZipPath(archivePath) - readFileFromZip(archivePath, filePath, wrapCallback(callback)) - else - callback(new Error("'#{path.extname(archivePath)}' files are not supported")) - undefined - - readGzip: (gzipArchivePath, callback) -> - callback = wrapCallback(callback) - - zlib = require 'zlib' - fileStream = fs.createReadStream(gzipArchivePath) - fileStream.on 'error', callback - gzipStream = fileStream.pipe(zlib.createGunzip()) - gzipStream.on 'error', callback - - chunks = [] - gzipStream.on 'data', (chunk) -> - chunks.push(chunk) - gzipStream.on 'end', -> - callback(null, Buffer.concat(chunks)) - - readBzip: (bzipArchivePath, callback) -> - callback = wrapCallback(callback) - - bzip = require 'unbzip2-stream' - fileStream = fs.createReadStream(bzipArchivePath) - fileStream.on 'error', callback - bzipStream = fileStream.pipe(bzip()) - bzipStream.on 'error', callback - - chunks = [] - bzipStream.on 'data', (chunk) -> - chunks.push(chunk) - bzipStream.on 'end', -> - callback(null, Buffer.concat(chunks)) From 0098befd30d244269f694b00137b5f408cf45f4e Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 31 Jan 2026 15:15:30 -0800 Subject: [PATCH 3/6] Manual decaf `ls-archive-cli` --- src/ls-archive-cli.js | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/ls-archive-cli.js b/src/ls-archive-cli.js index 9a2456a..cebc407 100644 --- a/src/ls-archive-cli.js +++ b/src/ls-archive-cli.js @@ -1,22 +1,22 @@ -var archive, async, colors, optimist, path; - -path = require('path'); - -async = require('async'); - -colors = require('colors'); - -optimist = require('optimist'); - -archive = require('./ls-archive'); +const path = require("path"); +const async = require("async"); +const colors = require("colors"); +const optimist = require("optimist"); +const archive = require("./ls-archive.js"); module.exports = function() { - var cli, files, queue; - cli = optimist.usage(`Usage: lsa [file ...] + const cli = optimist.usage(`Usage: lsa [file ...] List the files and folders inside an archive file. -Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files.`).describe('colors', 'Enable colored output').default('colors', true).boolean('colors').describe('help', 'Show this message').alias('h', 'help').demand(1); +Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files.`) + .describe('colors', 'Enable colored output') + .default('colors', true) + .boolean('colors') + .describe('help', 'Show this message') + .alias('h', 'help') + .demand(1); + if (cli.argv.help) { cli.showHelp(); return; @@ -27,30 +27,33 @@ Supports .zip, .tar, .tar.gz, .tgz, .tar.bz2, .tbz and .tbz2 files.`).describe(' red: 'stripColors' }); } - queue = async.queue(function(archivePath, callback) { + let queue = async.queue(function(archivePath, callback) { return (function(archivePath) { return archive.list(archivePath, function(error, files) { - var file, i, index, len, prefix; if (error != null) { console.error(`Error reading: ${archivePath}`.red); } else { + console.log(`${archivePath.cyan} (${files.length})`); - for (index = i = 0, len = files.length; i < len; index = ++i) { - file = files[index]; - if (index === files.length - 1) { + for (let i = 0; i < files.length; i++) { + let file = files[i]; + let prefix; + if (i === files.length - 1) { prefix = '\u2514\u2500\u2500 '; } else { prefix = '\u251C\u2500\u2500 '; } console.log(`${prefix}${file.getPath()}`); } + console.log(); } return callback(); }); })(archivePath); }); - files = cli.argv._; + + let files = cli.argv._; return files.forEach(function(file) { return queue.push(path.resolve(process.cwd(), file)); }); From 0cdb96fb2e027161054075f72401c6a7cdf2a132 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 31 Jan 2026 17:49:05 -0800 Subject: [PATCH 4/6] Manual decaf `ls-archive.js` --- src/ls-archive.js | 278 ++++++++++++++++++++++------------------------ 1 file changed, 135 insertions(+), 143 deletions(-) diff --git a/src/ls-archive.js b/src/ls-archive.js index 2bd56b3..3a12704 100644 --- a/src/ls-archive.js +++ b/src/ls-archive.js @@ -1,12 +1,8 @@ -var ArchiveEntry, convertToTree, findEntryWithName, fs, isBzipPath, isGzipPath, isTarPath, isZipPath, listBzip, listGzip, listTar, listTarStream, listZip, path, readEntry, readFileFromBzip, readFileFromGzip, readFileFromTar, readFileFromTarStream, readFileFromZip, util, wrapCallback; +const fs = require("fs"); +const path = require("path"); +const util = require("util"); -fs = require('fs'); - -path = require('path'); - -util = require('util'); - -ArchiveEntry = class ArchiveEntry { +class ArchiveEntry { constructor(path1, type) { this.path = path1; this.type = type; @@ -16,11 +12,10 @@ ArchiveEntry = class ArchiveEntry { } add(entry) { - var child, name, segments; if (!this.isParentOf(entry)) { return false; } - segments = entry.getPath().substring(this.getPath().length + 1).split(path.sep); + let segments = entry.getPath().substring(this.getPath().length + 1).split(path.sep); if (segments.length === 0) { return false; } @@ -28,8 +23,8 @@ ArchiveEntry = class ArchiveEntry { this.children.push(entry); return true; } else { - name = segments[0]; - child = findEntryWithName(this.children, name); + let name = segments[0]; + let child = findEntryWithName(this.children, name); if (child == null) { child = new ArchiveEntry(`${this.getPath()}${path.sep}${name}`, 5); this.children.push(child); @@ -70,29 +65,29 @@ ArchiveEntry = class ArchiveEntry { return this.getPath(); } -}; +} -findEntryWithName = function(entries, name) { - var entry, i, len; - for (i = 0, len = entries.length; i < len; i++) { - entry = entries[i]; +function findEntryWithName(entries, name) { + for (let i = 0; i < entries.length; i++) { + let entry = entries[i]; if (name === entry.getName()) { return entry; } } -}; +} + +function convertToTree(entries) { + let rootEntries = []; + + for (let i = 0; i < entries.length; i++) { + let entry = entries[i]; + let segments = entry.getPath().split(path.sep); -convertToTree = function(entries) { - var entry, i, len, name, parent, rootEntries, segments; - rootEntries = []; - for (i = 0, len = entries.length; i < len; i++) { - entry = entries[i]; - segments = entry.getPath().split(path.sep); if (segments.length === 1) { rootEntries.push(entry); } else { - name = segments[0]; - parent = findEntryWithName(rootEntries, name); + let name = segments[0]; + let parent = findEntryWithName(rootEntries, name); if (parent == null) { parent = new ArchiveEntry(name, 5); rootEntries.push(parent); @@ -101,26 +96,25 @@ convertToTree = function(entries) { } } return rootEntries; -}; +} + +function wrapCallback(cb) { + let called = false; -wrapCallback = function(callback) { - var called; - called = false; return function(error, data) { if (!called) { if ((error != null) && !util.isError(error)) { error = new Error(error); } called = true; - return callback(error, data); + return cb(error, data); } }; -}; +} -listZip = function(archivePath, options, callback) { - var entries, yauzl; - yauzl = require('yauzl'); - entries = []; +function listZip(archivePath, options, callback) { + const yauzl = require("yauzl"); + let entries = []; return yauzl.open(archivePath, { lazyEntries: true }, function(error, zipFile) { @@ -149,62 +143,63 @@ listZip = function(archivePath, options, callback) { return callback(null, entries); }); }); -}; +} + +function listGzip(archivePath, options, callback) { + const zlib = require("zlib"); + let fileStream = fs.createReadStream(archivePath); + fileStream.on("error", callback); + + let gzipStream = fileStream.pipe(zlib.createGunzip()); + gzipStream.on("error", callback); -listGzip = function(archivePath, options, callback) { - var fileStream, gzipStream, zlib; - zlib = require('zlib'); - fileStream = fs.createReadStream(archivePath); - fileStream.on('error', callback); - gzipStream = fileStream.pipe(zlib.createGunzip()); - gzipStream.on('error', callback); return listTarStream(gzipStream, options, callback); -}; +} + +function listBzip(archivePath, options, callback) { + const bzip = require("unbzip2-stream"); + + let fileStream = fs.createReadStream(archivePath); + fileStream.on("error", callback); + + let bzipStream = fileStream.pipe(bzip()); + bzipStream.on("error", callback); -listBzip = function(archivePath, options, callback) { - var bzip, bzipStream, fileStream; - bzip = require('unbzip2-stream'); - fileStream = fs.createReadStream(archivePath); - fileStream.on('error', callback); - bzipStream = fileStream.pipe(bzip()); - bzipStream.on('error', callback); return listTarStream(bzipStream, options, callback); -}; +} -listTar = function(archivePath, options, callback) { - var fileStream; - fileStream = fs.createReadStream(archivePath); - fileStream.on('error', callback); - return listTarStream(fileStream, options, callback); -}; +function listTar(archivePath, options, callback) { + let fileStream = fs.createReadStream(archivePath); + fileStream.on("error", callback); -listTarStream = function(inputStream, options, callback) { - var entries, tarStream; - entries = []; - tarStream = inputStream.pipe(require('tar').Parse()); - tarStream.on('error', callback); - tarStream.on('entry', function(entry) { - var entryPath, entryType; - if (entry.props.path.slice(-1) === '/') { + return listTarStream(fileStream, options, callback); +} + +function listTarStream(inputStream, options, callback) { + let entries = []; + let tarStream = inputStream.pipe(require("tar").Parse()); + tarStream.on("error", callback); + tarStream.on("entry", function(entry) { + let entryPath; + if (entry.props.path.slice(-1) === "/") { entryPath = entry.props.path.slice(0, -1); } else { entryPath = entry.props.path; } - entryType = parseInt(entry.props.type); + let entryType = parseInt(entry.props.type); entryPath = entryPath.replace(/\//g, path.sep); return entries.push(new ArchiveEntry(entryPath, entryType)); }); - return tarStream.on('end', function() { + return tarStream.on("end", function () { if (options.tree) { entries = convertToTree(entries); } return callback(null, entries); }); -}; +} -readFileFromZip = function(archivePath, filePath, callback) { - var yauzl; - yauzl = require('yauzl'); +function readFileFromZip(archivePath, filePath, callback) { + const yauzl = require("yauzl"); return yauzl.open(archivePath, { lazyEntries: true }, function(error, zipFile) { @@ -232,87 +227,85 @@ readFileFromZip = function(archivePath, filePath, callback) { } }); }); -}; - -readFileFromGzip = function(archivePath, filePath, callback) { - var fileStream, gzipStream; - fileStream = fs.createReadStream(archivePath); - fileStream.on('error', callback); - gzipStream = fileStream.pipe(require('zlib').createGunzip()); - gzipStream.on('error', callback); - gzipStream.on('end', function() { +} + +function readFileFromGzip(archivePath, filePath, callback) { + let fileStream = fs.createReadStream(archivePath); + fileStream.on("error", callback); + let gzipStream = fileStream.pipe(require("zlib").createGunzip()); + gzipStream.on("error", callback); + gzipStream.on("end", function() { return callback(`${filePath} does not exist in the archive: ${archivePath}`); }); return readFileFromTarStream(gzipStream, archivePath, filePath, callback); -}; - -readFileFromBzip = function(archivePath, filePath, callback) { - var bzipStream, fileStream; - fileStream = fs.createReadStream(archivePath); - fileStream.on('error', callback); - bzipStream = fileStream.pipe(require('unbzip2-stream')()); - bzipStream.on('error', callback); - bzipStream.on('end', function() { +} + +function readFileFromBzip(archivePath, filePath, callback) { + let fileStream = fs.createReadStream(archivePath); + fileStream.on("error", callback); + let bzipStream = fileStream.pipe(require("unbzip2-stream")()); + bzipStream.on("error", callback); + bzipStream.on("end", function() { return callback(`${filePath} does not exist in the archive: ${archivePath}`); }); return readFileFromTarStream(bzipStream, archivePath, filePath, callback); -}; +} -readFileFromTar = function(archivePath, filePath, callback) { - var fileStream; - fileStream = fs.createReadStream(archivePath); +function readFileFromTar(archivePath, filePath, callback) { + let fileStream = fs.createReadStream(archivePath); fileStream.on('error', callback); fileStream.on('end', function() { return callback(`${filePath} does not exist in the archive: ${archivePath}`); }); return readFileFromTarStream(fileStream, archivePath, filePath, callback); -}; +} -readFileFromTarStream = function(inputStream, archivePath, filePath, callback) { - var tar, tarStream; - tar = require('tar'); - tarStream = inputStream.pipe(tar.Parse()); - tarStream.on('error', callback); - return tarStream.on('entry', function(entry) { +function readFileFromTarStream(inputStream, archivePath, filePath, callback) { + const tar = require("tar"); + let tarStream = inputStream.pipe(tar.Parse()); + tarStream.on("error", callback); + + return tarStream.on("entry", function(entry) { if (filePath !== entry.props.path.replace(/\//g, path.sep)) { return; } - if (entry.props.type === '0') { + if (entry.props.type === "0") { return readEntry(entry, callback); } else { return callback(`${filePath} is not a normal file in the archive: ${archivePath}`); } }); -}; +} + +function readEntry(entry, callback) { + let contents = []; -readEntry = function(entry, callback) { - var contents; - contents = []; - entry.on('data', function(data) { + entry.on("data", function(data) { return contents.push(data); }); - return entry.on('end', function() { + + return entry.on("end", function() { return callback(null, Buffer.concat(contents)); }); -}; +} -isTarPath = function(archivePath) { - return path.extname(archivePath) === '.tar'; -}; +function isTarPath(archivePath) { + return path.extname(archivePath) === ".tar"; +} -isZipPath = function(archivePath) { - var extension; - extension = path.extname(archivePath); - return extension === '.epub' || extension === '.jar' || extension === '.love' || extension === '.war' || extension === '.zip' || extension === '.egg' || extension === '.whl' || extension === '.xpi' || extension === '.nupkg'; -}; +function isZipPath(archivePath) { + let ext = path.extname(archivePath); + let exts = [".epub", ".jar", ".love", ".war", ".zip", ".egg", ".whl", ".xpi", ".nupkg"]; + return exts.includes(ext); +} -isGzipPath = function(archivePath) { - return path.extname(archivePath) === '.tgz' || path.extname(path.basename(archivePath, '.gz')) === '.tar'; -}; +function isGzipPath(archivePath) { + return path.extname(archivePath) === ".tgz" || path.extname(path.basename(archivePath, ".gz")) === ".tar"; +} -isBzipPath = function(archivePath) { - return path.extname(archivePath) === '.tbz' || path.extname(archivePath) === '.tbz2' || path.extname(path.basename(archivePath, '.bz2')) === '.tar'; -}; +function isBzipPath(archivePath) { + return path.extname(archivePath) === ".tbz" || path.extname(archivePath) === ".tbz2" || path.extname(path.basename(archivePath, ".bz2")) === ".tar"; +} module.exports = { isPathSupported: function(archivePath) { @@ -354,35 +347,34 @@ module.exports = { return void 0; }, readGzip: function(gzipArchivePath, callback) { - var chunks, fileStream, gzipStream, zlib; callback = wrapCallback(callback); - zlib = require('zlib'); - fileStream = fs.createReadStream(gzipArchivePath); - fileStream.on('error', callback); - gzipStream = fileStream.pipe(zlib.createGunzip()); - gzipStream.on('error', callback); - chunks = []; - gzipStream.on('data', function(chunk) { + const zlib = require("zlib"); + let fileStream = fs.createReadStream(gzipArchivePath); + fileStream.on("error", callback); + let gzipStream = fileStream.pipe(zlib.createGunzip()); + gzipStream.on("error", callback); + let chunks = []; + + gzipStream.on("data", function(chunk) { return chunks.push(chunk); }); - return gzipStream.on('end', function() { + return gzipStream.on("end", function() { return callback(null, Buffer.concat(chunks)); }); }, readBzip: function(bzipArchivePath, callback) { - var bzip, bzipStream, chunks, fileStream; callback = wrapCallback(callback); - bzip = require('unbzip2-stream'); - fileStream = fs.createReadStream(bzipArchivePath); - fileStream.on('error', callback); - bzipStream = fileStream.pipe(bzip()); - bzipStream.on('error', callback); - chunks = []; - bzipStream.on('data', function(chunk) { + const bzip = require("unbzip2-stream"); + let fileStream = fs.createReadStream(bzipArchivePath); + fileStream.on("error", callback); + let bzipStream = fileStream.pipe(bzip()); + bzipStream.on("error", callback); + let chunks = []; + bzipStream.on("data", function(chunk) { return chunks.push(chunk); }); - return bzipStream.on('end', function() { + return bzipStream.on("end", function() { return callback(null, Buffer.concat(chunks)); }); - } + }, }; From 31bd0618c18d78b646fe9e55e7f1b271c8071f65 Mon Sep 17 00:00:00 2001 From: confused-Techie Date: Sat, 31 Jan 2026 17:54:59 -0800 Subject: [PATCH 5/6] Move all references `lib` => `src` --- bin/lsa | 2 +- package.json | 2 +- spec/bzip-spec.coffee | 8 ++++---- spec/common-spec.coffee | 2 +- spec/gzip-spec.coffee | 2 +- spec/tar-spec.coffee | 2 +- spec/zip-spec.coffee | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bin/lsa b/bin/lsa index 2730681..c7f4c58 100755 --- a/bin/lsa +++ b/bin/lsa @@ -1,3 +1,3 @@ #!/usr/bin/env node -require('../lib/ls-archive-cli')() +require('../src/ls-archive-cli')() diff --git a/package.json b/package.json index 49e8d60..2fbab8e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "url": "https://github.com/atom/node-ls-archive/issues" }, "homepage": "http://atom.github.io/node-ls-archive", - "main": "./lib/ls-archive.js", + "main": "./src/ls-archive.js", "bin": { "lsa": "./bin/lsa" }, diff --git a/spec/bzip-spec.coffee b/spec/bzip-spec.coffee index c7d0175..2012414 100644 --- a/spec/bzip-spec.coffee +++ b/spec/bzip-spec.coffee @@ -1,4 +1,4 @@ -archive = require '../lib/ls-archive' +archive = require '../src/ls-archive' path = require 'path' describe "bzipped tar files", -> @@ -32,7 +32,7 @@ describe "bzipped tar files", -> expect(bzipPaths[0].isDirectory()).toBe false expect(bzipPaths[0].isFile()).toBe true expect(bzipPaths[0].isSymbolicLink()).toBe false - + it "returns files in the bzipped tar archive", -> bzipPaths = null callback = (error, paths) -> bzipPaths = paths @@ -68,7 +68,7 @@ describe "bzipped tar files", -> expect(bzipPaths[0].isDirectory()).toBe true expect(bzipPaths[0].isFile()).toBe false expect(bzipPaths[0].isSymbolicLink()).toBe false - + it "returns folders in the bzipped tar archive", -> bzipPaths = null callback = (error, paths) -> bzipPaths = paths @@ -125,7 +125,7 @@ describe "bzipped tar files", -> archive.readFile(archivePath, 'file.txt', callback) waitsFor -> pathContents? runs -> expect(pathContents.toString()).toBe 'hello\n' - + it "calls back with the contents of the given path", -> archivePath = path.join(fixturesRoot, 'one-file.tbz2') pathContents = null diff --git a/spec/common-spec.coffee b/spec/common-spec.coffee index 56e1a49..ae49c2f 100644 --- a/spec/common-spec.coffee +++ b/spec/common-spec.coffee @@ -1,4 +1,4 @@ -archive = require '../lib/ls-archive' +archive = require '../src/ls-archive' path = require 'path' describe "Common behavior", -> diff --git a/spec/gzip-spec.coffee b/spec/gzip-spec.coffee index b59169c..5d4bcb7 100644 --- a/spec/gzip-spec.coffee +++ b/spec/gzip-spec.coffee @@ -1,4 +1,4 @@ -archive = require '../lib/ls-archive' +archive = require '../src/ls-archive' path = require 'path' describe "gzipped tar files", -> diff --git a/spec/tar-spec.coffee b/spec/tar-spec.coffee index c4aeaf6..50ffe4b 100644 --- a/spec/tar-spec.coffee +++ b/spec/tar-spec.coffee @@ -1,4 +1,4 @@ -archive = require '../lib/ls-archive' +archive = require '../src/ls-archive' path = require 'path' describe "tar files", -> diff --git a/spec/zip-spec.coffee b/spec/zip-spec.coffee index a331c83..a387a74 100644 --- a/spec/zip-spec.coffee +++ b/spec/zip-spec.coffee @@ -1,4 +1,4 @@ -archive = require '../lib/ls-archive' +archive = require '../src/ls-archive' path = require 'path' describe "zip files", -> From f4e96e6ea93648bfde8dbb8898b4e58377d6d7b1 Mon Sep 17 00:00:00 2001 From: confused_techie Date: Sun, 15 Feb 2026 21:41:06 -0800 Subject: [PATCH 6/6] Remove homepage URL from package.json after merging to main --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 1020687..1bc189b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "bugs": { "url": "https://github.com/pulsar-edit/node-ls-archive/issues" }, - "homepage": "http://atom.github.io/node-ls-archive", "main": "./src/ls-archive.js", "bin": { "lsa": "./bin/lsa"