Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add wip broken monstrosity targz * better, but still super idk man * uh, this actually made a file that winrar could open although the internal filepath was based on the full path from c:\ but this is promising. I still think things are done idiomatically wrong though. * add directory test and fixes * work off base directory resolution * add atomic shortcuts and tests * add more unit tests * fix type in Untar? * add gzip methods * I think this should be more efficient * simplify Tar * fix imports * utilize scan in targz * add some more types * lint * utilize _read * coverage fixes * remove state * reorg * obvious missed type, doesn't really effect anything though * so long as circulars aren't a problem, this should reduce dupe * fix failing test * better stage names * rewrite Untar and make progress * fix some names * still not correct, but probably moreso * added some state, and now it works but I don't think it should require state to do this * remove extra state * more tests, but trouble in checksum valley * it wasn't the checksum, it was empty directories now other tests are running, and other problems * fix? * add a test, yolo * coverage adjustments
- Loading branch information
Showing
32 changed files
with
958 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { createGunzip } from 'zlib'; | ||
|
||
import { createWriteStream, createReadStream } from '../fs'; | ||
import { pipelinePromise } from '../utils/util'; | ||
import gunzipAtomic from './gunzipAtomic'; | ||
|
||
/** | ||
* Un-Gzips a file | ||
* @function gunzip | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the output file | ||
* @param inputFile The filepath of the archive | ||
* @param atomic If the unzip file should be created atomically | ||
*/ | ||
export default async function gzip(fileName: string, inputFile: string, atomic: boolean = false): Promise<void> { | ||
if (atomic) return gunzipAtomic(fileName, inputFile); | ||
|
||
return pipelinePromise( | ||
createReadStream(inputFile), | ||
createGunzip(), | ||
createWriteStream(fileName) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import gunzip from './gunzip'; | ||
import move from './move'; | ||
import { tempFile } from '../utils/util'; | ||
|
||
/** | ||
* Un-Gzips a file atomically. | ||
* @function gunzipAtomic | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the output file | ||
* @param inputFile The filepath of the archive | ||
*/ | ||
export default async function gzipAtomic(fileName: string, inputFile: string): Promise<void> { | ||
const tempPath = tempFile(); | ||
await gunzip(tempPath, inputFile); | ||
return move(tempPath, fileName, { overwrite: true }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { createGzip } from 'zlib'; | ||
|
||
import { createWriteStream, createReadStream } from '../fs'; | ||
import { pipelinePromise } from '../utils/util'; | ||
import gzipAtomic from './gzipAtomic'; | ||
|
||
/** | ||
* Gzips a file | ||
* @function gzip | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the archive | ||
* @param inputFile The filepath of the input file | ||
* @param atomic If the gzip file should be created | ||
*/ | ||
export default async function gzip(fileName: string, inputFile: string, atomic: boolean = false): Promise<void> { | ||
if (atomic) return gzipAtomic(fileName, inputFile); | ||
|
||
return pipelinePromise( | ||
createReadStream(inputFile), | ||
createGzip(), | ||
createWriteStream(fileName) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import gzip from './gzip'; | ||
import move from './move'; | ||
import { tempFile } from '../utils/util'; | ||
|
||
/** | ||
* Gzips a file atomically. | ||
* @function gzipAtomic | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the archive | ||
* @param inputFile The filepath of the input file | ||
*/ | ||
export default async function gzipAtomic(fileName: string, inputFile: string): Promise<void> { | ||
const tempPath = tempFile(); | ||
await gzip(tempPath, inputFile); | ||
return move(tempPath, fileName, { overwrite: true }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { createGzip } from 'zlib'; | ||
|
||
import { createWriteStream } from '../fs'; | ||
import Tar from '../utils/Tar'; | ||
import { pipelinePromise } from '../utils/util'; | ||
import { dirname } from 'path'; | ||
import scan from './scan'; | ||
import targzAtomic from './targzAtomic'; | ||
|
||
|
||
/** | ||
* Tar/Gzips a directory or array of files. | ||
* @function targz | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the archive | ||
* @param inputFiles The directory or array of filepaths to .tar.gz | ||
* @param options The options for this .tar.gz | ||
*/ | ||
export default async function targz(fileName: string, inputFiles: string | string[], atomic: boolean = false): Promise<void> { | ||
if (atomic) return targzAtomic(fileName, inputFiles); | ||
if (!Array.isArray(inputFiles)) inputFiles = [inputFiles]; | ||
|
||
const tar = new Tar(dirname(inputFiles[0])); | ||
|
||
for (const input of inputFiles) { | ||
const files = await scan(input, { filter: stats => stats.isFile() }); | ||
for (const [file, stats] of files) tar.append(file, stats); | ||
} | ||
|
||
return pipelinePromise( | ||
tar, | ||
createGzip(), | ||
createWriteStream(fileName) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import targz from './targz'; | ||
import move from './move'; | ||
import { tempFile } from '../utils/util'; | ||
|
||
/** | ||
* Tar/Gzips a directory or array of files. | ||
* @function targzAtomic | ||
* @memberof fsn/nextra | ||
* @param fileName The filename of the archive | ||
* @param inputFiles The directory or array of filepaths to .tar.gz | ||
*/ | ||
export default async function targzAtomic(fileName: string, inputFiles: string | string[]): Promise<void> { | ||
const tempPath = tempFile(); | ||
await targz(tempPath, inputFiles); | ||
return move(tempPath, fileName, { overwrite: true }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { createGunzip } from 'zlib'; | ||
import { resolve } from 'path'; | ||
|
||
import { createReadStream } from '../fs'; | ||
import Untar from '../utils/Untar'; | ||
import outputFile from './outputFile'; | ||
import outputFileAtomic from './outputFileAtomic'; | ||
|
||
|
||
/** | ||
* Extracts files from .tar.gz archives. | ||
* @function unTargz | ||
* @memberof fsn/nextra | ||
* @param outputDirectory The directory to extract to | ||
* @param inputFile The archive file | ||
* @param atomic The if the writes should be atomic | ||
*/ | ||
export default async function unTargz(outputDirectory: string, inputFile: string, atomic: boolean = false): Promise<void> { | ||
const tar = createReadStream(inputFile).pipe(createGunzip()).pipe(new Untar()); | ||
const writeMethod = atomic ? outputFile : outputFileAtomic; | ||
|
||
for await (const { header, file } of tar.files()) await writeMethod(resolve(outputDirectory, header.filename), file); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import unTargz from './unTargz'; | ||
|
||
|
||
/** | ||
* Extracts files from .tar.gz archives and writes them atomically. | ||
* @function unTargzAtomic | ||
* @memberof fsn/nextra | ||
* @param outputDirectory The directory to extract to | ||
* @param inputFile The archive file | ||
* @param atomic The if the writes should be atomic | ||
*/ | ||
export default async function unTargzAtomic(outputDirectory: string, inputFile: string): Promise<void> { | ||
return unTargz(outputDirectory, inputFile, true); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { relative } from 'path'; | ||
import { Readable } from 'stream'; | ||
import { encodeHeader } from './header'; | ||
import { createReadStream, Stats } from '../fs'; | ||
|
||
export default class Tar extends Readable { | ||
|
||
private base: string; | ||
private written: number = 0; | ||
private recordSize = 512; | ||
private queue: Array<{ header: Buffer, file: Readable, size: number }> = []; | ||
|
||
public constructor(base: string) { | ||
super(); | ||
|
||
this.base = base; | ||
} | ||
|
||
public async _read(): Promise<void> { | ||
if (!this.queue.length) { | ||
this.push(null); | ||
return; | ||
} | ||
|
||
const { header, file, size } = this.queue.shift(); | ||
const { written } = this; | ||
|
||
this.written += header.length; | ||
|
||
const fileChunks = []; | ||
|
||
for await (const chunk of file) { | ||
fileChunks.push(chunk); | ||
this.written += chunk.length; | ||
} | ||
|
||
// Hard to produce, requires a size perfectibly divisible by the recordSize | ||
/* istanbul ignore next */ | ||
const extraBytes = this.recordSize - (size % this.recordSize || this.recordSize); | ||
this.written += extraBytes; | ||
|
||
this.push(Buffer.concat([header, ...fileChunks, Buffer.alloc(extraBytes)], this.written - written)); | ||
} | ||
|
||
public append(filepath: string, stats: Stats): void { | ||
this.queue.push({ | ||
header: encodeHeader({ | ||
filename: relative(this.base, filepath), | ||
mode: stats.mode, | ||
uid: stats.uid, | ||
gid: stats.gid, | ||
size: stats.size, | ||
mtime: Math.trunc(stats.mtime.valueOf() / 1000), | ||
type: '0', | ||
ustar: 'ustar ', | ||
owner: '', | ||
group: '' | ||
}), | ||
file: createReadStream(filepath), | ||
size: stats.size | ||
}); | ||
} | ||
|
||
} |
Oops, something went wrong.